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"
}
PacotePropósito
pi-aiAbstrações LLM principais: Model, streamSimple, tipos de mensagem, APIs de provedor
pi-agent-coreLoop de agente, execução de ferramenta, tipos AgentMessage
pi-coding-agentSDK de alto nível: createAgentSession, SessionManager, AuthStorage, ModelRegistry, ferramentas integradas
pi-tuiComponentes 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:

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: "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:

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. Subscrição de Evento

subscribeEmbeddedPiSession() subscreve aos eventos AgentSession do 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,
});

Eventos tratados incluem:

  • message_start / message_end / message_update (streaming de texto/pensamento)
  • tool_execution_start / tool_execution_update / tool_execution_end
  • turn_start / turn_end
  • agent_start / agent_end
  • auto_compaction_start / auto_compaction_end

4. Prompting

Após a configuração, a sessão é solicitada:

typescript
await 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

  1. Ferramentas Base: codingTools do pi (read, bash, edit, write)
  2. Substituições Personalizadas: Mayros substitui bash por exec/process, personaliza read/edit/write para sandbox
  3. Ferramentas Mayros: messaging, browser, canvas, sessions, cron, gateway, etc.
  4. Ferramentas de Canal: Ferramentas de ação específicas de Discord/Telegram/Slack/WhatsApp
  5. Filtragem de Política: Ferramentas filtradas por perfil, provedor, agente, grupo, políticas de sandbox
  6. Normalização de Schema: Schemas limpos para peculiaridades Gemini/OpenAI
  7. 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:

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) => {
      // 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:

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

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

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

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

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

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

Perfis rotacionam em falhas com rastreamento de cooldown:

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

Resolução de Modelo

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

typescript
if (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:

typescript
if (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:

typescript
if (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:

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

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

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

Tratamento de Erro

Classificação de Erro

pi-embedded-helpers.ts classifica erros para tratamento apropriado:

typescript
isContextOverflowError(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:

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

typescript
const 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_patch para 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

AspectoPi CLIMayros Incorporado
InvocaçãoComando pi / RPCSDK via createAgentSession()
FerramentasFerramentas de codificação padrãoSuite de ferramentas Mayros personalizada
Prompt do sistemaAGENTS.md + promptsDinâmico por canal/contexto
Armazenamento de sessão~/.pi/agent/sessions/~/.mayros/agents/<agentId>/sessions/ (ou $MAYROS_STATE_DIR/agents/<agentId>/sessions/)
AutenticaçãoCredencial únicaMulti-perfil com rotação
ExtensõesCarregadas do discoProgramáticas + caminhos de disco
Tratamento de eventoRenderização TUIBaseado em callback (onBlockReply, etc.)

Considerações Futuras

Áreas para potencial retrabalho:

  1. Alinhamento de assinatura de ferramenta: Atualmente adaptando entre assinaturas pi-agent-core e pi-coding-agent
  2. Envolvimento de gerenciador de sessão: guardSessionManager adiciona segurança mas aumenta complexidade
  3. Carregamento de extensão: Poderia usar ResourceLoader do pi mais diretamente
  4. Complexidade de handler de streaming: subscribeEmbeddedPiSession cresceu muito
  5. 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.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