Personal AI secretary over a single Git workspace, powered by the Pi agent runtime.
  • TypeScript 95.1%
  • Nix 4.5%
  • JavaScript 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-02 16:07:08 +03:00
bin Initial commit 2026-09-02 16:02:55 +03:00
nix Initial commit 2026-09-02 16:02:55 +03:00
src Initial commit 2026-09-02 16:02:55 +03:00
test Initial commit 2026-09-02 16:02:55 +03:00
.gitignore Initial commit 2026-09-02 16:02:55 +03:00
config.example.json Initial commit 2026-09-02 16:02:55 +03:00
LICENSE Add GPL-3.0-only license and reference it in docs 2026-09-02 16:07:08 +03:00
package-lock.json Initial commit 2026-09-02 16:02:55 +03:00
package.json Add GPL-3.0-only license and reference it in docs 2026-09-02 16:07:08 +03:00
README.md Add GPL-3.0-only license and reference it in docs 2026-09-02 16:07:08 +03:00
skill-extension-plan.md Initial commit 2026-09-02 16:02:55 +03:00
tsconfig.json Initial commit 2026-09-02 16:02:55 +03:00

Personal Assistant

Персональный ИИ-секретарь с одним Git workspace. Сервер — единственный владелец Pi-сессии, модели, workspace и напоминаний. CLI и Matrix bridge — HTTP-клиенты.

Запуск

npm install
cp config.example.json config.json
npm run init-workspace -- config.json
SECRETARY_API_KEY='…' npm run serve -- config.json

workspaceRoot можно указать абсолютным путём или относительным путём от каталога конфигурационного файла. Если его не указать, workspace — каталог, содержащий конфиг; конфиг разрешено хранить в самом workspace. Workspace не должен пересекаться с репозиторием сервиса. Ключ модели можно задать как apiKey в JSON или через SECRETARY_API_KEY; переменная окружения имеет приоритет. Опциональный SECRETARY_BEARER_TOKEN защищает все API-запросы. SECRETARY_LOG_TOOL_CALLS=1 выводит в stderr имя, ID, аргументы и результат каждого вызова tool. Журнал может содержать приватные данные и секреты. По умолчанию сервер слушает 127.0.0.1:3000.

В отдельном терминале запускаются тонкие клиенты:

npm start -- --config config.json
MATRIX_ACCESS_TOKEN='…' npm run matrix -- config.json

CLI и Matrix bridge используют workspaceRoot только для локального служебного состояния; им не нужны ключ модели и её настройки.

Конфигурация

  • workspaceRoot — путь к Git workspace с пользовательскими данными. Абсолютный путь используется как есть, относительный разрешается от каталога config-файла. По умолчанию — каталог config-файла. Не может пересекаться с репозиторием сервиса; config-файл может находиться внутри workspace.
  • piResourcesRoot — необязательный путь к существующему каталогу ресурсов Pi, принадлежащему владельцу сервиса. Абсолютный путь используется как есть, относительный разрешается от каталога config-файла. По умолчанию используется <workspaceRoot>/.pi; если этого каталога нет, ресурсы Pi не загружаются. Он не должен пересекаться с репозиторием сервиса.
  • timezone — IANA timezone для дат и времени в prompt; по умолчанию timezone процесса.
  • apiBaseUrl — HTTP(S) endpoint OpenAI-совместимого API модели.
  • model — идентификатор модели у этого endpoint.
  • apiKey — ключ API модели; предпочтительно задавать через SECRETARY_API_KEY, который имеет приоритет.
  • contextWindow — размер контекстного окна модели в токенах.
  • supportsImages — может ли модель принимать изображения во входе.
  • serverHost, serverPort — интерфейс и порт, на которых слушает сам Secretary (127.0.0.1:3000 по умолчанию).
  • secretaryApiUrl — публичный URL Secretary для CLI и Matrix bridge. По умолчанию составляется из serverHost и serverPort; задаётся отдельно при reverse proxy.
  • terminalTurnRecordLimit — положительный лимит сохранённых завершённых идемпотентных запросов.
  • response.suppressToolNarration — не просить модель описывать промежуточное использование tools.
  • response.finalMessageOnly — возвращать клиенту только последнее сообщение assistant в turn.
  • response.showDiff — добавлять diff к успешному chat-ответу.
  • matrix содержит homeserver, userId, accessToken, roomId и необязательный secretaryApiUrl. MATRIX_ACCESS_TOKEN переопределяет matrix.accessToken.

Переменные окружения

Переменная Назначение
SECRETARY_API_KEY Ключ API модели для сервера. Имеет приоритет над apiKey из конфигурации.
SECRETARY_BEARER_TOKEN Токен защиты HTTP API. При задании клиенты CLI и Matrix передают его в Authorization: Bearer …; сервер требует этот заголовок для всех endpoints.
MATRIX_ACCESS_TOKEN Токен Matrix-клиента. Имеет приоритет над matrix.accessToken в конфигурации.
SECRETARY_LOG_TOOL_CALLS=1 Включает запись в stderr имени, ID, аргументов и результата каждого tool-вызова. Лог может содержать приватные данные и секреты.
RIPGREP_CONFIG_PATH Служебная переменная: при запуске сервис устанавливает её сам на файл .secretary/.ripgreprc workspace, чтобы grep не видел скрытые файлы. Вручную задавать её не требуется.

В piResourcesRoot сервис автоматически загружает только существующие подкаталоги extensions/ и skills/; их создавать не нужно. В extensions/ допустимы обычные Pi entry points (name.ts, name.js, name/index.ts или name/index.js) и Pi packages: пакет помещается непосредственным дочерним каталогом extensions/ и объявляет entry points в package.json через pi.extensions и pi.skills. Его зависимости должны быть установлены в самом пакете. Skills имеют вид skills/<name>/SKILL.md: в prompt попадают только имя и описание, а полный текст агент получает инструментом load_skill. Вспомогательные файлы skills не получают доступа вне workspace. Обычный discovery ресурсов workspace (.agents/, package-файлы и другие пути) отключён: загружается только явно заданный piResourcesRoot, в том числе когда это <workspaceRoot>/.pi.

Extensions — доверенный код владельца сервиса с полными правами процесса, поэтому piResourcesRoot не является защитной границей от вредоносного extension (в MVP также не проверяется дерево symlink extensions). Их зарегистрированные tools и обычные agent/tool hooks доступны автоматически. Extension commands, UI API, session_start и resources_discover не поддерживаются. Изменения ресурсов владельцем вступают в силу при reload на следующем turn.

История Pi сохраняется только в памяти и сбрасывается после рестарта сервера либо команды /new. Команда /commit фиксирует все незакоммиченные изменения workspace; если изменений нет, она ничего не делает. Долговременный контекст — файлы workspace, включая assistant/.

HTTP API

Если задан SECRETARY_BEARER_TOKEN, каждый endpoint требует Authorization: Bearer <token>.

  • POST /chat: тело { "message": "..." }, обязательный заголовок Idempotency-Key (1–200 печатных ASCII-символов без пробелов). Ответ: { "text", "commit" }, а при showDiff также diff.
  • POST /files: { "name", "contentBase64" } создаёт вложение в workspace.
  • GET /files/:id скачивает вложение.
  • GET /events?after=<id> возвращает упорядоченные notifications и будущие автономные события.

Повтор POST /chat с тем же ключом и тем же сообщением возвращает сохранённый HTTP-результат. Тот же ключ с иным сообщением возвращает 409.

Runtime state и уведомления

Служебное состояние хранится отдельно от пользовательских данных в <workspaceRoot>/.secretary/: runtime.json содержит идемпотентные turn records, напоминания и журнал событий; CLI и Matrix bridge сохраняют там свои cursors. Запись выполняется atomic replace. Каталог добавляется в .gitignore при инициализации workspace. Агенту недоступны все файлы и каталоги workspace, чьи имена начинаются с точки.

Инструменты schedule_notification, list_notifications, cancel_notification работают с общим набором напоминаний. При срабатывании появляется event; CLI выводит накопленные события только до и после пользовательского запроса, Matrix bridge опрашивает их в своём последовательном sync loop.

Git lifecycle

Перед turn workspace должен быть чистым. Успешные изменения коммитятся как Assistant update. Ошибочный agent turn очищается до HEAD командой git reset --hard HEAD и git clean -fd; игнорируемые пользовательские файлы не удаляются.

Проверки

npm run check
npm test

Лицензия

Проект распространяется по лицензии GPL-3.0-only.