- TypeScript 95.1%
- Nix 4.5%
- JavaScript 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| bin | ||
| nix | ||
| src | ||
| test | ||
| .gitignore | ||
| config.example.json | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| skill-extension-plan.md | ||
| tsconfig.json | ||
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.