Архитектура интеграции 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:

typescript
import { 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:

typescript
import {
  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:

typescript
const 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_end
  • turn_start / turn_end
  • agent_start / agent_end
  • auto_compaction_start / auto_compaction_end

4. Промптинг

После настройки сессия получает промпт:

typescript
await session.prompt(effectivePrompt, { images: imageResult.images });

SDK обрабатывает полный цикл агента: отправку в LLM, выполнение вызовов инструментов, потоковые ответы.

Архитектура инструментов

Конвейер инструментов

  1. Базовые инструменты: codingTools pi (read, bash, edit, write)
  2. Пользовательские замены: Mayros заменяет bash на exec/process, настраивает read/edit/write для sandbox
  3. Инструменты Mayros: messaging, browser, canvas, sessions, cron, gateway и т.д.
  4. Инструменты каналов: Инструменты действий, специфичные для Discord/Telegram/Slack/WhatsApp
  5. Фильтрация по политике: Инструменты фильтруются по профилю, провайдеру, агенту, группе, политикам sandbox
  6. Нормализация схемы: Схемы очищаются для особенностей Gemini/OpenAI
  7. Обертка AbortSignal: Инструменты оборачиваются для учета сигналов прерывания

Адаптер определения инструмента

AgentTool pi-agent-core имеет другую сигнатуру execute, чем ToolDefinition pi-coding-agent. Адаптер в pi-tool-definition-adapter.ts соединяет это:

typescript
export 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:

typescript
export 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():

typescript
const systemPromptOverride = createSystemPromptOverride(appendPrompt);
applySystemPromptOverrideToSession(session, systemPromptOverride);

Управление сессиями

Файлы сессий

Сессии - это JSONL файлы с древовидной структурой (связывание id/parentId). SessionManager pi обрабатывает сохранение:

typescript
const sessionManager = SessionManager.open(params.sessionFile);

Mayros оборачивает это с помощью guardSessionManager() для безопасности результатов инструментов.

Кэширование сессий

session-manager-cache.ts кэширует экземпляры SessionManager, чтобы избежать повторного разбора файлов:

typescript
await prewarmSessionFile(params.sessionFile);
sessionManager = SessionManager.open(params.sessionFile);
trackSessionManagerAccess(params.sessionFile);

Ограничение истории

limitHistoryTurns() урезает историю разговора на основе типа канала (DM vs группа).

Уплотнение

Авто-уплотнение срабатывает при переполнении контекста. compactEmbeddedPiSessionDirect() обрабатывает ручное уплотнение:

typescript
const compactResult = await compactEmbeddedPiSessionDirect({
  sessionId, sessionFile, provider, model, ...
});

Аутентификация и разрешение моделей

Профили аутентификации

Mayros поддерживает хранилище профилей аутентификации с несколькими API ключами для каждого провайдера:

typescript
const authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });

Профили ротируются при сбоях с отслеживанием cooldown:

typescript
await markAuthProfileFailure({ store, profileId, reason, cfg, agentDir });
const rotated = await advanceAuthProfile();

Разрешение модели

typescript
import { 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 запускает откат модели, когда настроено:

typescript
if (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 добавляет защитные меры к уплотнению, включая адаптивный бюджет токенов плюс сбои инструментов и краткие описания файловых операций:

typescript
if (resolveCompactionMode(params.cfg) === "safeguard") {
  setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare });
  paths.push(resolvePiExtensionPath("compaction-safeguard"));
}

Обрезка контекста

pi-extensions/context-pruning.ts реализует обрезку контекста на основе cache-TTL:

typescript
if (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") {
  setContextPruningRuntime(params.sessionManager, {
    settings,
    contextWindowTokens,
    isToolPrunable,
    lastCacheTouchAt,
  });
  paths.push(resolvePiExtensionPath("context-pruning"));
}

Потоковая передача и блочные ответы

Разбиение блоков

EmbeddedBlockChunker управляет потоковой передачей текста в дискретные блоки ответов:

typescript
const blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;

Удаление тегов Thinking/Final

Потоковый вывод обрабатывается для удаления блоков <think>/<thinking> и извлечения содержимого <final>:

typescript
const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => {
  // Удалить содержимое <think>...</think>
  // Если enforceFinalTag, возвращать только содержимое <final>...</final>
};

Директивы ответа

Директивы ответа, такие как [[media:url]], [[voice]], [[reply:id]], разбираются и извлекаются:

typescript
const { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);

Обработка ошибок

Классификация ошибок

pi-embedded-helpers.ts классифицирует ошибки для соответствующей обработки:

typescript
isContextOverflowError(errorText)     // Контекст слишком большой
isCompactionFailureError(errorText)   // Уплотнение не удалось
isAuthAssistantError(lastAssistant)   // Ошибка аутентификации
isRateLimitAssistantError(...)        // Ограничение скорости
isFailoverAssistantError(...)         // Должен failover
classifyFailoverReason(errorText)     // "auth" | "rate_limit" | "quota" | "timeout" | ...

Откат уровня размышлений

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

typescript
const fallbackThinking = pickFallbackThinkingLevel({
  message: errorText,
  attempted: attemptedThinking,
});
if (fallbackThinking) {
  thinkLevel = fallbackThinking;
  continue;
}

Интеграция Sandbox

Когда режим sandbox включен, инструменты и пути ограничены:

typescript
const 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 CLIMayros встроенный
ВызовКоманда pi / RPCSDK через createAgentSession()
ИнструментыИнструменты кодирования по умолчаниюПользовательский набор инструментов Mayros
Системный промптAGENTS.md + промптыДинамический для каждого канала/контекста
Хранение сессий~/.pi/agent/sessions/~/.mayros/agents/<agentId>/sessions/ (или $MAYROS_STATE_DIR/agents/<agentId>/sessions/)
АутентификацияОдин набор учетных данныхМультипрофильная с ротацией
РасширенияЗагружаются с дискаПрограммные + пути на диске
Обработка событийРендеринг TUIНа основе коллбэков (onBlockReply и т.д.)

Будущие соображения

Области для потенциальной переработки:

  1. Выравнивание сигнатур инструментов: В настоящее время адаптация между сигнатурами pi-agent-core и pi-coding-agent
  2. Обертка менеджера сессий: guardSessionManager добавляет безопасность, но увеличивает сложность
  3. Загрузка расширений: Может более прямо использовать ResourceLoader pi
  4. Сложность обработчика потоковой передачи: subscribeEmbeddedPiSession сильно разросся
  5. Особенности провайдеров: Много кодовых путей, специфичных для провайдеров, которые pi потенциально мог бы обрабатывать

Тесты

Все существующие тесты, покрывающие интеграцию pi и ее расширения:

  • src/agents/pi-embedded-block-chunker.test.ts
  • src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts
  • src/agents/pi-embedded-helpers.classifyfailoverreason.test.ts
  • src/agents/pi-embedded-helpers.downgradeopenai-reasoning.test.ts
  • src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts
  • src/agents/pi-embedded-helpers.formatrawassistanterrorforui.test.ts
  • src/agents/pi-embedded-helpers.image-dimension-error.test.ts
  • src/agents/pi-embedded-helpers.image-size-error.test.ts
  • src/agents/pi-embedded-helpers.isautherrormessage.test.ts
  • src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts
  • src/agents/pi-embedded-helpers.iscloudcodeassistformaterror.test.ts
  • src/agents/pi-embedded-helpers.iscompactionfailureerror.test.ts
  • src/agents/pi-embedded-helpers.iscontextoverflowerror.test.ts
  • src/agents/pi-embedded-helpers.isfailovererrormessage.test.ts
  • src/agents/pi-embedded-helpers.islikelycontextoverflowerror.test.ts
  • src/agents/pi-embedded-helpers.ismessagingtoolduplicate.test.ts
  • src/agents/pi-embedded-helpers.messaging-duplicate.test.ts
  • src/agents/pi-embedded-helpers.normalizetextforcomparison.test.ts
  • src/agents/pi-embedded-helpers.resolvebootstrapmaxchars.test.ts
  • src/agents/pi-embedded-helpers.sanitize-session-messages-images.keeps-tool-call-tool-result-ids-unchanged.test.ts
  • src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.test.ts
  • src/agents/pi-embedded-helpers.sanitizegoogleturnordering.test.ts
  • src/agents/pi-embedded-helpers.sanitizesessionmessagesimages-thought-signature-stripping.test.ts
  • src/agents/pi-embedded-helpers.sanitizetoolcallid.test.ts
  • src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts
  • src/agents/pi-embedded-helpers.stripthoughtsignatures.test.ts
  • src/agents/pi-embedded-helpers.validate-turns.test.ts
  • src/agents/pi-embedded-runner-extraparams.live.test.ts (live)
  • src/agents/pi-embedded-runner-extraparams.test.ts
  • src/agents/pi-embedded-runner.applygoogleturnorderingfix.test.ts
  • src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts
  • src/agents/pi-embedded-runner.createsystempromptoverride.test.ts
  • src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.falls-back-provider-default-per-dm-not.test.ts
  • src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts
  • src/agents/pi-embedded-runner.google-sanitize-thinking.test.ts
  • src/agents/pi-embedded-runner.guard.test.ts
  • src/agents/pi-embedded-runner.limithistoryturns.test.ts
  • src/agents/pi-embedded-runner.resolvesessionagentids.test.ts
  • src/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.test.ts
  • src/agents/pi-embedded-runner.sanitize-session-history.test.ts
  • src/agents/pi-embedded-runner.splitsdktools.test.ts
  • src/agents/pi-embedded-runner.test.ts
  • src/agents/pi-embedded-subscribe.code-span-awareness.test.ts
  • src/agents/pi-embedded-subscribe.reply-tags.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.calls-onblockreplyflush-before-tool-execution-start-preserve.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-append-text-end-content-is.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-call-onblockreplyflush-callback-is-not.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-duplicate-text-end-repeats-full.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.includes-canvas-action-metadata-tool-summaries.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-indented-fenced-blocks-intact.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.reopens-fenced-blocks-splitting-inside-them.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.streams-soft-chunks-paragraph-preference.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.test.ts
  • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.ts
  • src/agents/pi-embedded-subscribe.tools.test.ts
  • src/agents/pi-embedded-utils.test.ts
  • src/agents/pi-extensions/compaction-safeguard.test.ts
  • src/agents/pi-extensions/context-pruning.test.ts
  • src/agents/pi-settings.test.ts
  • src/agents/pi-tool-definition-adapter.test.ts
  • src/agents/pi-tools-agent-config.test.ts
  • src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.ts
  • src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping-d.test.ts
  • src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping-f.test.ts
  • src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.ts
  • src/agents/pi-tools.policy.test.ts
  • src/agents/pi-tools.safe-bins.test.ts
  • src/agents/pi-tools.workspace-paths.test.ts