Cấu hình, tùy chỉnh, thiết lập nền tảng và tham chiếu API cho Pi.

SDK

pi có thể giúp bạn sử dụng SDK. Yêu cầu nó xây dựng một tích hợp cho trường hợp sử dụng của bạn.

SDK cung cấp quyền truy cập theo chương trình vào các khả năng của tác nhân pi. Sử dụng nó để nhúng pi vào các ứng dụng khác, xây dựng giao diện tùy chỉnh hoặc tích hợp với quy trình làm việc tự động.

Các trường hợp sử dụng ví dụ:

  • Xây dựng giao diện người dùng tùy chỉnh (web, máy tính để bàn, thiết bị di động)
  • Tích hợp khả năng của đại lý vào các ứng dụng hiện có
  • Tạo quy trình tự động với lý luận của tác nhân
  • Xây dựng các công cụ tùy chỉnh sinh ra các đại lý phụ
  • Kiểm tra hành vi của tác nhân theo chương trình

Xem examples/sdk/ để biết các ví dụ hoạt động từ kiểm soát tối thiểu đến kiểm soát hoàn toàn.

Bắt đầu nhanh

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

Cài đặt

npm install @earendil-works/pi-coding-agent

SDK được bao gồm trong gói chính. Không cần cài đặt riêng biệt.

Khái niệm cốt lõi

createAgentSession()

Chức năng chính của nhà máy cho một AgentSession.

createAgentSession() sử dụng ResourceLoader để cung cấp các tiện ích mở rộng, kỹ năng, prompt templates, chủ đề và context files. Nếu bạn không cung cấp, nó sẽ sử dụng DefaultResourceLoader với tính năng khám phá tiêu chuẩn.

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

Phiên đại lý

Phiên này quản lý vòng đời của tác nhân, lịch sử tin nhắn, trạng thái mô hình, quá trình nén và truyền phát sự kiện.

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

Thay thế phiên API chẳng hạn như phiên mới, tiếp tục, phân nhánh và nhập trực tiếp trên AgentSessionRuntime chứ không phải trên AgentSession.

createAgentSessionRuntime() và AgentSessionRuntime

Sử dụng thời gian chạy API khi bạn cần thay thế phiên hoạt động và xây dựng lại trạng thái thời gian chạy giới hạn cwd. Đây là cùng một lớp được sử dụng bởi các chế độ tương tác, in và RPC tích hợp sẵn.

createAgentSessionRuntime() lấy một nhà máy thời gian chạy cộng với mục tiêu cwd/phiên ban đầu. Nhà máy đóng các đầu vào cố định toàn quy trình, tạo lại các dịch vụ liên kết với cwd cho cwd hiệu quả, giải quyết các tùy chọn phiên đối với các dịch vụ đó và trả về kết quả thời gian chạy đầy đủ.

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 sở hữu sự thay thế thời gian chạy hoạt động trên:

  • newSession()
  • switchSession()
  • fork()
  • bản sao chảy qua fork(entryId, { position: "at" })
  • importFromJsonl()

Hành vi quan trọng:

  • runtime.session thay đổi sau những thao tác đó
  • đăng ký sự kiện được đính kèm với một AgentSession cụ thể, vì vậy hãy đăng ký lại sau khi thay thế
  • nếu bạn sử dụng tiện ích mở rộng, hãy gọi lại runtime.session.bindExtensions(...) cho phiên mới
  • quá trình tạo trả về chẩn đoán trên runtime.diagnostics
  • nếu việc tạo hoặc thay thế thời gian chạy không thành công, phương thức sẽ được đưa ra và người gọi sẽ quyết định cách xử lý nó
let session = runtime.session;
let unsubscribe = session.subscribe(() => {});

await runtime.newSession();

unsubscribe();
session = runtime.session;
unsubscribe = session.subscribe(() => {});

Nhắc nhở và xếp hàng tin nhắn

PromptOptions kiểm soát việc mở rộng lời nhắc, hành vi xếp hàng trong khi phát trực tuyến và nhắc nhở thông báo trước ánh sáng:

interface PromptOptions {
  expandPromptTemplates?: boolean;
  images?: ImageContent[];
  streamingBehavior?: "steer" | "followUp";
  source?: InputSource;
  preflightResult?: (success: boolean) => void;
}

preflightResult được gọi một lần cho mỗi lần gọi prompt():

  • true khi lời nhắc được chấp nhận, xếp hàng hoặc xử lý ngay lập tức
  • false khi lời nhắc preflight bị từ chối trước khi được chấp nhận

Nó kích hoạt trước khi prompt() được giải quyết. prompt() vẫn chỉ giải quyết sau khi quá trình chạy được chấp nhận hoàn toàn kết thúc, bao gồm cả lần thử lại. Các lỗi sau khi chấp nhận được báo cáo thông qua luồng sự kiện và tin nhắn thông thường, không phải thông qua preflightResult(false).

Phương thức prompt() xử lý prompt templates, các lệnh mở rộng và gửi tin nhắn:

// 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" });

Hành vi:

  • Lệnh mở rộng (ví dụ: /mycommand): Thực thi ngay lập tức, ngay cả trong khi phát trực tuyến. Họ quản lý tương tác LLM của riêng mình thông qua pi.sendMessage().
  • Dựa trên tệp prompt templates (từ tệp .md): Đã mở rộng sang nội dung của chúng trước khi gửi hoặc xếp hàng.
  • Trong khi phát trực tuyến mà không có streamingBehavior: Xảy ra lỗi. Sử dụng trực tiếp steer() hoặc followUp() hoặc chỉ định tùy chọn.
  • preflightResult(true): Có nghĩa là lời nhắc đã được chấp nhận, xếp hàng hoặc xử lý ngay lập tức.
  • preflightResult(false): Có nghĩa là chuyến bay trước bị từ chối trước khi được chấp nhận.

Để xếp hàng rõ ràng trong khi phát trực tuyến:

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

Cả steer()followUp() đều mở rộng prompt templates dựa trên tệp nhưng có lỗi trên các lệnh mở rộng (không thể xếp hàng các lệnh mở rộng).

Đại lý và Trạng thái đại lý

Lớp Agent (từ @earendil-works/pi-agent-core) xử lý tương tác LLM cốt lõi. Truy cập nó qua 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();

Sự kiện

Đăng ký các sự kiện để nhận thông báo đầu ra và vòng đời phát trực tuyến.

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

Tùy chọn tham khảo

Thư mục

const { session } = await createAgentSession({
  // Working directory for DefaultResourceLoader discovery
  cwd: process.cwd(), // default
  
  // Global config directory
  agentDir: "~/.pi/agent", // default (expands ~)
});

cwd được sử dụng bởi DefaultResourceLoader cho:

  • Mở rộng dự án (.pi/extensions/)
  • Kỹ năng dự án:
    • .pi/skills/
    • .agents/skills/ trong cwd và các thư mục tổ tiên (tối đa git repo root hoặc root hệ thống tập tin khi không có trong repo)
  • Lời nhắc dự án (.pi/prompts/)
  • Tệp ngữ cảnh (AGENTS.md đi lên từ cwd)
  • Đặt tên thư mục phiên

agentDir được sử dụng bởi DefaultResourceLoader cho:

  • Tiện ích mở rộng toàn cầu (extensions/)
  • Kỹ năng toàn cầu:
    • skills/ dưới agentDir (ví dụ ~/.pi/agent/skills/)
    • ~/.agents/skills/
  • Lời nhắc chung (prompts/)
  • Tệp ngữ cảnh chung (AGENTS.md)
  • Cài đặt (settings.json)
  • Mô hình tùy chỉnh (models.json)
  • Thông tin xác thực (auth.json)
  • Phiên (sessions/)

Khi bạn chuyển một tùy chỉnh ResourceLoader, cwdagentDir không còn kiểm soát việc khám phá tài nguyên nữa. Chúng vẫn ảnh hưởng đến việc đặt tên phiên và độ phân giải đường chạy dao.

Người mẫu

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

Nếu không có mô hình nào được cung cấp:

  1. Cố gắng khôi phục từ phiên (nếu tiếp tục)
  2. Sử dụng mặc định từ cài đặt
  3. Quay trở lại mô hình có sẵn đầu tiên

Để khớp với phân tích cú pháp mô hình CLI, hãy sử dụng trình trợ giúp trình phân giải đã xuất:

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() sử dụng tất cả các mô hình đã đăng ký nên thiết lập lần đầu tiên theo kiểu --api-key có thể giải quyết một mô hình trước khi tồn tại xác thực được lưu trữ. resolveModelScopeWithDiagnostics() khớp với ngữ nghĩa của --modelsenabledModels trong khi trả lại cảnh báo thay vì in chúng.

Xem examples/sdk/02-custom-model.ts

API Chìa khóa và OAuth

Mức độ ưu tiên của độ phân giải xác thực (được xử lý bởi ModelRuntime):

  1. Ghi đè thời gian chạy (thông qua setRuntimeApiKey, không được duy trì)
  2. Thông tin xác thực được lưu trữ trong auth.json (API keys hoặc OAuth mã thông báo)
  3. Biến môi trường (ANTHROPIC_API_KEY, OPENAI_API_KEY, v.v.)
  4. Trình phân giải dự phòng (đối với khóa nhà cung cấp tùy chỉnh từ 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() giải quyết sau khi danh mục, thành phần và ảnh chụp nhanh tình trạng sẵn có được lưu vào bộ nhớ đệm/tích hợp của nhà cung cấp bị ảnh hưởng nhất quán cục bộ. Họ không chờ đợi sự cập nhật danh mục từ xa. Nếu thông tin xác thực đã được cam kết nhưng đồng bộ hóa cục bộ không thành công thì chúng sẽ từ chối bằng CredentialSynchronizationError đã xuất; kiểm tra các trường providerId, operation, credentialcause của nó thay vì thử lại đột biến thông tin xác thực một cách mù quáng.

Hoạt động mô hình/xác thực công khai và ModelRuntime.create({ signal }) chấp nhận tín hiệu hủy bỏ tùy chọn và không bị giới hạn khi bị bỏ qua. SDK chính sách về thời hạn của ứng dụng đối với việc làm mới danh mục từ xa:

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

Việc làm mới mạng không thành công hoặc hết thời gian chờ sẽ không hoàn tác thao tác xác thực thành công. refresh() bắt đầu một thế hệ nhà cung cấp mới, do đó, nó không chờ đợi sau một lần làm mới cũ bị đình trệ và các thế hệ cũ không thể xuất bản sau đó.

Xem examples/sdk/09-api-keys-and-oauth.ts

Lời nhắc hệ thống

Sử dụng ResourceLoader để ghi đè lời nhắc hệ thống:

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

Xem examples/sdk/03-custom-prompt.ts

Công cụ

Chỉ định những công cụ tích hợp nào sẽ bật:

  • Tên công cụ tích hợp: read, bash, edit, write, grep, find, ls
  • Các phần dựng sẵn mặc định: read, bash, edit, write
  • noTools: "all" vô hiệu hóa tất cả các công cụ
  • noTools: "builtin" vô hiệu hóa các phần tích hợp mặc định trong khi vẫn bật tiện ích mở rộng và công cụ tùy chỉnh
  • excludeTools vô hiệu hóa các tên công cụ tùy chỉnh, tiện ích mở rộng hoặc tích hợp cụ thể sau khi áp dụng bất kỳ danh sách cho phép tools nào

Công cụ edit trả về details.diff cho màn hình TUI của Pi và details.patch dưới dạng bản vá thống nhất tiêu chuẩn cho người tiêu dùng SDK.

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

Công cụ với cwd tùy chỉnh

Khi bạn chuyển một cwd tùy chỉnh, createAgentSession() sẽ xây dựng các công cụ tích hợp đã chọn cho 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),
});

Xem examples/sdk/05-tools.ts

Công cụ tùy chỉnh

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

Sử dụng defineTool() cho các định nghĩa và mảng độc lập như customTools: [myTool]. Nội tuyến pi.registerTool({... }) đã suy ra chính xác các loại tham số.

Các công cụ tùy chỉnh được chuyển qua customTools được kết hợp với các công cụ đã đăng ký tiện ích mở rộng. Extensions được tải bởi ResourceLoader cũng có thể đăng ký các công cụ thông qua pi.registerTool().

Nếu bạn vượt qua tools, hãy bao gồm từng tên công cụ tùy chỉnh hoặc tiện ích mở rộng mà bạn muốn bật, ví dụ: tools: ["read", "bash", "my_tool"].

Xem examples/sdk/05-tools.ts

Extensions

Extensions được tải bởi ResourceLoader. DefaultResourceLoader khám phá các tiện ích mở rộng từ các nguồn tiện ích mở rộng ~/.pi/agent/extensions/, .pi/extensions/ và 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 có thể đăng ký công cụ, đăng ký sự kiện, thêm lệnh, v.v. Xem extensions.md để biết đầy đủ API.

Tiện ích mở rộng nội tuyến được đặt tên: Theo mặc định, các nhà máy nội tuyến hiển thị dưới dạng <inline:1>, <inline:2>, v.v. trong danh sách khởi động Extensions. Thay vào đó, để hiển thị tên mô tả, hãy bọc nhà máy:

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

Điều này hiển thị dưới dạng <inline:my-provider> thay vì <inline:1>. Các chức năng của nhà máy trần vẫn được chấp nhận để tương thích ngược.

Xe buýt sự kiện: Extensions có thể giao tiếp qua pi.events. Chuyển eventBus được chia sẻ đến DefaultResourceLoader nếu bạn cần phát hoặc nghe từ bên ngoài:

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

Xem examples/sdk/06-extensions.tsdocs/extensions.md

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

Xem examples/sdk/04-skills.ts

Tệp ngữ cảnh

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

Xem examples/sdk/07-context-files.ts

Lệnh gạch chéo

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

Xem examples/sdk/08-prompt-templates.ts

Quản lý phiên

Phiên sử dụng cấu trúc cây với liên kết id/parentId, cho phép phân nhánh tại chỗ.

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

Cây quản lý phiên 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

Xem examples/sdk/11-sessions.tsSession Format

Quản lý cài đặt

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

Nhà máy tĩnh:

  • SettingsManager.create(cwd?, agentDir?) - Tải từ tập tin
  • SettingsManager.inMemory(settings?) - Không có tệp vào/ra

Cài đặt dành riêng cho dự án:

Tải cài đặt từ hai vị trí và hợp nhất:

  1. Toàn cầu: ~/.pi/agent/settings.json
  2. Dự án: <cwd>/.pi/settings.json

Dự án ghi đè toàn cầu. Các đối tượng lồng nhau hợp nhất các khóa. Setters sửa đổi cài đặt chung theo mặc định.

Ngữ nghĩa xử lý kiên trì và lỗi:

  • Getters/setters cài đặt đồng bộ cho trạng thái trong bộ nhớ.
  • Tính kiên trì của Setters enqueue ghi không đồng bộ.
  • Gọi await settingsManager.flush() khi bạn cần ranh giới độ bền (ví dụ: trước khi thoát quá trình hoặc trước khi xác nhận nội dung tệp trong các bài kiểm tra).
  • SettingsManager không in các lỗi I/O cài đặt. Sử dụng settingsManager.drainErrors() và báo cáo chúng trong lớp ứng dụng của bạn.

Xem examples/sdk/10-settings.ts

Trình tải tài nguyên

Sử dụng DefaultResourceLoader để khám phá các tiện ích mở rộng, kỹ năng, lời nhắc, chủ đề và 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;

Giá trị trả về

createAgentSession() trả về:

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

Ví dụ hoàn chỉnh

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

Chế độ chạy

SDK xuất các tiện ích chế độ chạy để xây dựng giao diện tùy chỉnh trên createAgentSession():

Chế độ tương tác

Chế độ tương tác đầy đủ TUI với trình chỉnh sửa, lịch sử trò chuyện và tất cả các lệnh tích hợp:

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

Chế độ chụp một lần: gửi lời nhắc, kết quả đầu ra, thoát:

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

Chế độ JSON-RPC để tích hợp quy trình con:

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

Xem RPC documentation để biết giao thức JSON.

RPC Chế độ thay thế

Để tích hợp dựa trên quy trình con mà không cần xây dựng bằng SDK, hãy sử dụng trực tiếp CLI:

pi --mode rpc --no-session

Xem RPC documentation để biết giao thức JSON.

SDK được ưu tiên khi:

  • Bạn muốn loại an toàn
  • Bạn đang trong quá trình Node.js tương tự
  • Bạn cần truy cập trực tiếp vào trạng thái đại lý
  • Bạn muốn tùy chỉnh các công cụ/tiện ích mở rộng theo chương trình

Chế độ RPC được ưu tiên khi:

  • Bạn đang tích hợp từ một ngôn ngữ khác
  • Bạn muốn cách ly quá trình
  • Bạn đang xây dựng một ứng dụng khách không phân biệt ngôn ngữ

Xuất khẩu

Các điểm xuất khẩu chính:

// 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

Đối với các loại tiện ích mở rộng, hãy xem extensions.md để biết đầy đủ API.