Архитектура интеграции Pi
Этот документ описывает, как Mayros интегрируется с pi-coding-agent и его родственными пакетами (pi-ai, pi-agent-core, pi-tui) для обеспечения возможностей AI агента.
Обзор
Mayros использует SDK pi для встраивания AI агента программирования в свою архитектуру messaging gateway. Вместо запуска pi как подпроцесса или использования режима RPC, Mayros напрямую импортирует и создает экземпляр AgentSession pi через createAgentSession(). Этот встроенный подход обеспечивает:
- Полный контроль над жизненным циклом сессии и обработкой событий
- Внедрение пользовательских инструментов (messaging, sandbox, действия, специфичные для канала)
- Настройку системного промпта для каждого канала/контекста
- Сохранение сессий с поддержкой ветвления/уплотнения
- Ротация мультиаккаунтных профилей аутентификации с failover
- Независимое от провайдера переключение моделей
Зависимости пакетов
json{ "@mariozechner/pi-agent-core": "0.49.3", "@mariozechner/pi-ai": "0.49.3", "@mariozechner/pi-coding-agent": "0.49.3", "@mariozechner/pi-tui": "0.49.3" }
| Пакет | Назначение |
|---|---|
pi-ai | Основные абстракции LLM: Model, streamSimple, типы сообщений, API провайдеров |
pi-agent-core | Цикл агента, выполнение инструментов, типы AgentMessage |
pi-coding-agent | Высокоуровневый SDK: createAgentSession, SessionManager, AuthStorage, ModelRegistry, встроенные инструменты |
pi-tui | Компоненты терминального UI (используются в локальном режиме TUI Mayros) |
Структура файлов
src/agents/
├── pi-embedded-runner.ts # Реэкспорты из pi-embedded-runner/
├── pi-embedded-runner/
│ ├── run.ts # Основная точка входа: runEmbeddedPiAgent()
│ ├── run/
│ │ ├── attempt.ts # Логика одной попытки с настройкой сессии
│ │ ├── params.ts # Тип RunEmbeddedPiAgentParams
│ │ ├── payloads.ts # Построение полезных нагрузок ответа из результатов запуска
│ │ ├── images.ts # Внедрение изображений в модель с поддержкой vision
│ │ └── types.ts # EmbeddedRunAttemptResult
│ ├── abort.ts # Определение ошибки прерывания
│ ├── cache-ttl.ts # Отслеживание TTL кэша для обрезки контекста
│ ├── compact.ts # Логика ручного/авто уплотнения
│ ├── extensions.ts # Загрузка расширений pi для встроенных запусков
│ ├── extra-params.ts # Параметры потока, специфичные для провайдера
│ ├── google.ts # Исправления порядка ходов Google/Gemini
│ ├── history.ts # Ограничение истории (DM vs группа)
│ ├── lanes.ts # Полосы команд сессии/глобальные
│ ├── logger.ts # Логгер подсистемы
│ ├── model.ts # Разрешение модели через ModelRegistry
│ ├── runs.ts # Отслеживание активных запусков, прерывание, очередь
│ ├── sandbox-info.ts # Информация sandbox для системного промпта
│ ├── session-manager-cache.ts # Кэширование экземпляров SessionManager
│ ├── session-manager-init.ts # Инициализация файла сессии
│ ├── system-prompt.ts # Построитель системного промпта
│ ├── tool-split.ts # Разделение инструментов на builtIn vs custom
│ ├── types.ts # EmbeddedPiAgentMeta, EmbeddedPiRunResult
│ └── utils.ts # Маппинг ThinkLevel, описание ошибок
├── pi-embedded-subscribe.ts # Подписка/отправка событий сессии
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # Фабрика обработчиков событий
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts # Разбиение потоковых блоков ответа на части
├── pi-embedded-messaging.ts # Отслеживание отправленных messaging инструментов
├── pi-embedded-helpers.ts # Классификация ошибок, валидация ходов
├── pi-embedded-helpers/ # Модули помощников
├── pi-embedded-utils.ts # Утилиты форматирования
├── pi-tools.ts # createMayrosCodingTools()
├── pi-tools.abort.ts # Обертка AbortSignal для инструментов
├── pi-tools.policy.ts # Политика allowlist/denylist инструментов
├── pi-tools.read.ts # Настройки инструмента Read
├── pi-tools.schema.ts # Нормализация схемы инструментов
├── pi-tools.types.ts # Псевдоним типа AnyAgentTool
├── pi-tool-definition-adapter.ts # Адаптер AgentTool -> ToolDefinition
├── pi-settings.ts # Переопределения настроек
├── pi-extensions/ # Пользовательские расширения pi
│ ├── compaction-safeguard.ts # Расширение защиты
│ ├── compaction-safeguard-runtime.ts
│ ├── context-pruning.ts # Расширение обрезки контекста Cache-TTL
│ └── context-pruning/
├── model-auth.ts # Разрешение профиля аутентификации
├── auth-profiles.ts # Хранилище профилей, cooldown, failover
├── model-selection.ts # Разрешение модели по умолчанию
├── models-config.ts # Генерация models.json
├── model-catalog.ts # Кэш каталога моделей
├── context-window-guard.ts # Валидация окна контекста
├── failover-error.ts # Класс FailoverError
├── defaults.ts # DEFAULT_PROVIDER, DEFAULT_MODEL
├── system-prompt.ts # buildAgentSystemPrompt()
├── system-prompt-params.ts # Разрешение параметров системного промпта
├── system-prompt-report.ts # Генерация отчета отладки
├── tool-summaries.ts # Краткие описания инструментов
├── tool-policy.ts # Разрешение политики инструментов
├── transcript-policy.ts # Политика валидации транскрипта
├── skills.ts # Построение снимка/промпта навыков
├── skills/ # Подсистема навыков
├── sandbox.ts # Разрешение контекста sandbox
├── sandbox/ # Подсистема sandbox
├── channel-tools.ts # Внедрение инструментов, специфичных для канала
├── mayros-tools.ts # Инструменты, специфичные для Mayros
├── bash-tools.ts # Инструменты exec/process
├── apply-patch.ts # Инструмент apply_patch (OpenAI)
├── tools/ # Реализации отдельных инструментов
│ ├── browser-tool.ts
│ ├── canvas-tool.ts
│ ├── cron-tool.ts
│ ├── discord-actions*.ts
│ ├── gateway-tool.ts
│ ├── image-tool.ts
│ ├── message-tool.ts
│ ├── nodes-tool.ts
│ ├── session*.ts
│ ├── slack-actions.ts
│ ├── telegram-actions.ts
│ ├── web-*.ts
│ └── whatsapp-actions.ts
└── ...
Основной поток интеграции
1. Запуск встроенного агента
Основная точка входа - runEmbeddedPiAgent() в pi-embedded-runner/run.ts:
typescriptimport { runEmbeddedPiAgent } from "./agents/pi-embedded-runner.js"; const result = await runEmbeddedPiAgent({ sessionId: "user-123", sessionKey: "main:whatsapp:+1234567890", sessionFile: "/path/to/session.jsonl", workspaceDir: "/path/to/workspace", config: mayrosConfig, prompt: "Hello, how are you?", provider: "anthropic", model: "claude-sonnet-4-20250514", timeoutMs: 120_000, runId: "run-abc", onBlockReply: async (payload) => { await sendToChannel(payload.text, payload.mediaUrls); }, });
2. Создание сессии
Внутри runEmbeddedAttempt() (вызывается runEmbeddedPiAgent()), используется SDK pi:
typescriptimport { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent"; const resourceLoader = new DefaultResourceLoader({ cwd: resolvedWorkspace, agentDir, settingsManager, additionalExtensionPaths, }); await resourceLoader.reload(); const { session } = await createAgentSession({ cwd: resolvedWorkspace, agentDir, authStorage: params.authStorage, modelRegistry: params.modelRegistry, model: params.model, thinkingLevel: mapThinkingLevel(params.thinkLevel), tools: builtInTools, customTools: allCustomTools, sessionManager, settingsManager, resourceLoader, }); applySystemPromptOverrideToSession(session, systemPromptOverride);
3. Подписка на события
subscribeEmbeddedPiSession() подписывается на события AgentSession pi:
typescriptconst subscription = subscribeEmbeddedPiSession({ session: activeSession, runId: params.runId, verboseLevel: params.verboseLevel, reasoningMode: params.reasoningLevel, toolResultFormat: params.toolResultFormat, onToolResult: params.onToolResult, onReasoningStream: params.onReasoningStream, onBlockReply: params.onBlockReply, onPartialReply: params.onPartialReply, onAgentEvent: params.onAgentEvent, });
Обрабатываемые события включают:
message_start/message_end/message_update(потоковый текст/размышления)tool_execution_start/tool_execution_update/tool_execution_endturn_start/turn_endagent_start/agent_endauto_compaction_start/auto_compaction_end
4. Промптинг
После настройки сессия получает промпт:
typescriptawait session.prompt(effectivePrompt, { images: imageResult.images });
SDK обрабатывает полный цикл агента: отправку в LLM, выполнение вызовов инструментов, потоковые ответы.
Архитектура инструментов
Конвейер инструментов
- Базовые инструменты:
codingToolspi (read, bash, edit, write) - Пользовательские замены: Mayros заменяет bash на
exec/process, настраивает read/edit/write для sandbox - Инструменты Mayros: messaging, browser, canvas, sessions, cron, gateway и т.д.
- Инструменты каналов: Инструменты действий, специфичные для Discord/Telegram/Slack/WhatsApp
- Фильтрация по политике: Инструменты фильтруются по профилю, провайдеру, агенту, группе, политикам sandbox
- Нормализация схемы: Схемы очищаются для особенностей Gemini/OpenAI
- Обертка AbortSignal: Инструменты оборачиваются для учета сигналов прерывания
Адаптер определения инструмента
AgentTool pi-agent-core имеет другую сигнатуру execute, чем ToolDefinition pi-coding-agent. Адаптер в pi-tool-definition-adapter.ts соединяет это:
typescriptexport function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] { return tools.map((tool) => ({ name: tool.name, label: tool.label ?? name, description: tool.description ?? "", parameters: tool.parameters, execute: async (toolCallId, params, onUpdate, _ctx, signal) => { // Сигнатура pi-coding-agent отличается от pi-agent-core return await tool.execute(toolCallId, params, signal, onUpdate); }, })); }
Стратегия разделения инструментов
splitSdkTools() передает все инструменты через customTools:
typescriptexport function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) { return { builtInTools: [], // Пусто. Мы переопределяем все customTools: toToolDefinitions(options.tools), }; }
Это обеспечивает согласованность фильтрации политик Mayros, интеграции sandbox и расширенного набора инструментов между провайдерами.
Конструирование системного промпта
Системный промпт строится в buildAgentSystemPrompt() (system-prompt.ts). Он собирает полный промпт с секциями, включая Tooling, Tool Call Style, защитные меры Safety, справочник Mayros CLI, Skills, Docs, Workspace, Sandbox, Messaging, Reply Tags, Voice, Silent Replies, Heartbeats, метаданные Runtime, плюс Memory и Reactions, когда включено, и опциональные файлы контекста и дополнительное содержимое системного промпта. Секции урезаются для минимального режима промпта, используемого подагентами.
Промпт применяется после создания сессии через applySystemPromptOverrideToSession():
typescriptconst systemPromptOverride = createSystemPromptOverride(appendPrompt); applySystemPromptOverrideToSession(session, systemPromptOverride);
Управление сессиями
Файлы сессий
Сессии - это JSONL файлы с древовидной структурой (связывание id/parentId). SessionManager pi обрабатывает сохранение:
typescriptconst sessionManager = SessionManager.open(params.sessionFile);
Mayros оборачивает это с помощью guardSessionManager() для безопасности результатов инструментов.
Кэширование сессий
session-manager-cache.ts кэширует экземпляры SessionManager, чтобы избежать повторного разбора файлов:
typescriptawait prewarmSessionFile(params.sessionFile); sessionManager = SessionManager.open(params.sessionFile); trackSessionManagerAccess(params.sessionFile);
Ограничение истории
limitHistoryTurns() урезает историю разговора на основе типа канала (DM vs группа).
Уплотнение
Авто-уплотнение срабатывает при переполнении контекста. compactEmbeddedPiSessionDirect() обрабатывает ручное уплотнение:
typescriptconst compactResult = await compactEmbeddedPiSessionDirect({ sessionId, sessionFile, provider, model, ... });
Аутентификация и разрешение моделей
Профили аутентификации
Mayros поддерживает хранилище профилей аутентификации с несколькими API ключами для каждого провайдера:
typescriptconst authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
Профили ротируются при сбоях с отслеживанием cooldown:
typescriptawait markAuthProfileFailure({ store, profileId, reason, cfg, agentDir }); const rotated = await advanceAuthProfile();
Разрешение модели
typescriptimport { resolveModel } from "./pi-embedded-runner/model.js"; const { model, error, authStorage, modelRegistry } = resolveModel( provider, modelId, agentDir, config, ); // Использует ModelRegistry и AuthStorage pi authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);
Failover
FailoverError запускает откат модели, когда настроено:
typescriptif (fallbackConfigured && isFailoverErrorMessage(errorText)) { throw new FailoverError(errorText, { reason: promptFailoverReason ?? "unknown", provider, model: modelId, profileId, status: resolveFailoverStatus(promptFailoverReason), }); }
Расширения Pi
Mayros загружает пользовательские расширения pi для специализированного поведения:
Защита уплотнения
pi-extensions/compaction-safeguard.ts добавляет защитные меры к уплотнению, включая адаптивный бюджет токенов плюс сбои инструментов и краткие описания файловых операций:
typescriptif (resolveCompactionMode(params.cfg) === "safeguard") { setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare }); paths.push(resolvePiExtensionPath("compaction-safeguard")); }
Обрезка контекста
pi-extensions/context-pruning.ts реализует обрезку контекста на основе cache-TTL:
typescriptif (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") { setContextPruningRuntime(params.sessionManager, { settings, contextWindowTokens, isToolPrunable, lastCacheTouchAt, }); paths.push(resolvePiExtensionPath("context-pruning")); }
Потоковая передача и блочные ответы
Разбиение блоков
EmbeddedBlockChunker управляет потоковой передачей текста в дискретные блоки ответов:
typescriptconst blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
Удаление тегов Thinking/Final
Потоковый вывод обрабатывается для удаления блоков <think>/<thinking> и извлечения содержимого <final>:
typescriptconst stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => { // Удалить содержимое <think>...</think> // Если enforceFinalTag, возвращать только содержимое <final>...</final> };
Директивы ответа
Директивы ответа, такие как [[media:url]], [[voice]], [[reply:id]], разбираются и извлекаются:
typescriptconst { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
Обработка ошибок
Классификация ошибок
pi-embedded-helpers.ts классифицирует ошибки для соответствующей обработки:
typescriptisContextOverflowError(errorText) // Контекст слишком большой isCompactionFailureError(errorText) // Уплотнение не удалось isAuthAssistantError(lastAssistant) // Ошибка аутентификации isRateLimitAssistantError(...) // Ограничение скорости isFailoverAssistantError(...) // Должен failover classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
Откат уровня размышлений
Если уровень размышлений не поддерживается, происходит откат:
typescriptconst fallbackThinking = pickFallbackThinkingLevel({ message: errorText, attempted: attemptedThinking, }); if (fallbackThinking) { thinkLevel = fallbackThinking; continue; }
Интеграция Sandbox
Когда режим sandbox включен, инструменты и пути ограничены:
typescriptconst sandbox = await resolveSandboxContext({ config: params.config, sessionKey: sandboxSessionKey, workspaceDir: resolvedWorkspace, }); if (sandboxRoot) { // Использовать инструменты read/edit/write в sandbox // Exec работает в контейнере // Browser использует bridge URL }
Обработка, специфичная для провайдера
Anthropic
- Очистка магической строки отказа
- Валидация ходов для последовательных ролей
- Совместимость параметров Claude Code
Google/Gemini
- Исправления порядка ходов (
applyGoogleTurnOrderingFix) - Санитизация схемы инструментов (
sanitizeToolsForGoogle) - Санитизация истории сессий (
sanitizeSessionHistory)
OpenAI
- Инструмент
apply_patchдля моделей Codex - Обработка понижения уровня размышлений
Интеграция TUI
Mayros также имеет локальный режим TUI, который напрямую использует компоненты pi-tui:
typescript// src/tui/tui.ts import { ... } from "@mariozechner/pi-tui";
Это обеспечивает интерактивный терминальный опыт, аналогичный нативному режиму pi.
Ключевые отличия от Pi CLI
| Аспект | Pi CLI | Mayros встроенный |
|---|---|---|
| Вызов | Команда pi / RPC | SDK через createAgentSession() |
| Инструменты | Инструменты кодирования по умолчанию | Пользовательский набор инструментов Mayros |
| Системный промпт | AGENTS.md + промпты | Динамический для каждого канала/контекста |
| Хранение сессий | ~/.pi/agent/sessions/ | ~/.mayros/agents/<agentId>/sessions/ (или $MAYROS_STATE_DIR/agents/<agentId>/sessions/) |
| Аутентификация | Один набор учетных данных | Мультипрофильная с ротацией |
| Расширения | Загружаются с диска | Программные + пути на диске |
| Обработка событий | Рендеринг TUI | На основе коллбэков (onBlockReply и т.д.) |
Будущие соображения
Области для потенциальной переработки:
- Выравнивание сигнатур инструментов: В настоящее время адаптация между сигнатурами pi-agent-core и pi-coding-agent
- Обертка менеджера сессий:
guardSessionManagerдобавляет безопасность, но увеличивает сложность - Загрузка расширений: Может более прямо использовать
ResourceLoaderpi - Сложность обработчика потоковой передачи:
subscribeEmbeddedPiSessionсильно разросся - Особенности провайдеров: Много кодовых путей, специфичных для провайдеров, которые pi потенциально мог бы обрабатывать
Тесты
Все существующие тесты, покрывающие интеграцию pi и ее расширения:
src/agents/pi-embedded-block-chunker.test.tssrc/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.tssrc/agents/pi-embedded-helpers.classifyfailoverreason.test.tssrc/agents/pi-embedded-helpers.downgradeopenai-reasoning.test.tssrc/agents/pi-embedded-helpers.formatassistanterrortext.test.tssrc/agents/pi-embedded-helpers.formatrawassistanterrorforui.test.tssrc/agents/pi-embedded-helpers.image-dimension-error.test.tssrc/agents/pi-embedded-helpers.image-size-error.test.tssrc/agents/pi-embedded-helpers.isautherrormessage.test.tssrc/agents/pi-embedded-helpers.isbillingerrormessage.test.tssrc/agents/pi-embedded-helpers.iscloudcodeassistformaterror.test.tssrc/agents/pi-embedded-helpers.iscompactionfailureerror.test.tssrc/agents/pi-embedded-helpers.iscontextoverflowerror.test.tssrc/agents/pi-embedded-helpers.isfailovererrormessage.test.tssrc/agents/pi-embedded-helpers.islikelycontextoverflowerror.test.tssrc/agents/pi-embedded-helpers.ismessagingtoolduplicate.test.tssrc/agents/pi-embedded-helpers.messaging-duplicate.test.tssrc/agents/pi-embedded-helpers.normalizetextforcomparison.test.tssrc/agents/pi-embedded-helpers.resolvebootstrapmaxchars.test.tssrc/agents/pi-embedded-helpers.sanitize-session-messages-images.keeps-tool-call-tool-result-ids-unchanged.test.tssrc/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.test.tssrc/agents/pi-embedded-helpers.sanitizegoogleturnordering.test.tssrc/agents/pi-embedded-helpers.sanitizesessionmessagesimages-thought-signature-stripping.test.tssrc/agents/pi-embedded-helpers.sanitizetoolcallid.test.tssrc/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.tssrc/agents/pi-embedded-helpers.stripthoughtsignatures.test.tssrc/agents/pi-embedded-helpers.validate-turns.test.tssrc/agents/pi-embedded-runner-extraparams.live.test.ts(live)src/agents/pi-embedded-runner-extraparams.test.tssrc/agents/pi-embedded-runner.applygoogleturnorderingfix.test.tssrc/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.tssrc/agents/pi-embedded-runner.createsystempromptoverride.test.tssrc/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.falls-back-provider-default-per-dm-not.test.tssrc/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.tssrc/agents/pi-embedded-runner.google-sanitize-thinking.test.tssrc/agents/pi-embedded-runner.guard.test.tssrc/agents/pi-embedded-runner.limithistoryturns.test.tssrc/agents/pi-embedded-runner.resolvesessionagentids.test.tssrc/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.test.tssrc/agents/pi-embedded-runner.sanitize-session-history.test.tssrc/agents/pi-embedded-runner.splitsdktools.test.tssrc/agents/pi-embedded-runner.test.tssrc/agents/pi-embedded-subscribe.code-span-awareness.test.tssrc/agents/pi-embedded-subscribe.reply-tags.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.calls-onblockreplyflush-before-tool-execution-start-preserve.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-append-text-end-content-is.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-call-onblockreplyflush-callback-is-not.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-duplicate-text-end-repeats-full.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.includes-canvas-action-metadata-tool-summaries.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-indented-fenced-blocks-intact.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.reopens-fenced-blocks-splitting-inside-them.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.streams-soft-chunks-paragraph-preference.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.test.tssrc/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.tssrc/agents/pi-embedded-subscribe.tools.test.tssrc/agents/pi-embedded-utils.test.tssrc/agents/pi-extensions/compaction-safeguard.test.tssrc/agents/pi-extensions/context-pruning.test.tssrc/agents/pi-settings.test.tssrc/agents/pi-tool-definition-adapter.test.tssrc/agents/pi-tools-agent-config.test.tssrc/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.tssrc/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping-d.test.tssrc/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping-f.test.tssrc/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.tssrc/agents/pi-tools.policy.test.tssrc/agents/pi-tools.safe-bins.test.tssrc/agents/pi-tools.workspace-paths.test.ts