Arquitectura de Integración de Pi

Este documento describe cómo Mayros se integra con pi-coding-agent y sus paquetes hermanos (pi-ai, pi-agent-core, pi-tui) para potenciar sus capacidades de agente de IA.

Descripción General

Mayros usa el SDK de pi para incorporar un agente de codificación de IA en su arquitectura de gateway de mensajería. En lugar de generar pi como un subproceso o usar modo RPC, Mayros importa directamente e instancia el AgentSession de pi vía createAgentSession(). Este enfoque embebido proporciona:

  • Control completo sobre el ciclo de vida de la sesión y manejo de eventos
  • Inyección de herramientas personalizadas (mensajería, sandbox, acciones específicas de canal)
  • Personalización del prompt del sistema por canal/contexto
  • Persistencia de sesión con soporte para ramificación/compactación
  • Rotación de perfiles de autenticación multicuenta con failover
  • Cambio de modelo agnóstico al proveedor

Dependencias de Paquetes

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"
}
PaquetePropósito
pi-aiAbstracciones LLM principales: Model, streamSimple, tipos de mensaje, APIs de proveedor
pi-agent-coreBucle de agente, ejecución de herramientas, tipos AgentMessage
pi-coding-agentSDK de alto nivel: createAgentSession, SessionManager, AuthStorage, ModelRegistry, herramientas incorporadas
pi-tuiComponentes UI de terminal (usado en modo TUI local de Mayros)

Estructura de Archivos

src/agents/
├── pi-embedded-runner.ts          # Re-exports desde pi-embedded-runner/
├── pi-embedded-runner/
│   ├── run.ts                     # Punto de entrada principal: runEmbeddedPiAgent()
│   ├── run/
│   │   ├── attempt.ts             # Lógica de intento único con configuración de sesión
│   │   ├── params.ts              # Tipo RunEmbeddedPiAgentParams
│   │   ├── payloads.ts            # Construir payloads de respuesta desde resultados de ejecución
│   │   ├── images.ts              # Inyección de imágenes de modelo Vision
│   │   └── types.ts               # EmbeddedRunAttemptResult
│   ├── abort.ts                   # Detección de errores de cancelación
│   ├── cache-ttl.ts               # Seguimiento de Cache TTL para poda de contexto
│   ├── compact.ts                 # Lógica de compactación manual/automática
│   ├── extensions.ts              # Cargar extensiones pi para ejecuciones embebidas
│   ├── extra-params.ts            # Parámetros de stream específicos de proveedor
│   ├── google.ts                  # Correcciones de orden de turnos Google/Gemini
│   ├── history.ts                 # Limitación de historial (DM vs grupo)
│   ├── lanes.ts                   # Carriles de comandos sesión/global
│   ├── logger.ts                  # Logger de subsistema
│   ├── model.ts                   # Resolución de modelo vía ModelRegistry
│   ├── runs.ts                    # Seguimiento de ejecuciones activas, cancelación, cola
│   ├── sandbox-info.ts            # Info de Sandbox para prompt del sistema
│   ├── session-manager-cache.ts   # Caché de instancias SessionManager
│   ├── session-manager-init.ts    # Inicialización de archivos de sesión
│   ├── system-prompt.ts           # Constructor de prompt del sistema
│   ├── tool-split.ts              # Dividir herramientas en builtIn vs custom
│   ├── types.ts                   # EmbeddedPiAgentMeta, EmbeddedPiRunResult
│   └── utils.ts                   # Mapeo de ThinkLevel, descripción de errores
├── pi-embedded-subscribe.ts       # Suscripción/despacho de eventos de sesión
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # Fábrica de manejadores de eventos
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts   # Fragmentación de respuestas en streaming
├── pi-embedded-messaging.ts       # Seguimiento de envío de herramienta de mensajería
├── pi-embedded-helpers.ts         # Clasificación de errores, validación de turnos
├── pi-embedded-helpers/           # Módulos de ayuda
├── pi-embedded-utils.ts           # Utilidades de formato
├── pi-tools.ts                    # createMayrosCodingTools()
├── pi-tools.abort.ts              # Envoltura AbortSignal para herramientas
├── pi-tools.policy.ts             # Política allowlist/denylist de herramientas
├── pi-tools.read.ts               # Personalizaciones de herramienta Read
├── pi-tools.schema.ts             # Normalización de esquema de herramientas
├── pi-tools.types.ts              # Alias de tipo AnyAgentTool
├── pi-tool-definition-adapter.ts  # Adaptador AgentTool -> ToolDefinition
├── pi-settings.ts                 # Sobreescrituras de configuración
├── pi-extensions/                 # Extensiones pi personalizadas
│   ├── compaction-safeguard.ts    # Extensión Safeguard
│   ├── compaction-safeguard-runtime.ts
│   ├── context-pruning.ts         # Extensión de poda de contexto Cache-TTL
│   └── context-pruning/
├── model-auth.ts                  # Resolución de perfiles Auth
├── auth-profiles.ts               # Almacén de perfiles, cooldown, failover
├── model-selection.ts             # Resolución de modelo por defecto
├── models-config.ts               # Generación de models.json
├── model-catalog.ts               # Caché de catálogo de modelos
├── context-window-guard.ts        # Validación de ventana de contexto
├── failover-error.ts              # Clase FailoverError
├── defaults.ts                    # DEFAULT_PROVIDER, DEFAULT_MODEL
├── system-prompt.ts               # buildAgentSystemPrompt()
├── system-prompt-params.ts        # Resolución de parámetros de prompt del sistema
├── system-prompt-report.ts        # Generación de reporte de debug
├── tool-summaries.ts              # Resúmenes de descripción de herramientas
├── tool-policy.ts                 # Resolución de política de herramientas
├── transcript-policy.ts           # Política de validación de Transcript
├── skills.ts                      # Construcción de Skill snapshot/prompt
├── skills/                        # Subsistema de Skills
├── sandbox.ts                     # Resolución de contexto Sandbox
├── sandbox/                       # Subsistema Sandbox
├── channel-tools.ts               # Inyección de herramientas específicas de canal
├── mayros-tools.ts              # Herramientas específicas de Mayros
├── bash-tools.ts                  # Herramientas exec/process
├── apply-patch.ts                 # Herramienta apply_patch (OpenAI)
├── tools/                         # Implementaciones de herramientas individuales
│   ├── 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
└── ...

Flujo de Integración Principal

1. Ejecutar un Agente Embebido

El punto de entrada principal es runEmbeddedPiAgent() en 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. Creación de Sesión

Dentro de runEmbeddedAttempt() (llamado por runEmbeddedPiAgent()), se usa el SDK de 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. Suscripción a Eventos

subscribeEmbeddedPiSession() se suscribe a eventos de AgentSession de 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 manejados incluyen:

  • message_start / message_end / message_update (streaming de texto/pensamiento)
  • 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

Después de la configuración, se solicita la sesión:

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

El SDK maneja el bucle completo del agente: enviar al LLM, ejecutar llamadas de herramientas, transmitir respuestas.

Arquitectura de Herramientas

Pipeline de Herramientas

  1. Herramientas Base: codingTools de pi (read, bash, edit, write)
  2. Reemplazos Personalizados: Mayros reemplaza bash con exec/process, personaliza read/edit/write para sandbox
  3. Herramientas de Mayros: mensajería, navegador, canvas, sesiones, cron, gateway, etc.
  4. Herramientas de Canal: herramientas de acción específicas de Discord/Telegram/Slack/WhatsApp
  5. Filtrado de Política: herramientas filtradas por perfil, proveedor, agente, grupo, políticas de sandbox
  6. Normalización de Esquema: esquemas limpiados para peculiaridades de Gemini/OpenAI
  7. Envolvimiento AbortSignal: herramientas envueltas para respetar señales de abortar

Adaptador de Definición de Herramienta

AgentTool de pi-agent-core tiene una firma execute diferente de ToolDefinition de pi-coding-agent. El adaptador en pi-tool-definition-adapter.ts une esto:

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 signature differs from pi-agent-core
      return await tool.execute(toolCallId, params, signal, onUpdate);
    },
  }));
}

Estrategia de División de Herramientas

splitSdkTools() pasa todas las herramientas vía customTools:

typescript
export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) {
  return {
    builtInTools: [], // Empty. We override everything
    customTools: toToolDefinitions(options.tools),
  };
}

Esto asegura que el filtrado de políticas de Mayros, la integración de sandbox y el conjunto de herramientas extendido permanezcan consistentes entre proveedores.

Construcción del Prompt del Sistema

El prompt del sistema se construye en buildAgentSystemPrompt() (system-prompt.ts). Ensambla un prompt completo con secciones incluyendo Tooling, Tool Call Style, protecciones de Seguridad, referencia CLI de Mayros, Skills, Docs, Workspace, Sandbox, Messaging, Reply Tags, Voice, Silent Replies, Heartbeats, metadatos de Runtime, más Memory y Reactions cuando están habilitados, y archivos de contexto opcionales más contenido extra de prompt del sistema. Las secciones se recortan para el modo de prompt mínimo usado por subagentes.

El prompt se aplica después de la creación de sesión vía applySystemPromptOverrideToSession():

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

Gestión de Sesiones

Archivos de Sesión

Las sesiones son archivos JSONL con estructura de árbol (enlace id/parentId). El SessionManager de Pi maneja la persistencia:

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

Mayros envuelve esto con guardSessionManager() para seguridad de resultados de herramientas.

Caché de Sesión

session-manager-cache.ts cachea instancias de SessionManager para evitar parseo repetido de archivos:

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

Limitación de Historial

limitHistoryTurns() recorta el historial de conversación basado en el tipo de canal (DM vs grupo).

Compactación

La auto-compactación se activa en desbordamiento de contexto. compactEmbeddedPiSessionDirect() maneja la compactación manual:

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

Autenticación y Resolución de Modelo

Perfiles de Autenticación

Mayros mantiene un almacén de perfiles de autenticación con múltiples claves API por proveedor:

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

Los perfiles rotan en fallos con seguimiento de cooldown:

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

Resolución de Modelo

typescript
import { resolveModel } from "./pi-embedded-runner/model.js";

const { model, error, authStorage, modelRegistry } = resolveModel(
  provider,
  modelId,
  agentDir,
  config,
);

// Uses pi's ModelRegistry and AuthStorage
authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);

Failover

FailoverError activa el fallback de modelo cuando está configurado:

typescript
if (fallbackConfigured && isFailoverErrorMessage(errorText)) {
  throw new FailoverError(errorText, {
    reason: promptFailoverReason ?? "unknown",
    provider,
    model: modelId,
    profileId,
    status: resolveFailoverStatus(promptFailoverReason),
  });
}

Extensiones de Pi

Mayros carga extensiones de pi personalizadas para comportamiento especializado:

Protección de Compactación

pi-extensions/compaction-safeguard.ts añade barandillas a la compactación, incluyendo presupuesto adaptativo de tokens más resúmenes de fallo de herramienta y operaciones de archivo:

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 basada en cache-TTL:

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

Streaming y Respuestas por Bloques

Fragmentación de Bloques

EmbeddedBlockChunker gestiona el streaming de texto en bloques de respuesta discretos:

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

Eliminación de Etiquetas Thinking/Final

La salida en streaming se procesa para eliminar bloques <think>/<thinking> y extraer contenido <final>:

typescript
const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => {
  // Strip <think>...</think> content
  // If enforceFinalTag, only return <final>...</final> content
};

Directivas de Respuesta

Las directivas de respuesta como [[media:url]], [[voice]], [[reply:id]] se parsean y extraen:

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

Manejo de Errores

Clasificación de Errores

pi-embedded-helpers.ts clasifica errores para el manejo apropiado:

typescript
isContextOverflowError(errorText)     // Contexto demasiado grande
isCompactionFailureError(errorText)   // Compactación fallida
isAuthAssistantError(lastAssistant)   // Fallo de autenticación
isRateLimitAssistantError(...)        // Rate limited
isFailoverAssistantError(...)         // Debería hacer failover
classifyFailoverReason(errorText)     // "auth" | "rate_limit" | "quota" | "timeout" | ...

Fallback de Nivel de Pensamiento

Si un nivel de pensamiento no está soportado, hace fallback:

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

Integración de Sandbox

Cuando el modo sandbox está habilitado, las herramientas y rutas se restringen:

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

if (sandboxRoot) {
  // Use sandboxed read/edit/write tools
  // Exec runs in container
  // Browser uses bridge URL
}

Manejo Específico de Proveedor

Anthropic

  • Limpieza de cadena mágica de rechazo
  • Validación de turnos para roles consecutivos
  • Compatibilidad de parámetros de Claude Code

Google/Gemini

  • Correcciones de orden de turnos (applyGoogleTurnOrderingFix)
  • Sanitización de esquemas de herramientas (sanitizeToolsForGoogle)
  • Sanitización de historial de sesión (sanitizeSessionHistory)

OpenAI

  • Herramienta apply_patch para modelos Codex
  • Manejo de downgrade de nivel de pensamiento

Integración TUI

Mayros también tiene un modo TUI local que usa componentes pi-tui directamente:

typescript
// src/tui/tui.ts
import { ... } from "@mariozechner/pi-tui";

Esto proporciona la experiencia de terminal interactiva similar al modo nativo de pi.

Diferencias Clave con Pi CLI

AspectoPi CLIMayros Embebido
InvocaciónComando pi / RPCSDK vía createAgentSession()
HerramientasHerramientas coding por defectoSuite de herramientas Mayros personalizada
Prompt del sistemaAGENTS.md + promptsDinámico por canal/contexto
Almacenamiento sesión~/.pi/agent/sessions/~/.mayros/agents/<agentId>/sessions/ (o $MAYROS_STATE_DIR/agents/<agentId>/sessions/)
AutenticaciónCredencial únicaMulti-perfil con rotación
ExtensionesCargadas desde discoProgramáticas + rutas de disco
Manejo de eventosRenderizado TUIBasado en callbacks (onBlockReply, etc.)

Consideraciones Futuras

Áreas para potencial refactorización:

  1. Alineación de firmas de herramientas: Actualmente adaptando entre firmas de pi-agent-core y pi-coding-agent
  2. Envolvimiento de session manager: guardSessionManager añade seguridad pero incrementa complejidad
  3. Carga de extensiones: Podría usar el ResourceLoader de pi más directamente
  4. Complejidad del handler de streaming: subscribeEmbeddedPiSession ha crecido mucho
  5. Peculiaridades de proveedor: Muchos codepaths específicos de proveedor que pi podría manejar potencialmente

Tests

Todos los tests existentes que cubren la integración pi y sus extensiones:

  • 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