สถาปัตยกรรมการรวม Pi
เอกสารนี้อธิบายว่า Mayros รวมกับ pi-coding-agent และแพ็คเกจที่เกี่ยวข้อง (pi-ai, pi-agent-core, pi-tui) เพื่อขับเคลื่อนความสามารถ AI agent
ภาพรวม
Mayros ใช้ pi SDK เพื่อฝัง AI coding agent เข้าในสถาปัตยกรรมเกตเวย์ข้อความ แทนที่จะเรียกใช้ pi เป็น subprocess หรือใช้โหมด RPC Mayros จะนำเข้าและสร้างอินสแตนซ์ AgentSession ของ pi ผ่าน createAgentSession() โดยตรง วิธีการฝังนี้มอบ:
- การควบคุมวงจรชีวิตเซสชันและการจัดการเหตุการณ์อย่างเต็มที่
- การฉีดเครื่องมือแบบกำหนดเอง (การส่งข้อความ, sandbox, การดำเนินการเฉพาะช่องทาง)
- การปรับแต่งระบบ prompt ต่อช่องทาง/บริบท
- การคงอยู่ของเซสชันพร้อมการรองรับการแตกสาขา/การบีบอัด
- การหมุนเวียนโปรไฟล์การพิสูจน์ตัวตนหลายบัญชีพร้อม failover
- การสลับโมเดลแบบไม่ขึ้นกับผู้ให้บริการ
การพึ่งพาแพ็คเกจ
json{ "@mariozechner/pi-agent-core": "0.49.3", "@mariozechner/pi-ai": "0.49.3", "@mariozechner/pi-coding-agent": "0.49.3", "@mariozechner/pi-tui": "0.49.3" }
| แพ็คเกจ | วัตถุประสงค์ |
|---|---|
pi-ai | นามธรรม LLM หลัก: Model, streamSimple, ประเภทข้อความ, API ผู้ให้บริการ |
pi-agent-core | ลูป Agent, การดำเนินการเครื่องมือ, ประเภท AgentMessage |
pi-coding-agent | SDK ระดับสูง: createAgentSession, SessionManager, AuthStorage, ModelRegistry, เครื่องมือในตัว |
pi-tui | คอมโพเนนต์ Terminal UI (ใช้ในโหมด TUI โลคัลของ Mayros) |
โครงสร้างไฟล์
src/agents/
├── pi-embedded-runner.ts # Re-exports จาก pi-embedded-runner/
├── pi-embedded-runner/
│ ├── run.ts # จุดเข้าหลัก: runEmbeddedPiAgent()
│ ├── run/
│ │ ├── attempt.ts # ตรรกะความพยายามเดียวพร้อมการตั้งค่าเซสชัน
│ │ ├── params.ts # ประเภท RunEmbeddedPiAgentParams
│ │ ├── payloads.ts # สร้างเพย์โหลดการตอบกลับจากผลลัพธ์การรัน
│ │ ├── images.ts # การฉีดรูปภาพโมเดล Vision
│ │ └── types.ts # EmbeddedRunAttemptResult
│ ├── abort.ts # การตรวจจับข้อผิดพลาดการยกเลิก
│ ├── cache-ttl.ts # การติดตาม Cache TTL สำหรับการตัดแต่งบริบท
│ ├── compact.ts # ตรรกะการบีบอัดด้วยตนเอง/อัตโนมัติ
│ ├── extensions.ts # โหลด pi extensions สำหรับการรันที่ฝัง
│ ├── extra-params.ts # พารามิเตอร์สตรีมเฉพาะผู้ให้บริการ
│ ├── google.ts # การแก้ไขลำดับเทิร์น Google/Gemini
│ ├── history.ts # การจำกัดประวัติ (DM vs กลุ่ม)
│ ├── lanes.ts # เลนคำสั่งเซสชัน/ส่วนกลาง
│ ├── logger.ts # Logger ระบบย่อย
│ ├── model.ts # การแก้ไขโมเดลผ่าน ModelRegistry
│ ├── runs.ts # การติดตามการรันที่ใช้งาน, การยกเลิก, คิว
│ ├── sandbox-info.ts # ข้อมูล Sandbox สำหรับระบบ prompt
│ ├── session-manager-cache.ts # การแคชอินสแตนซ์ SessionManager
│ ├── session-manager-init.ts # การเริ่มต้นไฟล์เซสชัน
│ ├── system-prompt.ts # ตัวสร้างระบบ prompt
│ ├── tool-split.ts # แยกเครื่องมือเป็น builtIn vs custom
│ ├── types.ts # EmbeddedPiAgentMeta, EmbeddedPiRunResult
│ └── utils.ts # การแมป ThinkLevel, คำอธิบายข้อผิดพลาด
├── pi-embedded-subscribe.ts # การสมัครสมาชิกเหตุการณ์เซสชัน/การจัดส่ง
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # โรงงานตัวจัดการเหตุการณ์
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts # การแบ่งชิ้นการตอบกลับแบบสตรีม
├── pi-embedded-messaging.ts # การติดตามเครื่องมือส่งข้อความ
├── pi-embedded-helpers.ts # การจำแนกข้อผิดพลาด, การตรวจสอบเทิร์น
├── pi-embedded-helpers/ # โมดูลตัวช่วย
├── pi-embedded-utils.ts # ยูทิลิตี้การจัดรูปแบบ
├── pi-tools.ts # createMayrosCodingTools()
├── pi-tools.abort.ts # การห่อ AbortSignal สำหรับเครื่องมือ
├── pi-tools.policy.ts # นโยบาย allowlist/denylist เครื่องมือ
├── pi-tools.read.ts # การปรับแต่งเครื่องมือ Read
├── pi-tools.schema.ts # การปรับมาตรฐานสคีมาเครื่องมือ
├── pi-tools.types.ts # ประเภทนามแฝง AnyAgentTool
├── pi-tool-definition-adapter.ts # อะแดปเตอร์ AgentTool -> ToolDefinition
├── pi-settings.ts # การแทนที่การตั้งค่า
├── pi-extensions/ # Pi extensions แบบกำหนดเอง
│ ├── compaction-safeguard.ts # ส่วนขยาย Safeguard
│ ├── compaction-safeguard-runtime.ts
│ ├── context-pruning.ts # ส่วนขยายการตัดแต่งบริบท Cache-TTL
│ └── context-pruning/
├── model-auth.ts # การแก้ไขโปรไฟล์ Auth
├── auth-profiles.ts # ที่เก็บโปรไฟล์, cooldown, failover
├── model-selection.ts # การแก้ไขโมเดลเริ่มต้น
├── models-config.ts # การสร้าง models.json
├── model-catalog.ts # แคชแค็ตตาล็อกโมเดล
├── context-window-guard.ts # การตรวจสอบหน้าต่างบริบท
├── failover-error.ts # คลาส FailoverError
├── defaults.ts # DEFAULT_PROVIDER, DEFAULT_MODEL
├── system-prompt.ts # buildAgentSystemPrompt()
├── system-prompt-params.ts # การแก้ไขพารามิเตอร์ระบบ prompt
├── system-prompt-report.ts # การสร้างรายงานดีบัก
├── tool-summaries.ts # สรุปคำอธิบายเครื่องมือ
├── tool-policy.ts # การแก้ไขนโยบายเครื่องมือ
├── transcript-policy.ts # นโยบายการตรวจสอบ Transcript
├── skills.ts # การสร้าง Skill snapshot/prompt
├── skills/ # ระบบย่อย Skill
├── sandbox.ts # การแก้ไขบริบท Sandbox
├── sandbox/ # ระบบย่อย Sandbox
├── channel-tools.ts # การฉีดเครื่องมือเฉพาะช่องทาง
├── mayros-tools.ts # เครื่องมือเฉพาะ Mayros
├── bash-tools.ts # เครื่องมือ exec/process
├── apply-patch.ts # เครื่องมือ apply_patch (OpenAI)
├── tools/ # การดำเนินการเครื่องมือแต่ละตัว
│ ├── browser-tool.ts
│ ├── canvas-tool.ts
│ ├── cron-tool.ts
│ ├── discord-actions*.ts
│ ├── gateway-tool.ts
│ ├── image-tool.ts
│ ├── message-tool.ts
│ ├── nodes-tool.ts
│ ├── session*.ts
│ ├── slack-actions.ts
│ ├── telegram-actions.ts
│ ├── web-*.ts
│ └── whatsapp-actions.ts
└── ...
เวิร์กโฟลว์การรวมหลัก
1. การรัน Embedded Agent
จุดเข้าหลักคือ runEmbeddedPiAgent() ใน 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. การสร้างเซสชัน
ภายใน runEmbeddedAttempt() (เรียกโดย runEmbeddedPiAgent()) ใช้ pi SDK:
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. การสมัครสมาชิกเหตุการณ์
subscribeEmbeddedPiSession() สมัครสมาชิกเหตุการณ์ 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, });
เหตุการณ์ที่จัดการรวมถึง:
message_start/message_end/message_update(สตรีมข้อความ/ความคิด)tool_execution_start/tool_execution_update/tool_execution_endturn_start/turn_endagent_start/agent_endauto_compaction_start/auto_compaction_end
4. การ Prompting
หลังจากตั้งค่า เซสชันจะถูก prompt:
typescriptawait session.prompt(effectivePrompt, { images: imageResult.images });
SDK จัดการลูป agent เต็มรูปแบบ: ส่งไปยัง LLM, ดำเนินการ tool calls, สตรีมการตอบกลับ
สถาปัตยกรรมเครื่องมือ
ไปป์ไลน์เครื่องมือ
- เครื่องมือฐาน:
codingToolsของ pi (read, bash, edit, write) - การแทนที่แบบกำหนดเอง: Mayros แทนที่ bash ด้วย
exec/process, ปรับแต่ง read/edit/write สำหรับ sandbox - เครื่องมือ Mayros: messaging, browser, canvas, sessions, cron, gateway, ฯลฯ
- เครื่องมือช่องทาง: เครื่องมือการดำเนินการเฉพาะ Discord/Telegram/Slack/WhatsApp
- การกรองนโยบาย: เครื่องมือกรองตามโปรไฟล์, ผู้ให้บริการ, agent, กลุ่ม, นโยบาย sandbox
- การปรับมาตรฐานสคีมา: สคีมาที่ทำความสะอาดสำหรับความแปลกของ Gemini/OpenAI
- การห่อ AbortSignal: เครื่องมือที่ห่อเพื่อเคารพสัญญาณยกเลิก
อะแดปเตอร์คำนิยามเครื่องมือ
AgentTool ของ pi-agent-core มีลายเซ็น execute ที่แตกต่างจาก ToolDefinition ของ pi-coding-agent อะแดปเตอร์ใน pi-tool-definition-adapter.ts เชื่อมสิ่งนี้:
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); }, })); }
กลยุทธ์การแยกเครื่องมือ
splitSdkTools() ส่งเครื่องมือทั้งหมดผ่าน customTools:
typescriptexport function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) { return { builtInTools: [], // Empty. We override everything customTools: toToolDefinitions(options.tools), }; }
สิ่งนี้รับประกันว่าการกรองนโยบายของ Mayros, การรวม sandbox และชุดเครื่องมือที่ขยายยังคงสอดคล้องกันข้ามผู้ให้บริการ
การสร้างระบบ Prompt
ระบบ prompt ถูกสร้างใน buildAgentSystemPrompt() (system-prompt.ts) มันประกอบ prompt เต็มพร้อมส่วนต่างๆ รวมถึง Tooling, Tool Call Style, Safety guardrails, อ้างอิง CLI ของ Mayros, Skills, Docs, Workspace, Sandbox, Messaging, Reply Tags, Voice, Silent Replies, Heartbeats, ข้อมูล Runtime, รวมถึง Memory และ Reactions เมื่อเปิดใช้งาน และไฟล์บริบทเสริมพร้อมเนื้อหาระบบ prompt เพิ่มเติม ส่วนต่างๆ จะถูกตัดแต่งสำหรับโหมด prompt ขั้นต่ำที่ใช้โดย subagents
Prompt ถูกใช้หลังจากสร้างเซสชันผ่าน applySystemPromptOverrideToSession():
typescriptconst systemPromptOverride = createSystemPromptOverride(appendPrompt); applySystemPromptOverrideToSession(session, systemPromptOverride);
การจัดการเซสชัน
ไฟล์เซสชัน
เซสชันเป็นไฟล์ JSONL พร้อมโครงสร้างต้นไม้ (การเชื่อมโยง id/parentId) SessionManager ของ Pi จัดการความคงอยู่:
typescriptconst sessionManager = SessionManager.open(params.sessionFile);
Mayros ห่อสิ่งนี้ด้วย guardSessionManager() สำหรับความปลอดภัยผลลัพธ์เครื่องมือ
การแคชเซสชัน
session-manager-cache.ts แคชอินสแตนซ์ SessionManager เพื่อหลีกเลี่ยงการแยกวิเคราะห์ไฟล์ซ้ำ:
typescriptawait prewarmSessionFile(params.sessionFile); sessionManager = SessionManager.open(params.sessionFile); trackSessionManagerAccess(params.sessionFile);
การจำกัดประวัติ
limitHistoryTurns() ตัดประวัติการสนทนาตามประเภทช่องทาง (DM vs กลุ่ม)
การบีบอัด
การบีบอัดอัตโนมัติเกิดขึ้นเมื่อบริบทล้น compactEmbeddedPiSessionDirect() จัดการการบีบอัดด้วยตนเอง:
typescriptconst compactResult = await compactEmbeddedPiSessionDirect({ sessionId, sessionFile, provider, model, ... });
การพิสูจน์ตัวตนและการแก้ไขโมเดล
โปรไฟล์ Auth
Mayros รักษาที่เก็บโปรไฟล์ auth พร้อม API keys หลายตัวต่อผู้ให้บริการ:
typescriptconst authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
โปรไฟล์หมุนเวียนเมื่อล้มเหลวพร้อมการติดตาม cooldown:
typescriptawait markAuthProfileFailure({ store, profileId, reason, cfg, agentDir }); const rotated = await advanceAuthProfile();
การแก้ไขโมเดล
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 กระตุ้น fallback โมเดลเมื่อกำหนดค่า:
typescriptif (fallbackConfigured && isFailoverErrorMessage(errorText)) { throw new FailoverError(errorText, { reason: promptFailoverReason ?? "unknown", provider, model: modelId, profileId, status: resolveFailoverStatus(promptFailoverReason), }); }
Pi Extensions
Mayros โหลด pi extensions แบบกำหนดเองสำหรับพฤติกรรมเฉพาะทาง:
Compaction Safeguard
pi-extensions/compaction-safeguard.ts เพิ่มราวกั้นให้กับการบีบอัด รวมถึงการจัดงบโทเค็นแบบปรับตัวพร้อมสรุปความล้มเหลวของเครื่องมือและการดำเนินการไฟล์:
typescriptif (resolveCompactionMode(params.cfg) === "safeguard") { setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare }); paths.push(resolvePiExtensionPath("compaction-safeguard")); }
Context Pruning
pi-extensions/context-pruning.ts ดำเนินการตัดแต่งบริบทตาม cache-TTL:
typescriptif (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") { setContextPruningRuntime(params.sessionManager, { settings, contextWindowTokens, isToolPrunable, lastCacheTouchAt, }); paths.push(resolvePiExtensionPath("context-pruning")); }
การสตรีมและการตอบกลับแบบบล็อก
การแบ่งชิ้นบล็อก
EmbeddedBlockChunker จัดการการสตรีมข้อความเป็นบล็อกการตอบกลับแยกกัน:
typescriptconst blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
การลอกแท็ก Thinking/Final
เอาต์พุตสตรีมถูกประมวลผลเพื่อลอกบล็อก <think>/<thinking> และดึงเนื้อหา <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 เช่น [[media:url]], [[voice]], [[reply:id]] ถูกแยกวิเคราะห์และดึงออก:
typescriptconst { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
การจัดการข้อผิดพลาด
การจำแนกข้อผิดพลาด
pi-embedded-helpers.ts จำแนกข้อผิดพลาดสำหรับการจัดการที่เหมาะสม:
typescriptisContextOverflowError(errorText) // บริบทใหญ่เกินไป isCompactionFailureError(errorText) // การบีบอัดล้มเหลว isAuthAssistantError(lastAssistant) // ความล้มเหลว Auth isRateLimitAssistantError(...) // Rate limited isFailoverAssistantError(...) // ควร failover classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
Thinking Level Fallback
หาก thinking level ไม่รองรับ จะ fallback:
typescriptconst fallbackThinking = pickFallbackThinkingLevel({ message: errorText, attempted: attemptedThinking, }); if (fallbackThinking) { thinkLevel = fallbackThinking; continue; }
การรวม Sandbox
เมื่อเปิดใช้งานโหมด sandbox เครื่องมือและเส้นทางจะถูกจำกัด:
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 }
การจัดการเฉพาะผู้ให้บริการ
Anthropic
- การขัดสตริงมายากลของการปฏิเสธ
- การตรวจสอบเทิร์นสำหรับ roles ที่ต่อเนื่อง
- ความเข้ากันได้กับพารามิเตอร์ Claude Code
Google/Gemini
- การแก้ไขลำดับเทิร์น (
applyGoogleTurnOrderingFix) - การทำความสะอาดสคีมาเครื่องมือ (
sanitizeToolsForGoogle) - การทำความสะอาดประวัติเซสชัน (
sanitizeSessionHistory)
OpenAI
- เครื่องมือ
apply_patchสำหรับโมเดล Codex - การจัดการ downgrade thinking level
การรวม TUI
Mayros ยังมีโหมด TUI โลคัลที่ใช้คอมโพเนนต์ pi-tui โดยตรง:
typescript// src/tui/tui.ts import { ... } from "@mariozechner/pi-tui";
สิ่งนี้มอบประสบการณ์เทอร์มินัลแบบโต้ตอบคล้ายกับโหมดเนทีฟของ pi
ความแตกต่างหลักจาก Pi CLI
| ด้าน | Pi CLI | Mayros Embedded |
|---|---|---|
| การเรียกใช้ | คำสั่ง pi / RPC | SDK ผ่าน createAgentSession() |
| เครื่องมือ | เครื่องมือ coding เริ่มต้น | ชุดเครื่องมือ Mayros แบบกำหนดเอง |
| ระบบ prompt | AGENTS.md + prompts | แบบไดนามิกต่อช่องทาง/บริบท |
| ที่เก็บเซสชัน | ~/.pi/agent/sessions/ | ~/.mayros/agents/<agentId>/sessions/ (หรือ $MAYROS_STATE_DIR/agents/<agentId>/sessions/) |
| การพิสูจน์ตัวตน | ข้อมูลรับรองเดียว | หลายโปรไฟล์พร้อมการหมุนเวียน |
| ส่วนขยาย | โหลดจากดิสก์ | แบบโปรแกรม + เส้นทางดิสก์ |
| การจัดการเหตุการณ์ | เรนเดอร์ TUI | แบบ callback (onBlockReply, ฯลฯ) |
ข้อพิจารณาในอนาคต
พื้นที่สำหรับการปรับปรุงที่อาจเกิดขึ้น:
- การจัดตำแหน่งลายเซ็นเครื่องมือ: ปัจจุบันปรับตัวระหว่างลายเซ็น pi-agent-core และ pi-coding-agent
- การห่อ session manager:
guardSessionManagerเพิ่มความปลอดภัยแต่เพิ่มความซับซ้อน - การโหลดส่วนขยาย: สามารถใช้
ResourceLoaderของ pi โดยตรงมากขึ้น - ความซับซ้อนของ streaming handler:
subscribeEmbeddedPiSessionได้ใหญ่ขึ้น - ความแปลกของผู้ให้บริการ: codepaths เฉพาะผู้ให้บริการจำนวนมากที่ pi อาจจัดการได้
การทดสอบ
การทดสอบที่มีอยู่ทั้งหมดที่ครอบคลุมการรวม pi และส่วนขยาย:
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