Pi統合アーキテクチャ

このドキュメントは、MayrosがAIエージェント機能を強化するために、pi-coding-agentとその兄弟パッケージ(pi-aipi-agent-corepi-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抽象化: ModelstreamSimple、メッセージタイプ、プロバイダーAPI
pi-agent-coreエージェントループ、ツール実行、AgentMessageタイプ
pi-coding-agent高レベルSDK: createAgentSessionSessionManagerAuthStorageModelRegistry、組み込みツール
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.tsrunEmbeddedPiAgent()です:

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. セッション作成

runEmbeddedAttempt()runEmbeddedPiAgent()によって呼び出される)内で、Pi SDKが使用されます:

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. イベントサブスクリプション

subscribeEmbeddedPiSession()は、PiのAgentSessionイベントをサブスクライブします:

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

処理されるイベントには次のものが含まれます:

  • message_start / message_end / message_update(ストリーミングテキスト/思考)
  • tool_execution_start / tool_execution_update / tool_execution_end
  • turn_start / turn_end
  • agent_start / agent_end
  • auto_compaction_start / auto_compaction_end

4. プロンプティング

セットアップ後、セッションがプロンプトされます:

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

SDKは完全なエージェントループを処理します:LLMへの送信、ツール呼び出しの実行、応答のストリーミング。

ツールアーキテクチャ

ツールパイプライン

  1. ベースツール: PiのcodingTools(read、bash、edit、write)
  2. カスタム置換: Mayrosはbashをexec/processに置き換え、サンドボックス用にread/edit/writeをカスタマイズ
  3. Mayrosツール: メッセージング、ブラウザ、canvas、セッション、cron、gatewayなど
  4. チャネルツール: Discord/Telegram/Slack/WhatsApp固有のアクションツール
  5. ポリシーフィルタリング: プロファイル、プロバイダー、エージェント、グループ、サンドボックスポリシーによってフィルタリングされたツール
  6. スキーマ正規化: Gemini/OpenAIの癖に合わせてクリーンアップされたスキーマ
  7. AbortSignalラッピング: アボートシグナルを尊重するためにラップされたツール

ツール定義アダプター

pi-agent-coreのAgentToolは、pi-coding-agentのToolDefinitionとは異なるexecuteシグネチャを持っています。pi-tool-definition-adapter.tsのアダプターがこれを橋渡しします:

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シグネチャはpi-agent-coreと異なる
      return await tool.execute(toolCallId, params, signal, onUpdate);
    },
  }));
}

ツール分割戦略

splitSdkTools()は、すべてのツールをcustomTools経由で渡します:

typescript
export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) {
  return {
    builtInTools: [], // 空。すべてを上書き
    customTools: toToolDefinitions(options.tools),
  };
}

これにより、Mayrosのポリシーフィルタリング、サンドボックス統合、拡張ツールセットがプロバイダー間で一貫性を保つことが保証されます。

システムプロンプト構築

システムプロンプトはbuildAgentSystemPrompt()system-prompt.ts)で構築されます。これは、ツール、ツール呼び出しスタイル、安全ガードレール、Mayros CLIリファレンス、スキル、ドキュメント、ワークスペース、サンドボックス、メッセージング、返信タグ、音声、サイレント返信、ハートビート、ランタイムメタデータ、有効な場合はメモリと反応、オプションのコンテキストファイルと追加のシステムプロンプトコンテンツを含むセクションを持つ完全なプロンプトを組み立てます。セクションは、サブエージェントが使用する最小限のプロンプトモード用にトリミングされます。

プロンプトは、applySystemPromptOverrideToSession()経由でセッション作成後に適用されます:

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

セッション管理

セッションファイル

セッションは、ツリー構造(id/parentIdリンク)を持つJSONLファイルです。PiのSessionManagerが永続化を処理します:

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

Mayrosは、ツール結果の安全性のためにguardSessionManager()でこれをラップします。

セッションキャッシング

session-manager-cache.tsは、繰り返しファイル解析を避けるためにSessionManagerインスタンスをキャッシュします:

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

履歴制限

limitHistoryTurns()は、チャネルタイプ(DM vs グループ)に基づいて会話履歴をトリミングします。

コンパクション

自動コンパクションは、コンテキストオーバーフロー時にトリガーされます。compactEmbeddedPiSessionDirect()が手動コンパクションを処理します:

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

認証とモデル解決

認証プロファイル

Mayrosは、プロバイダーごとに複数のAPIキーを持つ認証プロファイルストアを維持します:

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

プロファイルは、クールダウン追跡付きの失敗時にローテーションします:

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

モデル解決

typescript
import { 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は、設定されている場合にモデルフォールバックをトリガーします:

typescript
if (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は、適応型トークン予算、ツール失敗、ファイル操作要約を含むコンパクションにガードレールを追加します:

typescript
if (resolveCompactionMode(params.cfg) === "safeguard") {
  setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare });
  paths.push(resolvePiExtensionPath("compaction-safeguard"));
}

コンテキストプルーニング

pi-extensions/context-pruning.tsは、キャッシュTTLベースのコンテキストプルーニングを実装します:

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

ストリーミングとブロック返信

ブロックチャンキング

EmbeddedBlockChunkerは、ストリーミングテキストを個別の返信ブロックに管理します:

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

思考/最終タグストリッピング

ストリーミング出力は、<think>/<thinking>ブロックをストリップし、<final>コンテンツを抽出するために処理されます:

typescript
const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => {
  // <think>...</think>コンテンツをストリップ
  // enforceFinalTagの場合、<final>...</final>コンテンツのみを返す
};

返信ディレクティブ

[[media:url]][[voice]][[reply:id]]のような返信ディレクティブが解析および抽出されます:

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

エラー処理

エラー分類

pi-embedded-helpers.tsは、適切な処理のためにエラーを分類します:

typescript
isContextOverflowError(errorText)     // コンテキストが大きすぎる
isCompactionFailureError(errorText)   // コンパクション失敗
isAuthAssistantError(lastAssistant)   // 認証失敗
isRateLimitAssistantError(...)        // レート制限
isFailoverAssistantError(...)         // フェイルオーバーすべき
classifyFailoverReason(errorText)     // "auth" | "rate_limit" | "quota" | "timeout" | ...

思考レベルフォールバック

思考レベルがサポートされていない場合、フォールバックします:

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

サンドボックス統合

サンドボックスモードが有効な場合、ツールとパスが制約されます:

typescript
const 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 CLIMayros埋め込み
呼び出しpiコマンド / RPCcreateAgentSession()経由のSDK
ツールデフォルトコーディングツールカスタムMayrosツールスイート
システムプロンプトAGENTS.md + プロンプトチャネル/コンテキストごとに動的
セッションストレージ~/.pi/agent/sessions/~/.mayros/agents/<agentId>/sessions/(または$MAYROS_STATE_DIR/agents/<agentId>/sessions/
認証単一の認証情報ローテーション付きマルチプロファイル
拡張ディスクからロードプログラマティック + ディスクパス
イベント処理TUIレンダリングコールバックベース(onBlockReplyなど)

将来の考慮事項

再作業の可能性がある領域:

  1. ツールシグネチャの整合性: 現在、pi-agent-coreとpi-coding-agentシグネチャ間で適応
  2. セッションマネージャーラッピング: guardSessionManagerは安全性を追加しますが、複雑さを増加させます
  3. 拡張ロード: PiのResourceLoaderをより直接使用できる可能性
  4. ストリーミングハンドラーの複雑さ: subscribeEmbeddedPiSessionが大きくなっています
  5. プロバイダーの癖: Piが潜在的に処理できる多くのプロバイダー固有のコードパス

テスト

Pi統合とその拡張をカバーする既存のすべてのテスト:

  • src/agents/pi-embedded-block-chunker.test.ts
  • src/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.ts
  • src/agents/pi-tool-definition-adapter.test.ts
  • src/agents/pi-tools*.test.ts(ツール関連テスト)

完全なテストリストは、元のドキュメントの「Tests」セクションを参照してください。