Arsitektur Integrasi Pi
Dokumen ini menjelaskan bagaimana Mayros berintegrasi dengan pi-coding-agent dan paket saudaranya (pi-ai, pi-agent-core, pi-tui) untuk mendukung kemampuan agen AI-nya.
Ringkasan
Mayros menggunakan SDK pi untuk menyematkan agen coding AI ke dalam arsitektur gateway pesan. Alih-alih menelurkan pi sebagai subprocess atau menggunakan mode RPC, Mayros langsung mengimpor dan membuat instance AgentSession pi melalui createAgentSession(). Pendekatan embedded ini menyediakan:
- Kontrol penuh atas siklus hidup sesi dan penanganan event
- Injeksi tool kustom (pesan, sandbox, aksi spesifik channel)
- Kustomisasi system prompt per channel/konteks
- Persistensi sesi dengan dukungan branching/compaction
- Rotasi profil auth multi-akun dengan failover
- Peralihan model yang agnostik provider
Dependensi Paket
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" }
| Paket | Tujuan |
|---|---|
pi-ai | Abstraksi LLM inti: Model, streamSimple, tipe pesan, API provider |
pi-agent-core | Loop agen, eksekusi tool, tipe AgentMessage |
pi-coding-agent | SDK tingkat tinggi: createAgentSession, SessionManager, AuthStorage, ModelRegistry, tool bawaan |
pi-tui | Komponen UI terminal (digunakan dalam mode TUI lokal Mayros) |
Struktur File
src/agents/
├── pi-embedded-runner.ts # Re-exports dari pi-embedded-runner/
├── pi-embedded-runner/
│ ├── run.ts # Entry point utama: runEmbeddedPiAgent()
│ ├── run/
│ │ ├── attempt.ts # Logika percobaan tunggal dengan setup sesi
│ │ ├── params.ts # Tipe RunEmbeddedPiAgentParams
│ │ ├── payloads.ts # Bangun payload respons dari hasil run
│ │ ├── images.ts # Injeksi gambar model Vision
│ │ └── types.ts # EmbeddedRunAttemptResult
│ ├── abort.ts # Deteksi error pembatalan
│ ├── cache-ttl.ts # Pelacakan Cache TTL untuk pemangkasan konteks
│ ├── compact.ts # Logika compaction manual/otomatis
│ ├── extensions.ts # Muat ekstensi pi untuk run embedded
│ ├── extra-params.ts # Parameter stream spesifik provider
│ ├── google.ts # Perbaikan urutan turn Google/Gemini
│ ├── history.ts # Pembatasan histori (DM vs grup)
│ ├── lanes.ts # Lane perintah sesi/global
│ ├── logger.ts # Logger subsistem
│ ├── model.ts # Resolusi model via ModelRegistry
│ ├── runs.ts # Pelacakan run aktif, pembatalan, antrian
│ ├── sandbox-info.ts # Info Sandbox untuk system prompt
│ ├── session-manager-cache.ts # Caching instance SessionManager
│ ├── session-manager-init.ts # Inisialisasi file sesi
│ ├── system-prompt.ts # Pembangun system prompt
│ ├── tool-split.ts # Pisahkan tool menjadi builtIn vs custom
│ ├── types.ts # EmbeddedPiAgentMeta, EmbeddedPiRunResult
│ └── utils.ts # Pemetaan ThinkLevel, deskripsi error
├── pi-embedded-subscribe.ts # Subscription/dispatch event sesi
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # Factory handler event
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts # Chunking balasan streaming block
├── pi-embedded-messaging.ts # Pelacakan pengiriman tool pesan
├── pi-embedded-helpers.ts # Klasifikasi error, validasi turn
├── pi-embedded-helpers/ # Modul helper
├── pi-embedded-utils.ts # Utilitas format
├── pi-tools.ts # createMayrosCodingTools()
├── pi-tools.abort.ts # Pembungkusan AbortSignal untuk tool
├── pi-tools.policy.ts # Kebijakan allowlist/denylist tool
├── pi-tools.read.ts # Kustomisasi tool Read
├── pi-tools.schema.ts # Normalisasi skema tool
├── pi-tools.types.ts # Alias tipe AnyAgentTool
├── pi-tool-definition-adapter.ts # Adapter AgentTool -> ToolDefinition
├── pi-settings.ts # Override pengaturan
├── pi-extensions/ # Ekstensi pi kustom
│ ├── compaction-safeguard.ts # Ekstensi Safeguard
│ ├── compaction-safeguard-runtime.ts
│ ├── context-pruning.ts # Ekstensi pemangkasan konteks Cache-TTL
│ └── context-pruning/
├── model-auth.ts # Resolusi profil Auth
├── auth-profiles.ts # Penyimpanan profil, cooldown, failover
├── model-selection.ts # Resolusi model default
├── models-config.ts # Pembuatan models.json
├── model-catalog.ts # Cache katalog model
├── context-window-guard.ts # Validasi jendela konteks
├── failover-error.ts # Kelas FailoverError
├── defaults.ts # DEFAULT_PROVIDER, DEFAULT_MODEL
├── system-prompt.ts # buildAgentSystemPrompt()
├── system-prompt-params.ts # Resolusi parameter system prompt
├── system-prompt-report.ts # Pembuatan laporan debug
├── tool-summaries.ts # Ringkasan deskripsi tool
├── tool-policy.ts # Resolusi kebijakan tool
├── transcript-policy.ts # Kebijakan validasi Transcript
├── skills.ts # Pembuatan Skill snapshot/prompt
├── skills/ # Subsistem Skill
├── sandbox.ts # Resolusi konteks Sandbox
├── sandbox/ # Subsistem Sandbox
├── channel-tools.ts # Injeksi tool spesifik channel
├── mayros-tools.ts # Tool spesifik Mayros
├── bash-tools.ts # Tool exec/process
├── apply-patch.ts # Tool apply_patch (OpenAI)
├── tools/ # Implementasi tool individual
│ ├── 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
└── ...
Alur Integrasi Inti
1. Menjalankan Embedded Agent
Entry point utama adalah runEmbeddedPiAgent() di 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: "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. Pembuatan Sesi
Di dalam runEmbeddedAttempt() (dipanggil oleh runEmbeddedPiAgent()), SDK pi digunakan:
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. Subscription Event
subscribeEmbeddedPiSession() berlangganan event AgentSession 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, });
Event yang ditangani meliputi:
message_start/message_end/message_update(streaming teks/thinking)tool_execution_start/tool_execution_update/tool_execution_endturn_start/turn_endagent_start/agent_endauto_compaction_start/auto_compaction_end
4. Prompting
Setelah pengaturan, sesi diprompt:
typescriptawait session.prompt(effectivePrompt, { images: imageResult.images });
SDK menangani loop agen lengkap: mengirim ke LLM, mengeksekusi tool call, streaming respons.
Arsitektur Tool
Pipeline Tool
- Base Tools:
codingToolspi (read, bash, edit, write) - Custom Replacement: Mayros mengganti bash dengan
exec/process, menyesuaikan read/edit/write untuk sandbox - Mayros Tools: messaging, browser, canvas, sessions, cron, gateway, dll.
- Channel Tools: Tool aksi spesifik Discord/Telegram/Slack/WhatsApp
- Policy Filtering: Tool difilter berdasarkan profil, provider, agen, grup, kebijakan sandbox
- Schema Normalization: Skema dibersihkan untuk quirk Gemini/OpenAI
- AbortSignal Wrapping: Tool dibungkus untuk menghormati abort signal
Tool Definition Adapter
AgentTool pi-agent-core memiliki signature execute yang berbeda dari ToolDefinition pi-coding-agent. Adapter di pi-tool-definition-adapter.ts menjembatani ini:
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) => { // pi-coding-agent signature differs from pi-agent-core return await tool.execute(toolCallId, params, signal, onUpdate); }, })); }
Strategi Tool Split
splitSdkTools() melewatkan semua tool melalui customTools:
typescriptexport function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) { return { builtInTools: [], // Empty. We override everything customTools: toToolDefinitions(options.tools), }; }
Ini memastikan filtering kebijakan Mayros, integrasi sandbox, dan toolset yang diperluas tetap konsisten di seluruh provider.
Konstruksi System Prompt
System prompt dibangun di buildAgentSystemPrompt() (system-prompt.ts). Ini merakit prompt lengkap dengan bagian termasuk Tooling, Tool Call Style, Safety guardrail, referensi CLI Mayros, Skills, Docs, Workspace, Sandbox, Messaging, Reply Tags, Voice, Silent Replies, Heartbeats, metadata Runtime, plus Memory dan Reactions ketika diaktifkan, dan file konteks opsional serta konten system prompt ekstra. Bagian dipangkas untuk mode prompt minimal yang digunakan oleh subagen.
Prompt diterapkan setelah pembuatan sesi melalui applySystemPromptOverrideToSession():
typescriptconst systemPromptOverride = createSystemPromptOverride(appendPrompt); applySystemPromptOverrideToSession(session, systemPromptOverride);
Manajemen Sesi
File Sesi
Sesi adalah file JSONL dengan struktur pohon (penautan id/parentId). SessionManager Pi menangani persistensi:
typescriptconst sessionManager = SessionManager.open(params.sessionFile);
Mayros membungkus ini dengan guardSessionManager() untuk keamanan hasil tool.
Caching Sesi
session-manager-cache.ts menyimpan instance SessionManager untuk menghindari parsing file berulang:
typescriptawait prewarmSessionFile(params.sessionFile); sessionManager = SessionManager.open(params.sessionFile); trackSessionManagerAccess(params.sessionFile);
Pembatasan Histori
limitHistoryTurns() memangkas histori percakapan berdasarkan tipe channel (DM vs grup).
Compaction
Auto-compaction terpicu pada context overflow. compactEmbeddedPiSessionDirect() menangani compaction manual:
typescriptconst compactResult = await compactEmbeddedPiSessionDirect({ sessionId, sessionFile, provider, model, ... });
Autentikasi & Resolusi Model
Profil Auth
Mayros memelihara penyimpanan profil auth dengan beberapa API key per provider:
typescriptconst authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
Profil berputar pada kegagalan dengan pelacakan cooldown:
typescriptawait markAuthProfileFailure({ store, profileId, reason, cfg, agentDir }); const rotated = await advanceAuthProfile();
Resolusi Model
typescriptimport { 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 memicu model fallback ketika dikonfigurasi:
typescriptif (fallbackConfigured && isFailoverErrorMessage(errorText)) { throw new FailoverError(errorText, { reason: promptFailoverReason ?? "unknown", provider, model: modelId, profileId, status: resolveFailoverStatus(promptFailoverReason), }); }
Ekstensi Pi
Mayros memuat ekstensi pi kustom untuk perilaku khusus:
Compaction Safeguard
pi-extensions/compaction-safeguard.ts menambahkan guardrail ke compaction, termasuk penganggaran token adaptif plus ringkasan kegagalan tool dan operasi file:
typescriptif (resolveCompactionMode(params.cfg) === "safeguard") { setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare }); paths.push(resolvePiExtensionPath("compaction-safeguard")); }
Context Pruning
pi-extensions/context-pruning.ts mengimplementasikan pemangkasan konteks berbasis cache-TTL:
typescriptif (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") { setContextPruningRuntime(params.sessionManager, { settings, contextWindowTokens, isToolPrunable, lastCacheTouchAt, }); paths.push(resolvePiExtensionPath("context-pruning")); }
Streaming & Balasan Block
Block Chunking
EmbeddedBlockChunker mengelola streaming teks menjadi block balasan diskrit:
typescriptconst blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
Stripping Tag Thinking/Final
Output streaming diproses untuk menghapus block <think>/<thinking> dan mengekstrak konten <final>:
typescriptconst stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => { // Strip <think>...</think> content // If enforceFinalTag, only return <final>...</final> content };
Reply Directives
Reply directives seperti [[media:url]], [[voice]], [[reply:id]] diparsing dan diekstrak:
typescriptconst { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
Penanganan Error
Klasifikasi Error
pi-embedded-helpers.ts mengklasifikasikan error untuk penanganan yang tepat:
typescriptisContextOverflowError(errorText) // Konteks terlalu besar isCompactionFailureError(errorText) // Compaction gagal isAuthAssistantError(lastAssistant) // Kegagalan auth isRateLimitAssistantError(...) // Rate limited isFailoverAssistantError(...) // Harus failover classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
Thinking Level Fallback
Jika thinking level tidak didukung, akan fallback:
typescriptconst fallbackThinking = pickFallbackThinkingLevel({ message: errorText, attempted: attemptedThinking, }); if (fallbackThinking) { thinkLevel = fallbackThinking; continue; }
Integrasi Sandbox
Ketika mode sandbox diaktifkan, tool dan path dibatasi:
typescriptconst 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 }
Penanganan Spesifik Provider
Anthropic
- Pembersihan magic string penolakan
- Validasi turn untuk role berurutan
- Kompatibilitas parameter Claude Code
Google/Gemini
- Perbaikan urutan turn (
applyGoogleTurnOrderingFix) - Sanitasi skema tool (
sanitizeToolsForGoogle) - Sanitasi histori sesi (
sanitizeSessionHistory)
OpenAI
- Tool
apply_patchuntuk model Codex - Penanganan downgrade thinking level
Integrasi TUI
Mayros juga memiliki mode TUI lokal yang menggunakan komponen pi-tui langsung:
typescript// src/tui/tui.ts import { ... } from "@mariozechner/pi-tui";
Ini menyediakan pengalaman terminal interaktif serupa dengan mode native pi.
Perbedaan Utama dari Pi CLI
| Aspek | Pi CLI | Mayros Embedded |
|---|---|---|
| Invokasi | Perintah pi / RPC | SDK melalui createAgentSession() |
| Tool | Tool coding default | Suite tool Mayros kustom |
| System prompt | AGENTS.md + prompt | Dinamis per-channel/konteks |
| Penyimpanan sesi | ~/.pi/agent/sessions/ | ~/.mayros/agents/<agentId>/sessions/ (atau $MAYROS_STATE_DIR/agents/<agentId>/sessions/) |
| Auth | Kredensial tunggal | Multi-profil dengan rotasi |
| Ekstensi | Dimuat dari disk | Programmatic + path disk |
| Penanganan event | Rendering TUI | Berbasis callback (onBlockReply, dll.) |
Pertimbangan Masa Depan
Area untuk potensi pengerjaan ulang:
- Penyelarasan signature tool: Saat ini beradaptasi antara signature pi-agent-core dan pi-coding-agent
- Pembungkusan session manager:
guardSessionManagermenambahkan keamanan tetapi meningkatkan kompleksitas - Pemuatan ekstensi: Dapat menggunakan
ResourceLoaderpi lebih langsung - Kompleksitas handler streaming:
subscribeEmbeddedPiSessiontelah tumbuh besar - Quirk provider: Banyak codepath spesifik provider yang berpotensi ditangani pi
Test
Semua test yang ada yang mencakup integrasi pi dan ekstensinya:
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