Код
April 14, 2023

Гайд по написанию расширений для Джеффа

На данный момент у Джеффа есть набор примеров расширений и скриптов:

Папки с расширениями на GitHub: https://github.com/markcda/jeff/tree/master/extensions

Чтобы написать рабочее расширение для Джеффа, нужно:

  1. Написать код для общения расширения и Джеффа (потому что они общаются путём передачи JSON поверх обычных TCP-сокетов). Если вы пишете на Python, для вас уже всё сделали, для других ЯП пока ещё ничего нет.
  2. Написать конфигурационный файл extension.j.json. В минимальной комплектации он выглядит так:
    { "name": "some_name", "title": "Some title", "desc": "Some desc", "license": "Some Open-Source or some proprietary", "program": "/path/to/program" }
    В папках с расширениями полно примеров.
  3. Написать нужную вам логику.

Общение, как было упомянуто выше, происходит за счёт обмена информацией по TCP-протоколу. Расширение добавляется через диалоговое окно Джеффа и впоследствии стартует и завершается вместе с ним. Большинство расширений использует механизм аргументов для передачи портов сокетов:
"args": [ "alias-maker.py", "<SERVER_PORT>", "<JEFF_PORT>" ], "server_ip": "", "server_port": 23179
В итоге вместо <SERVER_PORT> подставится 23179, указанный ниже, а вместо <JEFF_PORT> подставится порт Джеффа, который можно изменять в настройках.

Не все расширения обязаны иметь сервер; напротив, некоторые могут только что-то отправлять в Джеффа и ничего от него не ждать. Например, так работает vosk-voice-input-daemon.

Какие возможности предоставляет Джефф для расширений?

  1. Внутренняя память.
    В Джеффе есть общее между всеми расширениями хранилище JSON-объектов.
    Вот так выглядит запрос на получение данных: {"memory_cells": ["needed_memory_cell_1", "needed_2", "needed_3_etc"]}
    - и на сохранение: {"store_in_memory": {"some_key": "some value, even decimal, double, boolean, object or array"}}.
    Причём по умолчанию каждый запуск три ячейки - jeff-lang, jeff-os, jeff-bundle-dir заполняются Джеффом.
  2. Получение сообщений.
    Если вы указали в файле конфигурации расширения, что у него есть сервер, это значит, что Джефф будет вам отправлять сообщения пользователя каждый раз, когда сам не сможет на них ответить. Если вы хотите всегда передавать ввод пользователя в расширение, добавьте в конфигурацию строчку "always_send": true.
  3. Отправка сообщений.
    Вот примеры JSON запросов на отправку:
    {"send": "какое-то сообщение на отправку"} {"send_as_user": "сообщение на отправку от лица пользователя"} {"send_info": "информация от расширения"} {"send_warning": "предупреждение"} {"send_status": {"id": "уникальный идентификатор обновляемого сообщения", "msg": "сообщение, которое может меняться со временем"}}
  4. Добавление выражений в базу данных.
    Делается это так:
    {"add_expr": [ { "activator_text": "пользовательский ввод", "reagent_text": "ответ Джеффа", "properties": {"какие-то свойства": "их значения",..}, "exec": false | true },.. ]}
  5. Эксклюзивное общение по сценарию.
    В сущности, сценарий представляет из себя способ взаимодействия, когда весь ввод пользователя без обработки перенаправляется в одно расширение. Джефф в этом смысле работает как паром.

Если у вас есть идеи расширений, или вы уже написали расширение и хотите им поделиться, пишите!