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"
}
PaketTujuan
pi-aiAbstraksi LLM inti: Model, streamSimple, tipe pesan, API provider
pi-agent-coreLoop agen, eksekusi tool, tipe AgentMessage
pi-coding-agentSDK tingkat tinggi: createAgentSession, SessionManager, AuthStorage, ModelRegistry, tool bawaan
pi-tuiKomponen UI terminal (digunakan dalam mode TUI lokal Mayros)

Alur Integrasi Inti

1. Menjalankan Embedded Agent

Entry point utama adalah runEmbeddedPiAgent() di 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. Pembuatan Sesi

Di dalam runEmbeddedAttempt() (dipanggil oleh runEmbeddedPiAgent()), SDK pi digunakan:

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. Subscription Event

subscribeEmbeddedPiSession() berlangganan event AgentSession 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,
});

Event yang ditangani meliputi:

  • message_start / message_end / message_update (streaming teks/thinking)
  • 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

Setelah pengaturan, sesi diprompt:

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

SDK menangani loop agen lengkap: mengirim ke LLM, mengeksekusi tool call, streaming respons.

Arsitektur Tool

Pipeline Tool

  1. Base Tools: codingTools pi (read, bash, edit, write)
  2. Custom Replacement: Mayros mengganti bash dengan exec/process, menyesuaikan read/edit/write untuk sandbox
  3. Mayros Tools: messaging, browser, canvas, sessions, cron, gateway, dll.
  4. Channel Tools: Tool aksi spesifik Discord/Telegram/Slack/WhatsApp
  5. Policy Filtering: Tool difilter berdasarkan profil, provider, agen, grup, kebijakan sandbox
  6. Schema Normalization: Skema dibersihkan untuk quirk Gemini/OpenAI
  7. 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:

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);
    },
  }));
}

Strategi Tool Split

splitSdkTools() melewatkan semua tool melalui customTools:

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

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

Manajemen Sesi

File Sesi

Sesi adalah file JSONL dengan struktur pohon (penautan id/parentId). SessionManager Pi menangani persistensi:

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

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

Autentikasi & Resolusi Model

Profil Auth

Mayros memelihara penyimpanan profil auth dengan beberapa API key per provider:

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

Profil berputar pada kegagalan dengan pelacakan cooldown:

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

Resolusi Model

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);

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:

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

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

Perbedaan Utama dari Pi CLI

AspekPi CLIMayros Embedded
InvokasiPerintah pi / RPCSDK melalui createAgentSession()
ToolTool coding defaultSuite tool Mayros kustom
System promptAGENTS.md + promptDinamis per-channel/konteks
Penyimpanan sesi~/.pi/agent/sessions/~/.mayros/agents/<agentId>/sessions/ (atau $MAYROS_STATE_DIR/agents/<agentId>/sessions/)
AuthKredensial tunggalMulti-profil dengan rotasi
EkstensiDimuat dari diskProgrammatic + path disk
Penanganan eventRendering TUIBerbasis callback (onBlockReply, dll.)

Pertimbangan Masa Depan

Area untuk potensi pengerjaan ulang:

  1. Penyelarasan signature tool: Saat ini beradaptasi antara signature pi-agent-core dan pi-coding-agent
  2. Pembungkusan session manager: guardSessionManager menambahkan keamanan tetapi meningkatkan kompleksitas
  3. Pemuatan ekstensi: Dapat menggunakan ResourceLoader pi lebih langsung
  4. Kompleksitas handler streaming: subscribeEmbeddedPiSession telah tumbuh besar
  5. Quirk provider: Banyak codepath spesifik provider yang berpotensi ditangani pi