Pi統合アーキテクチャ
このドキュメントは、MayrosがAIエージェント機能を強化するために、pi-coding-agentとその兄弟パッケージ(pi-ai、pi-agent-core、pi-tui)とどのように統合されているかを説明します。
概要
MayrosはPi SDKを使用して、AIコーディングエージェントをメッセージングゲートウェイアーキテクチャに組み込みます。Piをサブプロセスとして生成したり、RPCモードを使用したりする代わりに、MayrosはcreateAgentSession()経由でPiのAgentSessionを直接インポートして インスタンス化します。この組み込みアプローチは次のことを提供します:
- セッションライフサイクルとイベント処理の完全な制御
- カスタムツールインジェクション(メッセージング、サンドボックス、チャネル固有のアクション)
- チャネル/コンテキストごとのシステムプロンプトカスタマイズ
- ブランチング/コンパクションサポート付きセッション永続化
- フェイルオーバー付きマルチアカウント認証プロファイルローテーション
- プロバイダー非依存のモデル切り替え
パッケージの依存関係
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 | エージェントループ、ツール実行、AgentMessageタイプ |
pi-coding-agent | 高レベルSDK: createAgentSession、SessionManager、AuthStorage、ModelRegistry、組み込みツール |
pi-tui | ターミナルUIコンポーネント(MayrosのローカルTUIモードで使用) |
ファイル構造
src/agents/
├── pi-embedded-runner.ts # pi-embedded-runner/から再エクスポート
├── pi-embedded-runner/
│ ├── run.ts # メインエントリ: runEmbeddedPiAgent()
│ ├── run/
│ │ ├── attempt.ts # セッションセットアップ付き単一試行ロジック
│ │ ├── params.ts # RunEmbeddedPiAgentParams型
│ │ ├── payloads.ts # 実行結果から応答ペイロードを構築
│ │ ├── images.ts # ビジョンモデル画像インジェクション
│ │ └── types.ts # EmbeddedRunAttemptResult
│ ├── abort.ts # アボートエラー検出
│ ├── cache-ttl.ts # コンテキストプルーニング用キャッシュTTL追跡
│ ├── compact.ts # 手動/自動コンパクションロジック
│ ├── extensions.ts # 埋め込み実行用Pi拡張をロード
│ ├── extra-params.ts # プロバイダー固有ストリームパラメータ
│ ├── google.ts # Google/Geminiターン順序修正
│ ├── history.ts # 履歴制限(DM vs グループ)
│ ├── lanes.ts # セッション/グローバルコマンドレーン
│ ├── logger.ts # サブシステムロガー
│ ├── model.ts # ModelRegistry経由のモデル解決
│ ├── runs.ts # アクティブ実行追跡、アボート、キュー
│ ├── sandbox-info.ts # システムプロンプト用サンドボックス情報
│ ├── session-manager-cache.ts # SessionManagerインスタンスキャッシュ
│ ├── session-manager-init.ts # セッションファイル初期化
│ ├── system-prompt.ts # システムプロンプトビルダー
│ ├── 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 # ツール許可リスト/拒否リストポリシー
├── pi-tools.read.ts # 読み取りツールカスタマイズ
├── pi-tools.schema.ts # ツールスキーマ正規化
├── pi-tools.types.ts # AnyAgentTool型エイリアス
├── pi-tool-definition-adapter.ts # AgentTool -> ToolDefinitionアダプター
├── pi-settings.ts # 設定上書き
├── pi-extensions/ # カスタムPi拡張
│ ├── compaction-safeguard.ts # セーフガード拡張
│ ├── compaction-safeguard-runtime.ts
│ ├── context-pruning.ts # キャッシュTTLコンテキストプルーニング拡張
│ └── context-pruning/
├── model-auth.ts # 認証プロファイル解決
├── auth-profiles.ts # プロファイルストア、クールダウン、フェイルオーバー
├── 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 # システムプロンプトパラメータ解決
├── system-prompt-report.ts # デバッグレポート生成
├── tool-summaries.ts # ツール説明要約
├── tool-policy.ts # ツールポリシー解決
├── transcript-policy.ts # トランスクリプト検証ポリシー
├── skills.ts # スキルスナップショット/プロンプト構築
├── skills/ # スキルサブシステム
├── sandbox.ts # サンドボックスコンテキスト解決
├── 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. 埋め込みエージェントの実行
メインエントリポイントはpi-embedded-runner/run.tsのrunEmbeddedPiAgent()です:
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()は、PiのAgentSessionイベントをサブスクライブします:
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. プロンプティング
セットアップ後、セッションがプロンプトされます:
typescriptawait session.prompt(effectivePrompt, { images: imageResult.images });
SDKは完全なエージェントループを処理します:LLMへの送信、ツール呼び出しの実行、応答のストリーミング。
ツールアーキテクチャ
ツールパイプライン
- ベースツール: Piの
codingTools(read、bash、edit、write) - カスタム置換: Mayrosはbashを
exec/processに置き換え、サンドボックス用にread/edit/writeをカスタマイズ - Mayrosツール: メッセージング、ブラウザ、canvas、セッション、cron、gatewayなど
- チャネルツール: Discord/Telegram/Slack/WhatsApp固有のアクションツール
- ポリシーフィルタリング: プロファイル、プロバイダー、エージェント、グループ、サンドボックスポリシーによってフィルタリングされたツール
- スキーマ正規化: Gemini/OpenAIの癖に合わせてクリーンアップされたスキーマ
- AbortSignalラッピング: アボートシグナルを尊重するためにラップされたツール
ツール定義アダプター
pi-agent-coreのAgentToolは、pi-coding-agentのToolDefinitionとは異なるexecuteシグネチャを持っています。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シグネチャはpi-agent-coreと異なる return await tool.execute(toolCallId, params, signal, onUpdate); }, })); }
ツール分割戦略
splitSdkTools()は、すべてのツールをcustomTools経由で渡します:
typescriptexport function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) { return { builtInTools: [], // 空。すべてを上書き customTools: toToolDefinitions(options.tools), }; }
これにより、Mayrosのポリシーフィルタリング、サンドボックス統合、拡張ツールセットがプロバイダー間で一貫性を保つことが保証されます。
システムプロンプト構築
システムプロンプトはbuildAgentSystemPrompt()(system-prompt.ts)で構築されます。これは、ツール、ツール呼び出しスタイル、安全ガードレール、Mayros CLIリファレンス、スキル、ドキュメント、ワークスペース、サンドボックス、メッセージング、返信タグ、音声、サイレント返信、ハートビート、ランタイムメタデータ、有効な場合はメモリと反応、オプションのコンテキストファイルと追加のシステムプロンプトコンテンツを含むセクションを持つ完全なプロンプトを組み立てます。セクションは、サブエージェントが使用する最小限のプロンプトモード用にトリミングされます。
プロンプトは、applySystemPromptOverrideToSession()経由でセッション作成後に適用されます:
typescriptconst systemPromptOverride = createSystemPromptOverride(appendPrompt); applySystemPromptOverrideToSession(session, systemPromptOverride);
セッション管理
セッションファイル
セッションは、ツリー構造(id/parentIdリンク)を持つJSONLファイルです。PiのSessionManagerが永続化を処理します:
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, ... });
認証とモデル解決
認証プロファイル
Mayrosは、プロバイダーごとに複数のAPIキーを持つ認証プロファイルストアを維持します:
typescriptconst authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
プロファイルは、クールダウン追跡付きの失敗時にローテーションします:
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, ); // PiのModelRegistryとAuthStorageを使用 authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);
フェイルオーバー
FailoverErrorは、設定されている場合にモデルフォールバックをトリガーします:
typescriptif (fallbackConfigured && isFailoverErrorMessage(errorText)) { throw new FailoverError(errorText, { reason: promptFailoverReason ?? "unknown", provider, model: modelId, profileId, status: resolveFailoverStatus(promptFailoverReason), }); }
Pi拡張
Mayrosは、特殊な動作のためにカスタムPi拡張をロードします:
コンパクションセーフガード
pi-extensions/compaction-safeguard.tsは、適応型トークン予算、ツール失敗、ファイル操作要約を含むコンパクションにガードレールを追加します:
typescriptif (resolveCompactionMode(params.cfg) === "safeguard") { setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare }); paths.push(resolvePiExtensionPath("compaction-safeguard")); }
コンテキストプルーニング
pi-extensions/context-pruning.tsは、キャッシュ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;
思考/最終タグストリッピング
ストリーミング出力は、<think>/<thinking>ブロックをストリップし、<final>コンテンツを抽出するために処理されます:
typescriptconst stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => { // <think>...</think>コンテンツをストリップ // enforceFinalTagの場合、<final>...</final>コンテンツのみを返す };
返信ディレクティブ
[[media:url]]、[[voice]]、[[reply:id]]のような返信ディレクティブが解析および抽出されます:
typescriptconst { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
エラー処理
エラー分類
pi-embedded-helpers.tsは、適切な処理のためにエラーを分類します:
typescriptisContextOverflowError(errorText) // コンテキストが大きすぎる isCompactionFailureError(errorText) // コンパクション失敗 isAuthAssistantError(lastAssistant) // 認証失敗 isRateLimitAssistantError(...) // レート制限 isFailoverAssistantError(...) // フェイルオーバーすべき classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
思考レベルフォールバック
思考レベルがサポートされていない場合、フォールバックします:
typescriptconst fallbackThinking = pickFallbackThinkingLevel({ message: errorText, attempted: attemptedThinking, }); if (fallbackThinking) { thinkLevel = fallbackThinking; continue; }
サンドボックス統合
サンドボックスモードが有効な場合、ツールとパスが制約されます:
typescriptconst sandbox = await resolveSandboxContext({ config: params.config, sessionKey: sandboxSessionKey, workspaceDir: resolvedWorkspace, }); if (sandboxRoot) { // サンドボックス化されたread/edit/writeツールを使用 // Execはコンテナで実行 // ブラウザはブリッジURLを使用 }
プロバイダー固有の処理
Anthropic
- リフューザルマジック文字列スクラビング
- 連続した役割のターン検証
- Claude Codeパラメータ互換性
Google/Gemini
- ターン順序修正(
applyGoogleTurnOrderingFix) - ツールスキーマサニタイゼーション(
sanitizeToolsForGoogle) - セッション履歴サニタイゼーション(
sanitizeSessionHistory)
OpenAI
- Codexモデル用
apply_patchツール - 思考レベルダウングレード処理
TUI統合
Mayrosには、Pi-TUIコンポーネントを直接使用するローカルTUIモードもあります:
typescript// src/tui/tui.ts import { ... } from "@mariozechner/pi-tui";
これにより、Piのネイティブモードと同様のインタラクティブなターミナル体験が提供されます。
Pi CLIとの主な違い
| 側面 | Pi CLI | Mayros埋め込み |
|---|---|---|
| 呼び出し | piコマンド / RPC | createAgentSession()経由のSDK |
| ツール | デフォルトコーディングツール | カスタムMayrosツールスイート |
| システムプロンプト | AGENTS.md + プロンプト | チャネル/コンテキストごとに動的 |
| セッションストレージ | ~/.pi/agent/sessions/ | ~/.mayros/agents/<agentId>/sessions/(または$MAYROS_STATE_DIR/agents/<agentId>/sessions/) |
| 認証 | 単一の認証情報 | ローテーション付きマルチプロファイル |
| 拡張 | ディスクからロード | プログラマティック + ディスクパス |
| イベント処理 | TUIレンダリング | コールバックベース(onBlockReplyなど) |
将来の考慮事項
再作業の可能性がある領域:
- ツールシグネチャの整合性: 現在、pi-agent-coreとpi-coding-agentシグネチャ間で適応
- セッションマネージャーラッピング:
guardSessionManagerは安全性を追加しますが、複雑さを増加させます - 拡張ロード: Piの
ResourceLoaderをより直接使用できる可能性 - ストリーミングハンドラーの複雑さ:
subscribeEmbeddedPiSessionが大きくなっています - プロバイダーの癖: Piが潜在的に処理できる多くのプロバイダー固有のコードパス
テスト
Pi統合とその拡張をカバーする既存のすべてのテスト:
src/agents/pi-embedded-block-chunker.test.tssrc/agents/pi-embedded-helpers.*.test.ts(多数のヘルパーテスト)src/agents/pi-embedded-runner*.test.ts(実行とコンパクションテスト)src/agents/pi-embedded-subscribe.*.test.ts(サブスクリプションとイベントテスト)src/agents/pi-extensions/*.test.ts(拡張テスト)src/agents/pi-settings.test.tssrc/agents/pi-tool-definition-adapter.test.tssrc/agents/pi-tools*.test.ts(ツール関連テスト)
完全なテストリストは、元のドキュメントの「Tests」セクションを参照してください。