SDK
pi は、SDK の使用に役立ちます。ユースケースに合わせた統合を構築するよう依頼してください。
SDK は、pi のエージェント機能へのプログラムによるアクセスを提供します。これを使用して、他のアプリケーションに pi を埋め込んだり、カスタム インターフェイスを構築したり、自動化されたワークフローと統合したりできます。
使用例の例:
- カスタム UI (Web、デスクトップ、モバイル) を構築する
- エージェント機能を既存のアプリケーションに統合する
- エージェント推論を使用して自動化されたパイプラインを作成する
- サブエージェントを生成するカスタム ツールを構築する
- エージェントの動作をプログラムでテストする
最小限の制御から完全な制御までの実際の例については、examples/sdk/ を参照してください。
クイックスタート
import { createAgentSession, ModelRuntime, SessionManager } from "@earendil-works/pi-coding-agent";
const modelRuntime = await ModelRuntime.create();
const { session } = await createAgentSession({
sessionManager: SessionManager.inMemory(),
modelRuntime,
});
session.subscribe((event) => {
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
await session.prompt("What files are in the current directory?");インストール
npm install @earendil-works/pi-coding-agentSDK はメインパッケージに含まれています。別途インストールする必要はありません。
中心となる概念
createAgentSession()
単一の AgentSession のメインのファクトリー関数。
createAgentSession() は、ResourceLoader を使用して、拡張機能、スキル、prompt templates、テーマ、および context files を提供します。指定しない場合は、標準の検出で DefaultResourceLoader が使用されます。
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
// Minimal: defaults with DefaultResourceLoader
const { session } = await createAgentSession();
// Custom: override specific options
const { session } = await createAgentSession({
model: myModel,
tools: ["read", "bash"],
sessionManager: SessionManager.inMemory(),
});エージェントセッション
セッションは、エージェントのライフサイクル、メッセージ履歴、モデルの状態、圧縮、およびイベント ストリーミングを管理します。
interface AgentSession {
// Send a prompt and wait for completion
prompt(text: string, options?: PromptOptions): Promise<void>;
// Queue messages during streaming
steer(text: string): Promise<void>;
followUp(text: string): Promise<void>;
// Subscribe to events (returns unsubscribe function)
subscribe(listener: (event: AgentSessionEvent) => void): () => void;
// Session info
sessionFile: string | undefined;
sessionId: string;
// Model control
setModel(model: Model): Promise<void>;
setThinkingLevel(level: ThinkingLevel): void;
cycleModel(): Promise<ModelCycleResult | undefined>;
cycleThinkingLevel(): ThinkingLevel | undefined;
// State access
agent: Agent;
model: Model | undefined;
thinkingLevel: ThinkingLevel;
messages: AgentMessage[];
isStreaming: boolean;
// In-place tree navigation within the current session file
navigateTree(targetId: string, options?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string }): Promise<{ editorText?: string; cancelled: boolean }>;
// Compaction
compact(customInstructions?: string): Promise<CompactionResult>;
abortCompaction(): void;
// Abort current operation
abort(): Promise<void>;
// Cleanup
dispose(): void;
}新しいセッション、再開、フォーク、インポートなどのセッション置換 API は、AgentSession ではなく AgentSessionRuntime にライブになります。
createAgentSessionRuntime() と AgentSessionRuntime
アクティブなセッションを置き換えて、CWD バウンドのランタイム状態を再構築する必要がある場合は、ランタイム API を使用します。 これは、組み込みのインタラクティブ、印刷、および RPC モードで使用されるのと同じレイヤーです。
createAgentSessionRuntime() は、ランタイム ファクトリと初期 cwd/セッション ターゲットを受け取ります。ファクトリは、プロセス グローバルの固定入力を閉じ、有効な cwd に対して cwd バインドされたサービスを再作成し、それらのサービスに対してセッション オプションを解決し、完全な実行時結果を返します。
import {
type CreateAgentSessionRuntimeFactory,
createAgentSessionFromServices,
createAgentSessionRuntime,
createAgentSessionServices,
getAgentDir,
SessionManager,
} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
const services = await createAgentSessionServices({ cwd });
return {
...(await createAgentSessionFromServices({
services,
sessionManager,
sessionStartEvent,
})),
services,
diagnostics: services.diagnostics,
};
};
const runtime = await createAgentSessionRuntime(createRuntime, {
cwd: process.cwd(),
agentDir: getAgentDir(),
sessionManager: SessionManager.create(process.cwd()),
});AgentSessionRuntime は、以下のアクティブなランタイムの置き換えを所有しています。
newSession()switchSession()fork()- クローンは
fork(entryId, { position: "at" })経由でフローします importFromJsonl()
重要な行動:
- これらの操作後の
runtime.sessionの変化 - イベントのサブスクリプションは特定の
AgentSessionに関連付けられているため、置換後に再サブスクライブしてください - 内線番号を使用している場合は、新しいセッションのためにもう一度
runtime.session.bindExtensions(...)に電話してください - 作成により
runtime.diagnosticsに診断が返されます - ランタイムの作成または置換が失敗した場合、メソッドがスローされ、呼び出し元がそれを処理する方法を決定します。
let session = runtime.session;
let unsubscribe = session.subscribe(() => {});
await runtime.newSession();
unsubscribe();
session = runtime.session;
unsubscribe = session.subscribe(() => {});プロンプトとメッセージキューイング
PromptOptions は、プロンプトの拡張、ストリーミング中のキューイング動作、およびプロンプトのプリフライト通知を制御します。
interface PromptOptions {
expandPromptTemplates?: boolean;
images?: ImageContent[];
streamingBehavior?: "steer" | "followUp";
source?: InputSource;
preflightResult?: (success: boolean) => void;
}preflightResult は、prompt() の呼び出しごとに 1 回呼び出されます。
trueプロンプトが受け入れられたか、キューに入れられたか、すぐに処理されたときfalseプロンプトプリフライトが受け入れ前に拒否された場合
prompt() が解決される前に発動します。 prompt() は、再試行を含め、受け入れられたすべての実行が終了した後にのみ解決されます。受け入れ後の失敗は、preflightResult(false) ではなく、通常のイベントとメッセージ ストリームを通じて報告されます。
prompt() メソッドは、prompt templates、拡張コマンド、およびメッセージ送信を処理します。
// Basic prompt (when not streaming)
await session.prompt("What files are here?");
// With images
await session.prompt("What's in this image?", {
images: [{ type: "image", source: { type: "base64", mediaType: "image/png", data: "..." } }]
});
// During streaming: must specify how to queue the message
await session.prompt("Stop and do this instead", { streamingBehavior: "steer" });
await session.prompt("After you're done, also check X", { streamingBehavior: "followUp" });行動:
- 拡張コマンド (例:
/mycommand): ストリーミング中でもすぐに実行されます。彼らは、pi.sendMessage()を介して独自の LLM インタラクションを管理します。 - ファイルベース prompt templates (
.mdファイルから): 送信またはキューに入れる前にコンテンツに展開されます。 streamingBehaviorを使用しないストリーミング中: エラーがスローされます。steer()またはfollowUp()を直接使用するか、オプションを指定します。preflightResult(true): プロンプトが受け入れられたか、キューに入れられたか、すぐに処理されたことを意味します。preflightResult(false): 受け入れられる前にプリフライトが拒否されたことを意味します。
ストリーミング中の明示的なキューイングの場合:
// Queue a steering message for delivery after the current assistant turn finishes its tool calls
await session.steer("New instruction");
// Wait for agent to finish (delivered only when agent stops)
await session.followUp("After you're done, also do this");steer() と followUp() はどちらもファイルベースの prompt templates を展開しますが、拡張コマンドでエラーが発生します (拡張コマンドをキューに入れることができません)。
エージェントとエージェント状態
Agent クラス (@earendil-works/pi-agent-core から) は、コア LLM インタラクションを処理します。 session.agent からアクセスしてください。
// Access current state
const state = session.agent.state;
// state.messages: AgentMessage[] - conversation history
// state.model: Model - current model
// state.thinkingLevel: ThinkingLevel - current thinking level
// state.systemPrompt: string - system prompt
// state.tools: AgentTool[] - available tools
// state.streamingMessage?: AgentMessage - current partial assistant message
// state.errorMessage?: string - latest assistant error
// Replace messages (useful for branching or restoration)
session.agent.state.messages = messages; // copies the top-level array
// Replace tools
session.agent.state.tools = tools; // copies the top-level array
// Wait for agent to finish processing
await session.agent.waitForIdle();イベント
イベントをサブスクライブして、ストリーミング出力とライフサイクル通知を受け取ります。
session.subscribe((event) => {
switch (event.type) {
// Streaming text from assistant
case "message_update":
if (event.assistantMessageEvent.type === "text_delta") {
process.stdout.write(event.assistantMessageEvent.delta);
}
if (event.assistantMessageEvent.type === "thinking_delta") {
// Thinking output (if thinking enabled)
}
break;
// Tool execution
case "tool_execution_start":
console.log(`Tool: ${event.toolName}`);
break;
case "tool_execution_update":
// Streaming tool output
break;
case "tool_execution_end":
console.log(`Result: ${event.isError ? "error" : "success"}`);
break;
// Message lifecycle
case "message_start":
// New message starting
break;
case "message_end":
// Message complete
break;
// Agent lifecycle
case "agent_start":
// Agent started processing prompt
break;
case "agent_end":
// Agent finished (event.messages contains new messages)
break;
// Turn lifecycle (one LLM response + tool calls)
case "turn_start":
break;
case "turn_end":
// event.message: assistant response
// event.toolResults: tool results from this turn
break;
// Session events (queue, compaction, retry)
case "queue_update":
console.log(event.steering, event.followUp);
break;
case "compaction_start":
case "compaction_end":
case "auto_retry_start":
case "auto_retry_end":
case "summarization_retry_scheduled":
case "summarization_retry_attempt_start":
case "summarization_retry_finished":
break;
}
});オプションのリファレンス
ディレクトリ
const { session } = await createAgentSession({
// Working directory for DefaultResourceLoader discovery
cwd: process.cwd(), // default
// Global config directory
agentDir: "~/.pi/agent", // default (expands ~)
});cwd は、DefaultResourceLoader によって次の目的で使用されます。
- プロジェクトの拡張 (
.pi/extensions/) - プロジェクトスキル:
.pi/skills/cwdの.agents/skills/および祖先ディレクトリ (git リポジトリのルート、またはリポジトリにない場合はファイルシステムのルートまで)
- プロジェクトのプロンプト (
.pi/prompts/) - コンテキスト ファイル (cwd からウォーキングアップする
AGENTS.md) - セッションディレクトリの命名
agentDir は、DefaultResourceLoader によって次の目的で使用されます。
- グローバル拡張機能 (
extensions/) - グローバルスキル:
agentDirの下のskills/(例:~/.pi/agent/skills/)~/.agents/skills/
- グローバルプロンプト (
prompts/) - グローバルコンテキストファイル (
AGENTS.md) - 設定 (
settings.json) - カスタムモデル (
models.json) - 資格情報 (
auth.json) - セッション (
sessions/)
カスタムの ResourceLoader、cwd、および agentDir はリソース検出を制御しなくなります。これらは依然としてセッションの名前付けとツール パスの解決に影響します。
モデル
import { getModel } from "@earendil-works/pi-ai";
import { ModelRuntime } from "@earendil-works/pi-coding-agent";
const modelRuntime = await ModelRuntime.create();
// Find specific built-in model (doesn't check if API key exists)
const opus = getModel("anthropic", "claude-opus-4-5");
if (!opus) throw new Error("Model not found");
// Find any model by provider/id, including custom models from models.json
// (doesn't check if API key exists)
const customModel = modelRuntime.getModel("my-provider", "my-model");
// Get only models that have valid authentication configured
const available = await modelRuntime.getAvailable();
const { session } = await createAgentSession({
model: opus,
thinkingLevel: "medium", // off, minimal, low, medium, high, xhigh, max
// Models for cycling (Ctrl+P in interactive mode)
scopedModels: [
{ model: opus, thinkingLevel: "high" },
{ model: haiku, thinkingLevel: "off" },
],
modelRuntime,
});モデルが指定されていない場合:
- セッションからの復元を試行します (続行する場合)
- 設定のデフォルトを使用します
- 最初に利用可能なモデルにフォールバックします
CLI モデル解析と一致させるには、エクスポートされたリゾルバー ヘルパーを使用します。
import {
resolveCliModel,
resolveModelScopeWithDiagnostics,
} from "@earendil-works/pi-coding-agent";
const cliModel = resolveCliModel({
cliModel: "anthropic/claude-opus-4-5:high",
modelRuntime,
});
if (cliModel.error) throw new Error(cliModel.error);
if (cliModel.warning) console.warn(cliModel.warning);
const { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(
["anthropic/*:high", "gpt-5"],
modelRuntime,
);
for (const diagnostic of diagnostics) {
console.warn(diagnostic.message);
}resolveCliModel() は登録されているすべてのモデルを使用するため、--api-key スタイルの初回セットアップでは、保存された認証が存在する前にモデルを解決できます。 resolveModelScopeWithDiagnostics() は、警告を出力するのではなく返しながら、--models および enabledModels のセマンティクスと一致します。
API キーと OAuth
認証解決の優先順位 (ModelRuntime によって処理):
- ランタイムオーバーライド (
setRuntimeApiKey経由、永続化されない) auth.jsonに保存された認証情報 (API key または OAuth トークン)- 環境変数 (
ANTHROPIC_API_KEY、OPENAI_API_KEYなど) - フォールバック リゾルバー (
models.jsonからのカスタム プロバイダー キー用)
import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
import { createAgentSession, ModelRuntime } from "@earendil-works/pi-coding-agent";
// Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.json
const modelRuntime = await ModelRuntime.create();
// Provider-owned auth methods and current status
for (const provider of modelRuntime.getProviders()) {
const status = await modelRuntime.checkAuth(provider.id);
console.log(provider.name, provider.auth, status);
}
// Runtime API key override (not persisted to disk)
await modelRuntime.setRuntimeApiKey("anthropic", "sk-my-temp-key");
// Custom credential and model locations
const customRuntime = await ModelRuntime.create({
authPath: "/my/app/auth.json",
modelsPath: "/my/app/models.json",
});
// Or inject any pi-ai CredentialStore
const credentials = new InMemoryCredentialStore();
const inMemoryRuntime = await ModelRuntime.create({ credentials });
const { session } = await createAgentSession({
modelRuntime: customRuntime,
});login()、logout()、setRuntimeApiKey()、および removeRuntimeApiKey() は、影響を受けるプロバイダーのキャッシュ/組み込みカタログ、構成、および可用性スナップショットがローカルで一貫した後に解決されます。リモート カタログの鮮度を待ちません。資格情報がコミットされたがローカル同期が失敗した場合、エクスポートされた CredentialSynchronizationError で拒否されます。資格情報の変更を盲目的に再試行するのではなく、その providerId、operation、credential、および cause フィールドを検査します。
パブリック モデル/認証操作と ModelRuntime.create({ signal }) はオプションの中止シグナルを受け入れ、省略された場合は制限がありません。 SDK アプリケーション独自のリモート カタログの鮮度に関する期限ポリシー:
const signal = AbortSignal.timeout(15_000);
const result = await modelRuntime.refresh({
providers: ["anthropic"],
signal,
});
if (result.aborted) console.warn("Catalog refresh timed out; using cached models");
for (const [providerId, error] of result.errors) {
console.warn(`Could not refresh ${providerId}:`, error);
}ネットワーク更新が失敗またはタイムアウトしても、成功した認証情報操作は取り消されません。 refresh() は新しいプロバイダーの世代を開始するため、古い停止した更新の後に待機せず、その後古い世代を公開することはできません。
システムプロンプト
ResourceLoader を使用してシステム プロンプトをオーバーライドします。
import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({
systemPromptOverride: () => "You are a helpful assistant.",
});
await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });ツール
有効にする組み込みツールを指定します。
- 内蔵ツール名:
read、bash、edit、write、grep、find、ls - デフォルトの組み込み:
read、bash、edit、write noTools: "all"はすべてのツールを無効にしますnoTools: "builtin"は、拡張機能とカスタム ツールを有効にしたまま、デフォルトの組み込みを無効にしますexcludeToolsは、tools許可リストが適用された後、特定の組み込み、拡張、またはカスタム ツール名を無効にします
edit ツールは、Pi の TUI ディスプレイには details.diff を返し、SDK 消費者には標準統合パッチとして details.patch を返します。
import { createAgentSession } from "@earendil-works/pi-coding-agent";
// Read-only mode
const { session } = await createAgentSession({
tools: ["read", "grep", "find", "ls"],
});
// Pick specific tools
const { session } = await createAgentSession({
tools: ["read", "bash", "grep"],
});
// Disable one tool while keeping the rest available
const { session } = await createAgentSession({
excludeTools: ["ask_question"],
});カスタム cwd を使用したツール
カスタム cwd を渡すと、createAgentSession() はその cwd 用に選択された組み込みツールを構築します。
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
const cwd = "/path/to/project";
// Use default tools for custom cwd
const { session } = await createAgentSession({
cwd,
sessionManager: SessionManager.inMemory(cwd),
});
// Or pick specific tools for custom cwd
const { session } = await createAgentSession({
cwd,
tools: ["read", "bash", "grep"],
sessionManager: SessionManager.inMemory(cwd),
});カスタムツール
import { Type } from "typebox";
import { createAgentSession, defineTool } from "@earendil-works/pi-coding-agent";
// Inline custom tool
const myTool = defineTool({
name: "my_tool",
label: "My Tool",
description: "Does something useful",
parameters: Type.Object({
input: Type.String({ description: "Input value" }),
}),
execute: async (_toolCallId, params) => ({
content: [{ type: "text", text: `Result: ${params.input}` }],
details: {},
}),
});
// Pass custom tools directly
const { session } = await createAgentSession({
customTools: [myTool],
});スタンドアロン定義および customTools: [myTool] のような配列には defineTool() を使用します。 Inline pi.registerTool({... }) はすでにパラメーターの型を正しく推論しています。
customTools 経由で渡されたカスタム ツールは、拡張機能に登録されたツールと結合されます。 ResourceLoader によってロードされた Extensions は、pi.registerTool() 経由でツールを登録することもできます。
tools を渡す場合は、有効にする各カスタム ツールまたは拡張ツールの名前を含めます (例: tools: ["read", "bash", "my_tool"])。
Extensions
Extensions は ResourceLoader によってロードされます。 DefaultResourceLoader は、~/.pi/agent/extensions/、.pi/extensions/、settings.json 拡張ソースから拡張機能を検出します。
import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({
additionalExtensionPaths: ["/path/to/my-extension.ts"],
extensionFactories: [
(pi) => {
pi.on("agent_start", () => {
console.log("[Inline Extension] Agent starting");
});
},
],
});
await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });Extensions は、ツールの登録、イベントのサブスクライブ、コマンドの追加などを行うことができます。 API の詳細については、extensions.md を参照してください。
名前付きインライン拡張機能: デフォルトでは、インライン ファクトリは起動時の Extensions リストに <inline:1>、<inline:2> などとして表示されます。代わりにわかりやすい名前を表示するには、ファクトリをラップします。
import type { InlineExtension } from "@earendil-works/pi-coding-agent";
const myProvider: InlineExtension = {
name: "my-provider",
factory: (pi) => {
pi.on("agent_start", () => {
console.log("[my-provider] Agent starting");
});
},
};
const loader = new DefaultResourceLoader({
extensionFactories: [myProvider],
});これは、<inline:1> ではなく <inline:my-provider> と表示されます。ベア ファクトリ関数は、下位互換性のために引き続き受け入れられます。
イベント バス: Extensions は pi.events 経由で通信できます。外部から送信またはリッスンする必要がある場合は、共有の eventBus を DefaultResourceLoader に渡します。
import { createEventBus, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const eventBus = createEventBus();
const loader = new DefaultResourceLoader({
eventBus,
});
await loader.reload();
eventBus.on("my-extension:status", (data) => console.log(data));Skills
import {
createAgentSession,
DefaultResourceLoader,
type Skill,
} from "@earendil-works/pi-coding-agent";
const customSkill: Skill = {
name: "my-skill",
description: "Custom instructions",
filePath: "/path/to/SKILL.md",
baseDir: "/path/to",
source: "custom",
};
const loader = new DefaultResourceLoader({
skillsOverride: (current) => ({
skills: [...current.skills, customSkill],
diagnostics: current.diagnostics,
}),
});
await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });コンテキストファイル
import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({
agentsFilesOverride: (current) => ({
agentsFiles: [
...current.agentsFiles,
{ path: "/virtual/AGENTS.md", content: "# Guidelines\n\n- Be concise" },
],
}),
});
await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });スラッシュコマンド
import {
createAgentSession,
DefaultResourceLoader,
type PromptTemplate,
} from "@earendil-works/pi-coding-agent";
const customCommand: PromptTemplate = {
name: "deploy",
description: "Deploy the application",
source: "(custom)",
content: "# Deploy\n\n1. Build\n2. Test\n3. Deploy",
};
const loader = new DefaultResourceLoader({
promptsOverride: (current) => ({
prompts: [...current.prompts, customCommand],
diagnostics: current.diagnostics,
}),
});
await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });セッション管理
セッションは、id/parentId リンクを持つツリー構造を使用し、インプレース分岐を可能にします。
import {
type CreateAgentSessionRuntimeFactory,
createAgentSession,
createAgentSessionFromServices,
createAgentSessionRuntime,
createAgentSessionServices,
getAgentDir,
SessionManager,
} from "@earendil-works/pi-coding-agent";
// In-memory (no persistence)
const { session } = await createAgentSession({
sessionManager: SessionManager.inMemory(),
});
// New persistent session
const { session: persisted } = await createAgentSession({
sessionManager: SessionManager.create(process.cwd()),
});
// Continue most recent
const { session: continued, modelFallbackMessage } = await createAgentSession({
sessionManager: SessionManager.continueRecent(process.cwd()),
});
if (modelFallbackMessage) {
console.log("Note:", modelFallbackMessage);
}
// Open specific file
const { session: opened } = await createAgentSession({
sessionManager: SessionManager.open("/path/to/session.jsonl"),
});
// List sessions
const currentProjectSessions = await SessionManager.list(process.cwd());
const allSessions = await SessionManager.listAll(process.cwd());
// Session replacement API for /new, /resume, /fork, /clone, and import flows.
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
const services = await createAgentSessionServices({ cwd });
return {
...(await createAgentSessionFromServices({
services,
sessionManager,
sessionStartEvent,
})),
services,
diagnostics: services.diagnostics,
};
};
const runtime = await createAgentSessionRuntime(createRuntime, {
cwd: process.cwd(),
agentDir: getAgentDir(),
sessionManager: SessionManager.create(process.cwd()),
});
// Replace the active session with a fresh one
await runtime.newSession();
// Replace the active session with another saved session
await runtime.switchSession("/path/to/session.jsonl");
// Replace the active session with a fork from a specific user entry
await runtime.fork("entry-id");
// Clone the active path through a specific entry
await runtime.fork("entry-id", { position: "at" });SessionManager ツリー API:
const sm = SessionManager.open("/path/to/session.jsonl");
// Session listing
const currentProjectSessions = await SessionManager.list(process.cwd());
const allSessions = await SessionManager.listAll(process.cwd());
// Tree traversal
const entries = sm.getEntries(); // All entries (excludes header)
const tree = sm.getTree(); // Full tree structure
const path = sm.getPath(); // Path from root to current leaf
const leaf = sm.getLeafEntry(); // Current leaf entry
const entry = sm.getEntry(id); // Get entry by ID
const children = sm.getChildren(id); // Direct children of entry
// Labels
const label = sm.getLabel(id); // Get label for entry
sm.appendLabelChange(id, "checkpoint"); // Set label
// Branching
sm.branch(entryId); // Move leaf to earlier entry
sm.branchWithSummary(id, "Summary..."); // Branch with context summary
sm.createBranchedSession(leafId); // Extract path to new file設定管理
import { createAgentSession, SettingsManager, SessionManager } from "@earendil-works/pi-coding-agent";
// Default: loads from files (global + project merged)
const { session } = await createAgentSession({
settingsManager: SettingsManager.create(),
});
// With overrides
const settingsManager = SettingsManager.create();
settingsManager.applyOverrides({
compaction: { enabled: false },
retry: { enabled: true, maxRetries: 5 },
});
const { session } = await createAgentSession({ settingsManager });
// In-memory (no file I/O, for testing)
const { session } = await createAgentSession({
settingsManager: SettingsManager.inMemory({ compaction: { enabled: false } }),
sessionManager: SessionManager.inMemory(),
});
// Custom directories
const { session } = await createAgentSession({
settingsManager: SettingsManager.create("/custom/cwd", "/custom/agent"),
});静的ファクトリー:
SettingsManager.create(cwd?, agentDir?)- ファイルからロードSettingsManager.inMemory(settings?)- ファイル I/O なし
プロジェクト固有の設定:
設定は 2 つの場所からロードされ、マージされます。
- グローバル:
~/.pi/agent/settings.json - プロジェクト:
<cwd>/.pi/settings.json
プロジェクトはグローバルをオーバーライドします。ネストされたオブジェクトはキーをマージします。設定者はデフォルトでグローバル設定を変更します。
永続性とエラー処理のセマンティクス:
- 設定のゲッター/セッターはメモリ内状態に対して同期されます。
- Setter は永続書き込みを非同期でキューに入れます。
- 耐久性境界が必要な場合 (たとえば、プロセスの終了前、またはテストでファイルの内容をアサートする前) に、
await settingsManager.flush()を呼び出します。 SettingsManagerは設定 I/O エラーを出力しません。settingsManager.drainErrors()を使用してアプリ層で報告します。
リソースローダー
DefaultResourceLoader を使用して、拡張機能、スキル、プロンプト、テーマ、および context files を見つけます。
import {
DefaultResourceLoader,
getAgentDir,
} from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({
cwd,
agentDir: getAgentDir(),
});
await loader.reload();
const extensions = loader.getExtensions();
const skills = loader.getSkills();
const prompts = loader.getPrompts();
const themes = loader.getThemes();
const contextFiles = loader.getAgentsFiles().agentsFiles;戻り値
createAgentSession() は次を返します:
interface CreateAgentSessionResult {
// The session
session: AgentSession;
// Extensions result (for runner setup)
extensionsResult: LoadExtensionsResult;
// Warning if session model couldn't be restored
modelFallbackMessage?: string;
}
interface LoadExtensionsResult {
extensions: Extension[];
errors: Array<{ path: string; error: string }>;
runtime: ExtensionRuntime;
}完全な例
import { getModel } from "@earendil-works/pi-ai";
import { Type } from "typebox";
import {
createAgentSession,
DefaultResourceLoader,
defineTool,
ModelRuntime,
SessionManager,
SettingsManager,
} from "@earendil-works/pi-coding-agent";
const modelRuntime = await ModelRuntime.create({
authPath: "/custom/agent/auth.json",
modelsPath: "/custom/agent/models.json",
});
if (process.env.MY_KEY) {
await modelRuntime.setRuntimeApiKey("anthropic", process.env.MY_KEY);
}
// Inline tool
const statusTool = defineTool({
name: "status",
label: "Status",
description: "Get system status",
parameters: Type.Object({}),
execute: async () => ({
content: [{ type: "text", text: `Uptime: ${process.uptime()}s` }],
details: {},
}),
});
const model = getModel("anthropic", "claude-opus-4-5");
if (!model) throw new Error("Model not found");
// In-memory settings with overrides
const settingsManager = SettingsManager.inMemory({
compaction: { enabled: false },
retry: { enabled: true, maxRetries: 2 },
});
const loader = new DefaultResourceLoader({
cwd: process.cwd(),
agentDir: "/custom/agent",
settingsManager,
systemPromptOverride: () => "You are a minimal assistant. Be concise.",
});
await loader.reload();
const { session } = await createAgentSession({
cwd: process.cwd(),
agentDir: "/custom/agent",
model,
thinkingLevel: "off",
modelRuntime,
tools: ["read", "bash", "status"],
customTools: [statusTool],
resourceLoader: loader,
sessionManager: SessionManager.inMemory(),
settingsManager,
});
session.subscribe((event) => {
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
await session.prompt("Get status and list files.");実行モード
SDK は、createAgentSession() 上にカスタム インターフェイスを構築するための実行モード ユーティリティをエクスポートします。
インタラクティブモード
エディター、チャット履歴、およびすべての組み込みコマンドを備えた完全なTUI インタラクティブ モード:
import {
type CreateAgentSessionRuntimeFactory,
createAgentSessionFromServices,
createAgentSessionRuntime,
createAgentSessionServices,
getAgentDir,
InteractiveMode,
SessionManager,
} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
const services = await createAgentSessionServices({ cwd });
return {
...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
services,
diagnostics: services.diagnostics,
};
};
const runtime = await createAgentSessionRuntime(createRuntime, {
cwd: process.cwd(),
agentDir: getAgentDir(),
sessionManager: SessionManager.create(process.cwd()),
});
const mode = new InteractiveMode(runtime, {
migratedProviders: [],
modelFallbackMessage: undefined,
initialMessage: "Hello",
initialImages: [],
initialMessages: [],
});
await mode.run();runPrintMode
シングルショット モード: プロンプトを送信し、結果を出力し、終了します。
import {
type CreateAgentSessionRuntimeFactory,
createAgentSessionFromServices,
createAgentSessionRuntime,
createAgentSessionServices,
getAgentDir,
runPrintMode,
SessionManager,
} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
const services = await createAgentSessionServices({ cwd });
return {
...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
services,
diagnostics: services.diagnostics,
};
};
const runtime = await createAgentSessionRuntime(createRuntime, {
cwd: process.cwd(),
agentDir: getAgentDir(),
sessionManager: SessionManager.create(process.cwd()),
});
await runPrintMode(runtime, {
mode: "text",
initialMessage: "Hello",
initialImages: [],
messages: ["Follow up"],
});runRpcMode
サブプロセス統合用のJSON-RPC モード:
import {
type CreateAgentSessionRuntimeFactory,
createAgentSessionFromServices,
createAgentSessionRuntime,
createAgentSessionServices,
getAgentDir,
runRpcMode,
SessionManager,
} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
const services = await createAgentSessionServices({ cwd });
return {
...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
services,
diagnostics: services.diagnostics,
};
};
const runtime = await createAgentSessionRuntime(createRuntime, {
cwd: process.cwd(),
agentDir: getAgentDir(),
sessionManager: SessionManager.create(process.cwd()),
});
await runRpcMode(runtime);JSON プロトコルについては、RPC documentation を参照してください。
RPC 代替モード
SDK でビルドせずにサブプロセスベースの統合を行う場合は、CLI を直接使用します。
pi --mode rpc --no-sessionJSON プロトコルについては、RPC documentation を参照してください。
次の場合には SDK が優先されます。
- タイプ セーフティが必要な場合
- あなたも同じNode.jsプロセスにいます
- エージェントの状態に直接アクセスする必要がある
- ツール/拡張機能をプログラム的にカスタマイズしたい
RPC モードは、次の場合に優先されます。
- 別の言語から統合している
- プロセスを分離したい
- 言語に依存しないクライアントを構築している
輸出
メインのエントリ ポイントは以下をエクスポートします。
// Factory
createAgentSession
createAgentSessionRuntime
AgentSessionRuntime
// Auth and Models
ModelRuntime // implements pi-ai Models and owns credential storage
ModelRegistry // synchronous extension compatibility facade
CredentialSynchronizationError
resolveCliModel
resolveModelScopeWithDiagnostics
// Resource loading
DefaultResourceLoader
type ResourceLoader
createEventBus
// Constants and helpers
CONFIG_DIR_NAME
defineTool
getAgentDir
getPackageDir
getReadmePath
getDocsPath
getExamplesPath
// Session management
SessionManager
SettingsManager
// Tool factories
createCodingTools
createReadOnlyTools
createReadTool, createBashTool, createEditTool, createWriteTool
createGrepTool, createFindTool, createLsTool
// Types
type CreateAgentSessionOptions
type CreateAgentSessionResult
type ExtensionFactory
type InlineExtension
type ExtensionAPI
type ToolDefinition
type Skill
type PromptTemplate
type Tool拡張子の種類については、完全な API については extensions.md を参照してください。