Arquitetura de Integração Pi
Este documento descreve como o Mayros se integra com pi-coding-agent e seus pacotes irmãos (pi-ai, pi-agent-core, pi-tui) para potencializar suas capacidades de agente de IA.
Visão geral
Mayros usa o SDK pi para incorporar um agente de codificação de IA em sua arquitetura de gateway de mensagens. Em vez de gerar pi como um subprocesso ou usar modo RPC, Mayros importa e instancia diretamente o AgentSession do pi via createAgentSession(). Esta abordagem incorporada fornece:
- Controle total sobre ciclo de vida de sessão e tratamento de eventos
- Injeção de ferramenta personalizada (mensagens, sandbox, ações específicas de canal)
- Personalização de prompt do sistema por canal/contexto
- Persistência de sessão com suporte a ramificação/compactação
- Rotação de perfil de autenticação multi-conta com failover
- Troca de modelo agnóstica de provedor
Dependências de Pacote
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" }
| Pacote | Propósito |
|---|---|
pi-ai | Abstrações LLM principais: Model, streamSimple, tipos de mensagem, APIs de provedor |
pi-agent-core | Loop de agente, execução de ferramenta, tipos AgentMessage |
pi-coding-agent | SDK de alto nível: createAgentSession, SessionManager, AuthStorage, ModelRegistry, ferramentas integradas |
pi-tui | Componentes de UI de terminal (usado no modo TUI local do Mayros) |
Estrutura de Arquivo
src/agents/
├── pi-embedded-runner.ts # Re-exporta de pi-embedded-runner/
├── pi-embedded-runner/
│ ├── run.ts # Entrada principal: runEmbeddedPiAgent()
│ ├── run/
│ │ ├── attempt.ts # Lógica de tentativa única com configuração de sessão
│ │ ├── params.ts # Tipo RunEmbeddedPiAgentParams
│ │ ├── payloads.ts # Construir payloads de resposta de resultados de execução
│ │ ├── images.ts # Injeção de imagem de modelo de visão
│ │ └── types.ts # EmbeddedRunAttemptResult
│ ├── abort.ts # Detecção de erro de aborto
│ ├── cache-ttl.ts # Rastreamento de TTL de cache para poda de contexto
│ ├── compact.ts # Lógica de compactação manual/auto
│ ├── extensions.ts # Carregar extensões pi para execuções incorporadas
│ ├── extra-params.ts # Parâmetros de stream específicos do provedor
│ ├── google.ts # Correções de ordenação de turno Google/Gemini
│ ├── history.ts # Limitação de histórico (DM vs grupo)
│ ├── lanes.ts # Lanes de comando de sessão/global
│ ├── logger.ts # Logger de subsistema
│ ├── model.ts # Resolução de modelo via ModelRegistry
│ ├── runs.ts # Rastreamento de execução ativa, abortar, fila
│ ├── sandbox-info.ts # Info de sandbox para prompt do sistema
│ ├── session-manager-cache.ts # Cache de instância SessionManager
│ ├── session-manager-init.ts # Inicialização de arquivo de sessão
│ ├── system-prompt.ts # Construtor de prompt do sistema
│ ├── tool-split.ts # Dividir ferramentas em builtIn vs custom
│ ├── types.ts # EmbeddedPiAgentMeta, EmbeddedPiRunResult
│ └── utils.ts # Mapeamento ThinkLevel, descrição de erro
├── pi-embedded-subscribe.ts # Subscrição/despacho de evento de sessão
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # Fábrica de handler de evento
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts # Chunking de resposta de bloco de streaming
├── pi-embedded-messaging.ts # Rastreamento de ferramenta de mensagem enviada
├── pi-embedded-helpers.ts # Classificação de erro, validação de turno
├── pi-embedded-helpers/ # Módulos auxiliares
├── pi-embedded-utils.ts # Utilitários de formatação
├── pi-tools.ts # createMayrosCodingTools()
├── pi-tools.abort.ts # Envolvimento AbortSignal para ferramentas
├── pi-tools.policy.ts # Política de lista de permissões/negação de ferramenta
├── pi-tools.read.ts # Personalizações de ferramenta de leitura
├── pi-tools.schema.ts # Normalização de schema de ferramenta
├── pi-tools.types.ts # Alias de tipo AnyAgentTool
├── pi-tool-definition-adapter.ts # Adaptador AgentTool -> ToolDefinition
├── pi-settings.ts # Substituições de configurações
├── pi-extensions/ # Extensões pi personalizadas
│ ├── compaction-safeguard.ts # Extensão Safeguard
│ ├── compaction-safeguard-runtime.ts
│ ├── context-pruning.ts # Extensão de poda de contexto Cache-TTL
│ └── context-pruning/
├── model-auth.ts # Resolução de perfil de autenticação
├── auth-profiles.ts # Armazenamento de perfil, cooldown, failover
├── model-selection.ts # Resolução de modelo padrão
├── models-config.ts # Geração models.json
├── model-catalog.ts # Cache de catálogo de modelo
├── context-window-guard.ts # Validação de janela de contexto
├── failover-error.ts # Classe FailoverError
├── defaults.ts # DEFAULT_PROVIDER, DEFAULT_MODEL
├── system-prompt.ts # buildAgentSystemPrompt()
├── system-prompt-params.ts # Resolução de parâmetro de prompt do sistema
├── system-prompt-report.ts # Geração de relatório de depuração
├── tool-summaries.ts # Resumos de descrição de ferramenta
├── tool-policy.ts # Resolução de política de ferramenta
├── transcript-policy.ts # Política de validação de transcrição
├── skills.ts # Snapshot/construção de prompt de skill
├── skills/ # Subsistema de skill
├── sandbox.ts # Resolução de contexto de sandbox
├── sandbox/ # Subsistema de sandbox
├── channel-tools.ts # Injeção de ferramenta específica de canal
├── mayros-tools.ts # Ferramentas específicas do Mayros
├── bash-tools.ts # Ferramentas exec/process
├── apply-patch.ts # Ferramenta apply_patch (OpenAI)
├── tools/ # Implementações de ferramenta individuais
│ ├── 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
└── ...
Fluxo de Integração Principal
1. Executando um Agente Incorporado
O ponto de entrada principal é runEmbeddedPiAgent() em 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: "Olá, como você está?", provider: "anthropic", model: "claude-sonnet-4-20250514", timeoutMs: 120_000, runId: "run-abc", onBlockReply: async (payload) => { await sendToChannel(payload.text, payload.mediaUrls); }, });
2. Criação de Sessão
Dentro de runEmbeddedAttempt() (chamado por runEmbeddedPiAgent()), o SDK pi é usado:
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. Subscrição de Evento
subscribeEmbeddedPiSession() subscreve aos eventos AgentSession do 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, });
Eventos tratados incluem:
message_start/message_end/message_update(streaming de texto/pensamento)tool_execution_start/tool_execution_update/tool_execution_endturn_start/turn_endagent_start/agent_endauto_compaction_start/auto_compaction_end
4. Prompting
Após a configuração, a sessão é solicitada:
typescriptawait session.prompt(effectivePrompt, { images: imageResult.images });
O SDK trata o loop completo do agente: enviando para LLM, executando chamadas de ferramenta, streaming de respostas.
Arquitetura de Ferramenta
Pipeline de Ferramenta
- Ferramentas Base:
codingToolsdo pi (read, bash, edit, write) - Substituições Personalizadas: Mayros substitui bash por
exec/process, personaliza read/edit/write para sandbox - Ferramentas Mayros: messaging, browser, canvas, sessions, cron, gateway, etc.
- Ferramentas de Canal: Ferramentas de ação específicas de Discord/Telegram/Slack/WhatsApp
- Filtragem de Política: Ferramentas filtradas por perfil, provedor, agente, grupo, políticas de sandbox
- Normalização de Schema: Schemas limpos para peculiaridades Gemini/OpenAI
- Envolvimento AbortSignal: Ferramentas envolvidas para respeitar sinais de aborto
Adaptador de Definição de Ferramenta
AgentTool do pi-agent-core tem uma assinatura execute diferente do ToolDefinition do pi-coding-agent. O adaptador em pi-tool-definition-adapter.ts conecta isso:
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) => { // Assinatura pi-coding-agent difere de pi-agent-core return await tool.execute(toolCallId, params, signal, onUpdate); }, })); }
Estratégia de Divisão de Ferramenta
splitSdkTools() passa todas as ferramentas via customTools:
typescriptexport function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) { return { builtInTools: [], // Vazio. Substituímos tudo customTools: toToolDefinitions(options.tools), }; }
Isso garante que a filtragem de política do Mayros, integração de sandbox e conjunto de ferramentas estendido permaneçam consistentes entre provedores.
Construção de Prompt do Sistema
O prompt do sistema é construído em buildAgentSystemPrompt() (system-prompt.ts). Ele monta um prompt completo com seções incluindo Tooling, Estilo de Chamada de Ferramenta, guardas de Segurança, referência CLI Mayros, Skills, Docs, Workspace, Sandbox, Messaging, Tags de Resposta, Voz, Respostas Silenciosas, Heartbeats, metadados de Runtime, mais Memória e Reações quando habilitado, e arquivos de contexto opcionais e conteúdo extra de prompt do sistema. Seções são aparadas para modo de prompt mínimo usado por subagentes.
O prompt é aplicado após a criação da sessão via applySystemPromptOverrideToSession():
typescriptconst systemPromptOverride = createSystemPromptOverride(appendPrompt); applySystemPromptOverrideToSession(session, systemPromptOverride);
Gerenciamento de Sessão
Arquivos de Sessão
Sessões são arquivos JSONL com estrutura de árvore (vinculação id/parentId). O SessionManager do Pi trata a persistência:
typescriptconst sessionManager = SessionManager.open(params.sessionFile);
Mayros envolve isso com guardSessionManager() para segurança de resultado de ferramenta.
Cache de Sessão
session-manager-cache.ts cacheia instâncias SessionManager para evitar análise de arquivo repetida:
typescriptawait prewarmSessionFile(params.sessionFile); sessionManager = SessionManager.open(params.sessionFile); trackSessionManagerAccess(params.sessionFile);
Limitação de Histórico
limitHistoryTurns() corta histórico de conversa baseado no tipo de canal (DM vs grupo).
Compactação
Auto-compactação aciona em estouro de contexto. compactEmbeddedPiSessionDirect() trata compactação manual:
typescriptconst compactResult = await compactEmbeddedPiSessionDirect({ sessionId, sessionFile, provider, model, ... });
Autenticação e Resolução de Modelo
Perfis de Autenticação
Mayros mantém um armazenamento de perfil de autenticação com múltiplas chaves de API por provedor:
typescriptconst authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
Perfis rotacionam em falhas com rastreamento de cooldown:
typescriptawait markAuthProfileFailure({ store, profileId, reason, cfg, agentDir }); const rotated = await advanceAuthProfile();
Resolução de Modelo
typescriptimport { resolveModel } from "./pi-embedded-runner/model.js"; const { model, error, authStorage, modelRegistry } = resolveModel( provider, modelId, agentDir, config, ); // Usa ModelRegistry e AuthStorage do pi authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);
Failover
FailoverError aciona fallback de modelo quando configurado:
typescriptif (fallbackConfigured && isFailoverErrorMessage(errorText)) { throw new FailoverError(errorText, { reason: promptFailoverReason ?? "unknown", provider, model: modelId, profileId, status: resolveFailoverStatus(promptFailoverReason), }); }
Extensões Pi
Mayros carrega extensões pi personalizadas para comportamento especializado:
Safeguard de Compactação
pi-extensions/compaction-safeguard.ts adiciona guardas à compactação, incluindo orçamento de token adaptativo mais resumos de falha de ferramenta e operação de arquivo:
typescriptif (resolveCompactionMode(params.cfg) === "safeguard") { setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare }); paths.push(resolvePiExtensionPath("compaction-safeguard")); }
Poda de Contexto
pi-extensions/context-pruning.ts implementa poda de contexto baseada em cache-TTL:
typescriptif (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") { setContextPruningRuntime(params.sessionManager, { settings, contextWindowTokens, isToolPrunable, lastCacheTouchAt, }); paths.push(resolvePiExtensionPath("context-pruning")); }
Streaming e Respostas de Bloco
Chunking de Bloco
EmbeddedBlockChunker gerencia streaming de texto em blocos de resposta discretos:
typescriptconst blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
Remoção de Tag Thinking/Final
Saída de streaming é processada para remover blocos <think>/<thinking> e extrair conteúdo <final>:
typescriptconst stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => { // Remover conteúdo <think>...</think> // Se enforceFinalTag, retornar apenas conteúdo <final>...</final> };
Diretivas de Resposta
Diretivas de resposta como [[media:url]], [[voice]], [[reply:id]] são analisadas e extraídas:
typescriptconst { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
Tratamento de Erro
Classificação de Erro
pi-embedded-helpers.ts classifica erros para tratamento apropriado:
typescriptisContextOverflowError(errorText) // Contexto muito grande isCompactionFailureError(errorText) // Compactação falhou isAuthAssistantError(lastAssistant) // Falha de autenticação isRateLimitAssistantError(...) // Taxa limitada isFailoverAssistantError(...) // Deve fazer failover classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
Fallback de Nível de Pensamento
Se um nível de pensamento não for suportado, ele faz fallback:
typescriptconst fallbackThinking = pickFallbackThinkingLevel({ message: errorText, attempted: attemptedThinking, }); if (fallbackThinking) { thinkLevel = fallbackThinking; continue; }
Integração de Sandbox
Quando o modo sandbox está habilitado, ferramentas e caminhos são restringidos:
typescriptconst sandbox = await resolveSandboxContext({ config: params.config, sessionKey: sandboxSessionKey, workspaceDir: resolvedWorkspace, }); if (sandboxRoot) { // Usar ferramentas read/edit/write em sandbox // Exec executa em container // Browser usa URL de ponte }
Tratamento Específico de Provedor
Anthropic
- Limpeza de string mágica de recusa
- Validação de turno para papéis consecutivos
- Compatibilidade de parâmetro Claude Code
Google/Gemini
- Correções de ordenação de turno (
applyGoogleTurnOrderingFix) - Sanitização de schema de ferramenta (
sanitizeToolsForGoogle) - Sanitização de histórico de sessão (
sanitizeSessionHistory)
OpenAI
- Ferramenta
apply_patchpara modelos Codex - Tratamento de downgrade de nível de pensamento
Integração TUI
Mayros também tem um modo TUI local que usa componentes pi-tui diretamente:
typescript// src/tui/tui.ts import { ... } from "@mariozechner/pi-tui";
Isso fornece a experiência de terminal interativo similar ao modo nativo do pi.
Principais Diferenças do Pi CLI
| Aspecto | Pi CLI | Mayros Incorporado |
|---|---|---|
| Invocação | Comando pi / RPC | SDK via createAgentSession() |
| Ferramentas | Ferramentas de codificação padrão | Suite de ferramentas Mayros personalizada |
| Prompt do sistema | AGENTS.md + prompts | Dinâmico por canal/contexto |
| Armazenamento de sessão | ~/.pi/agent/sessions/ | ~/.mayros/agents/<agentId>/sessions/ (ou $MAYROS_STATE_DIR/agents/<agentId>/sessions/) |
| Autenticação | Credencial única | Multi-perfil com rotação |
| Extensões | Carregadas do disco | Programáticas + caminhos de disco |
| Tratamento de evento | Renderização TUI | Baseado em callback (onBlockReply, etc.) |
Considerações Futuras
Áreas para potencial retrabalho:
- Alinhamento de assinatura de ferramenta: Atualmente adaptando entre assinaturas pi-agent-core e pi-coding-agent
- Envolvimento de gerenciador de sessão:
guardSessionManageradiciona segurança mas aumenta complexidade - Carregamento de extensão: Poderia usar
ResourceLoaderdo pi mais diretamente - Complexidade de handler de streaming:
subscribeEmbeddedPiSessioncresceu muito - Peculiaridades de provedor: Muitos caminhos de código específicos de provedor que pi poderia potencialmente tratar
Testes
Todos os testes existentes que cobrem a integração pi e suas extensões:
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