Архітектура інтеграції Pi

Цей документ описує, як Mayros інтегрується з pi-coding-agent та його сусідніми пакетами (pi-ai, pi-agent-core, pi-tui) для забезпечення можливостей AI-агента.

Огляд

Mayros використовує SDK pi для вбудовування AI-агента кодування в свою архітектуру шлюзу обміну повідомленнями. Замість створення pi як підпроцесу або використання режиму RPC, Mayros безпосередньо імпортує та створює екземпляр AgentSession pi через createAgentSession(). Цей вбудований підхід забезпечує:

  • Повний контроль над життєвим циклом сесії та обробкою подій
  • Власне впровадження інструментів (обмін повідомленнями, пісочниця, дії, специфічні для каналу)
  • Налаштування системної підказки для кожного каналу/контексту
  • Збереження сесії з підтримкою розгалуження/ущільнення
  • Ротація профілю автентифікації з кількома обліковими записами з аварійним переключенням
  • Перемикання моделі незалежно від провайдера

Залежності пакетів

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              # Впровадження зображень моделі зору
│   │   └── types.ts               # EmbeddedRunAttemptResult
│   ├── abort.ts                   # Виявлення помилки переривання
│   ├── cache-ttl.ts               # Відстеження TTL кешу для обрізання контексту
│   ├── compact.ts                 # Логіка ручного/автоматичного ущільнення
│   ├── extensions.ts              # Завантаження розширень pi для вбудованих запусків
│   ├── extra-params.ts            # Параметри потоку, специфічні для провайдера
│   ├── google.ts                  # Виправлення порядку ходів Google/Gemini
│   ├── history.ts                 # Обмеження історії (DM проти групи)
│   ├── lanes.ts                   # Командні доріжки сесії/глобальні
│   ├── logger.ts                  # Логер підсистеми
│   ├── model.ts                   # Розв'язання моделі через ModelRegistry
│   ├── runs.ts                    # Відстеження активних запусків, переривання, черга
│   ├── sandbox-info.ts            # Інформація про пісочницю для системної підказки
│   ├── 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       # Відстеження надісланих інструментів обміну повідомленнями
├── pi-embedded-helpers.ts         # Класифікація помилок, перевірка ходів
├── pi-embedded-helpers/           # Модулі помічників
├── pi-embedded-utils.ts           # Утиліти форматування
├── pi-tools.ts                    # createMayrosCodingTools()
├── pi-tools.abort.ts              # Обгортання AbortSignal для інструментів
├── pi-tools.policy.ts             # Політика списку дозволів/заборон інструментів
├── pi-tools.read.ts               # Налаштування інструменту читання
├── 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               # Сховище профілів, час очікування, аварійне переключення
├── 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/                       # Підсистема пісочниці
├── 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: "Привіт, як справи?",
  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 для пісочниці
  3. Інструменти Mayros: обмін повідомленнями, браузер, canvas, сесії, cron, шлюз тощо.
  4. Інструменти каналів: інструменти дій, специфічні для Discord/Telegram/Slack/WhatsApp
  5. Фільтрація політики: інструменти фільтруються за профілем, провайдером, агентом, групою, політиками пісочниці
  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, інтеграція пісочниці та розширений набір інструментів залишаються узгодженими між провайдерами.

Побудова системної підказки

Системна підказка будується в buildAgentSystemPrompt() (system-prompt.ts). Вона збирає повну підказку з розділами, включаючи Інструментарій, Стиль виклику інструментів, Захисні бар'єри безпеки, Довідник Mayros CLI, Навички, Документацію, Робочий простір, Пісочницю, Обмін повідомленнями, Теги відповіді, Голос, Тихі відповіді, Серцебиття, Метадані виконання, плюс Пам'ять та Реакції, коли ввімкнено, та необов'язкові файли контексту та додатковий вміст системної підказки. Розділи обрізаються для мінімального режиму підказки, що використовується підагентами.

Підказка застосовується після створення сесії через 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 проти групи).

Ущільнення

Автоматичне ущільнення спрацьовує при переповненні контексту. 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 });

Профілі обертаються при збоях з відстеженням часу очікування:

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);

Аварійне переключення

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;

Видалення тегів мислення/фінальних

Потоковий вивід обробляється для видалення блоків <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(...)         // Має бути аварійне переключення
classifyFailoverReason(errorText)     // "auth" | "rate_limit" | "quota" | "timeout" | ...

Резервний рівень мислення

Якщо рівень мислення не підтримується, він повертається:

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

Інтеграція пісочниці

Коли ввімкнено режим пісочниці, інструменти та шляхи обмежені:

typescript
const sandbox = await resolveSandboxContext({
  config: params.config,
  sessionKey: sandboxSessionKey,
  workspaceDir: resolvedWorkspace,
});

if (sandboxRoot) {
  // Використовувати інструменти read/edit/write у пісочниці
  // Exec виконується в контейнері
  // Браузер використовує 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 Embedded
ВикликКоманда 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