SDK
pi 可以帮助你使用 SDK。请它为你的用例构建集成。
SDK 提供对 pi agent 能力的编程访问。你可以用它将 pi 嵌入其他应用、构建自定义界面,或集成到自动化工作流中。
示例用例:
- 构建自定义 UI(Web、桌面、移动端)
- 将 agent 能力集成到现有应用中
- 创建带 agent 推理的自动化流水线
- 构建可生成子 agent 的自定义工具
- 以编程方式测试 agent 行为
请参阅 examples/sdk/ 中从最小到完全控制的示例。
import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent";
// Set up credential storage and model registryconst authStorage = AuthStorage.create();const modelRegistry = ModelRegistry.create(authStorage);
const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(), authStorage, modelRegistry,});
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()
Section titled “createAgentSession()”创建单个 AgentSession 的主工厂函数。
createAgentSession() 使用 ResourceLoader 提供扩展、技能、提示模板、主题和上下文文件。若未提供,则使用带标准发现的 DefaultResourceLoader。
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
// Minimal: defaults with DefaultResourceLoaderconst { session } = await createAgentSession();
// Custom: override specific optionsconst { session } = await createAgentSession({ model: myModel, tools: ["read", "bash"], sessionManager: SessionManager.inMemory(),});AgentSession
Section titled “AgentSession”会话管理 agent 生命周期、消息历史、模型状态、压缩和事件流。
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(如 new-session、resume、fork 和 import)位于 AgentSessionRuntime 上,而非 AgentSession。
createAgentSessionRuntime() 与 AgentSessionRuntime
Section titled “createAgentSessionRuntime() 与 AgentSessionRuntime”当你需要替换活动会话并重建与 cwd 绑定的运行时状态时,使用 runtime API。 这与内置交互式、print 和 RPC 模式使用的层相同。
createAgentSessionRuntime() 接受 runtime 工厂和初始 cwd/会话目标。工厂闭包进程级固定输入,为有效 cwd 重建与 cwd 绑定的服务,针对这些服务解析会话选项,并返回完整 runtime 结果。
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 负责在以下操作间替换活动 runtime:
newSession()switchSession()fork()- 通过
fork(entryId, { position: "at" })的克隆流程 importFromJsonl()
重要行为:
- 上述操作后
runtime.session会变化 - 事件订阅绑定到特定
AgentSession,替换后需重新订阅 - 若使用扩展,需为新会话再次调用
runtime.session.bindExtensions(...) - 创建时在
runtime.diagnostics返回诊断信息 - 若 runtime 创建或替换失败,方法会抛出异常,由调用方决定如何处理
let session = runtime.session;let unsubscribe = session.subscribe(() => {});
await runtime.newSession();
unsubscribe();session = runtime.session;unsubscribe = session.subscribe(() => {});提示与消息队列
Section titled “提示与消息队列”PromptOptions 控制提示扩展、流式传输期间的队列行为以及提示预检通知:
interface PromptOptions { expandPromptTemplates?: boolean; images?: ImageContent[]; streamingBehavior?: "steer" | "followUp"; source?: InputSource; preflightResult?: (success: boolean) => void;}preflightResult 在每次 prompt() 调用时触发一次:
- 提示被接受、入队或立即处理时为
true - 提示预检在接受前拒绝时为
false
它在 prompt() resolve 之前触发。prompt() 仍仅在完整接受的运行(含重试)结束后 resolve。接受后的失败通过正常事件和消息流报告,而非 preflightResult(false)。
prompt() 方法处理提示模板、扩展命令和消息发送:
// Basic prompt (when not streaming)await session.prompt("What files are here?");
// With imagesawait 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 messageawait 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 交互。 - 基于文件的提示模板(来自
.md文件):在发送或入队前展开为内容。 - 流式传输期间未指定
streamingBehavior:抛出错误。请直接使用steer()或followUp(),或指定该选项。 preflightResult(true):表示提示已被接受、入队或立即处理。preflightResult(false):表示预检在接受前被拒绝。
流式传输期间显式队列:
// Queue a steering message for delivery after the current assistant turn finishes its tool callsawait 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() 都会展开基于文件的提示模板,但对扩展命令会报错(扩展命令无法入队)。
Agent 与 AgentState
Section titled “Agent 与 AgentState”Agent 类(来自 @earendil-works/pi-agent-core)处理核心 LLM 交互。通过 session.agent 访问。
// Access current stateconst 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 toolssession.agent.state.tools = tools; // copies the top-level array
// Wait for agent to finish processingawait 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": 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 { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
const authStorage = AuthStorage.create();const modelRegistry = ModelRegistry.create(authStorage);
// 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 = modelRegistry.find("my-provider", "my-model");
// Get only models that have valid API keys configuredconst available = await modelRegistry.getAvailable();
const { session } = await createAgentSession({ model: opus, thinkingLevel: "medium", // off, minimal, low, medium, high, xhigh
// Models for cycling (Ctrl+P in interactive mode) scopedModels: [ { model: opus, thinkingLevel: "high" }, { model: haiku, thinkingLevel: "off" }, ],
authStorage, modelRegistry,});若未提供模型:
- 尝试从会话恢复(若继续)
- 使用设置中的默认值
- 回退到第一个可用模型
API 密钥与 OAuth
Section titled “API 密钥与 OAuth”API 密钥解析优先级(由 AuthStorage 处理):
- 运行时覆盖(通过
setRuntimeApiKey,不持久化) auth.json中存储的凭据(API 密钥或 OAuth 令牌)- 环境变量(
ANTHROPIC_API_KEY、OPENAI_API_KEY等) - 回退解析器(用于
models.json中的自定义 provider 密钥)
import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
// Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.jsonconst authStorage = AuthStorage.create();const modelRegistry = ModelRegistry.create(authStorage);
const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(), authStorage, modelRegistry,});
// Runtime API key override (not persisted to disk)authStorage.setRuntimeApiKey("anthropic", "sk-my-temp-key");
// Custom auth storage locationconst customAuth = AuthStorage.create("/my/app/auth.json");const customRegistry = ModelRegistry.create(customAuth, "/my/app/models.json");
const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(), authStorage: customAuth, modelRegistry: customRegistry,});
// No custom models.json (built-in models only)const simpleRegistry = ModelRegistry.inMemory(authStorage);使用 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 modeconst { session } = await createAgentSession({ tools: ["read", "grep", "find", "ls"],});
// Pick specific toolsconst { session } = await createAgentSession({ tools: ["read", "bash", "grep"],});
// Disable one tool while keeping the rest availableconst { session } = await createAgentSession({ excludeTools: ["ask_question"],});自定义 cwd 的工具
Section titled “自定义 cwd 的工具”传入自定义 cwd 时,createAgentSession() 会为该 cwd 构建选定的内置工具。
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
const cwd = "/path/to/project";
// Use default tools for custom cwdconst { session } = await createAgentSession({ cwd, sessionManager: SessionManager.inMemory(cwd),});
// Or pick specific tools for custom cwdconst { 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 toolconst 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 directlyconst { session } = await createAgentSession({ customTools: [myTool],});对独立定义和数组(如 customTools: [myTool])使用 defineTool()。内联 pi.registerTool({ ... }) 已能正确推断参数类型。
通过 customTools 传入的自定义工具与扩展注册的工具合并。ResourceLoader 加载的扩展也可通过 pi.registerTool() 注册工具。
若传入 tools,需包含要启用的每个自定义或扩展工具名称,例如 tools: ["read", "bash", "my_tool"]。
扩展由 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 });扩展可注册工具、订阅事件、添加命令等。完整 API 请参阅 extensions.md。
事件总线: 扩展可通过 pi.events 通信。若需从外部发送或监听,向 DefaultResourceLoader 传入共享 eventBus:
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));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 sessionconst { session: persisted } = await createAgentSession({ sessionManager: SessionManager.create(process.cwd()),});
// Continue most recentconst { session: continued, modelFallbackMessage } = await createAgentSession({ sessionManager: SessionManager.continueRecent(process.cwd()),});if (modelFallbackMessage) { console.log("Note:", modelFallbackMessage);}
// Open specific fileconst { session: opened } = await createAgentSession({ sessionManager: SessionManager.open("/path/to/session.jsonl"),});
// List sessionsconst 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 oneawait runtime.newSession();
// Replace the active session with another saved sessionawait runtime.switchSession("/path/to/session.jsonl");
// Replace the active session with a fork from a specific user entryawait runtime.fork("entry-id");
// Clone the active path through a specific entryawait runtime.fork("entry-id", { position: "at" });SessionManager 树 API:
const sm = SessionManager.open("/path/to/session.jsonl");
// Session listingconst currentProjectSessions = await SessionManager.list(process.cwd());const allSessions = await SessionManager.listAll(process.cwd());
// Tree traversalconst entries = sm.getEntries(); // All entries (excludes header)const tree = sm.getTree(); // Full tree structureconst path = sm.getPath(); // Path from root to current leafconst leaf = sm.getLeafEntry(); // Current leaf entryconst entry = sm.getEntry(id); // Get entry by IDconst children = sm.getChildren(id); // Direct children of entry
// Labelsconst label = sm.getLabel(id); // Get label for entrysm.appendLabelChange(id, "checkpoint"); // Set label
// Branchingsm.branch(entryId); // Move leaf to earlier entrysm.branchWithSummary(id, "Summary..."); // Branch with context summarysm.createBranchedSession(leafId); // Extract path to new fileimport { createAgentSession, SettingsManager, SessionManager } from "@earendil-works/pi-coding-agent";
// Default: loads from files (global + project merged)const { session } = await createAgentSession({ settingsManager: SettingsManager.create(),});
// With overridesconst 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 directoriesconst { session } = await createAgentSession({ settingsManager: SettingsManager.create("/custom/cwd", "/custom/agent"),});静态工厂:
SettingsManager.create(cwd?, agentDir?)- 从文件加载SettingsManager.inMemory(settings?)- 无文件 I/O
项目特定设置:
设置从两个位置加载并合并:
- 全局:
~/.pi/agent/settings.json - 项目:
<cwd>/.pi/settings.json
项目覆盖全局。嵌套对象合并键。setter 默认修改全局设置。
持久化与错误处理语义:
- 设置 getter/setter 对内存状态是同步的。
- setter 异步排队持久化写入。
- 需要持久化边界时调用
await settingsManager.flush()(例如进程退出前或测试中断言文件内容前)。 SettingsManager不会打印设置 I/O 错误。使用settingsManager.drainErrors()并在应用层报告。
ResourceLoader
Section titled “ResourceLoader”使用 DefaultResourceLoader 发现扩展、技能、提示、主题和上下文文件。
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 { AuthStorage, createAgentSession, DefaultResourceLoader, defineTool, ModelRegistry, SessionManager, SettingsManager,} from "@earendil-works/pi-coding-agent";
// Set up auth storage (custom location)const authStorage = AuthStorage.create("/custom/agent/auth.json");
// Runtime API key override (not persisted)if (process.env.MY_KEY) { authStorage.setRuntimeApiKey("anthropic", process.env.MY_KEY);}
// Model registry (no custom models.json)const modelRegistry = ModelRegistry.create(authStorage);
// Inline toolconst 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 overridesconst 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", authStorage, modelRegistry,
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() 之上构建自定义界面:
InteractiveMode
Section titled “InteractiveMode”完整 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
Section titled “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
Section titled “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 文档。
RPC 模式替代方案
Section titled “RPC 模式替代方案”若不使用 SDK 构建而需基于子进程的集成,可直接使用 CLI:
pi --mode rpc --no-sessionJSON 协议请参阅 RPC 文档。
以下情况优先使用 SDK:
- 需要类型安全
- 在同一 Node.js 进程中运行
- 需要直接访问 agent 状态
- 需要以编程方式自定义工具/扩展
以下情况优先使用 RPC 模式:
- 从其他语言集成
- 需要进程隔离
- 构建与语言无关的客户端
主入口点导出:
// FactorycreateAgentSessioncreateAgentSessionRuntimeAgentSessionRuntime
// Auth and ModelsAuthStorageModelRegistry
// Resource loadingDefaultResourceLoadertype ResourceLoadercreateEventBus
// Constants and helpersCONFIG_DIR_NAMEdefineToolgetAgentDirgetPackageDirgetReadmePathgetDocsPathgetExamplesPath
// Session managementSessionManagerSettingsManager
// Tool factoriescreateCodingToolscreateReadOnlyToolscreateReadTool, createBashTool, createEditTool, createWriteToolcreateGrepTool, createFindTool, createLsTool
// Typestype CreateAgentSessionOptionstype CreateAgentSessionResulttype ExtensionFactorytype ExtensionAPItype ToolDefinitiontype Skilltype PromptTemplatetype Tool扩展类型完整 API 请参阅 extensions.md。