mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 15:02:32 +00:00
Add SDK usage examples
12 examples showing increasing levels of customization: - 01-minimal: all defaults - 02-custom-model: model and thinking level - 03-custom-prompt: replace or modify prompt - 04-skills: discover, filter, merge skills - 05-tools: built-in tools, custom tools - 06-hooks: logging, blocking, result modification - 07-context-files: AGENTS.md files - 08-slash-commands: file-based commands - 09-api-keys-and-oauth: API key resolution, OAuth config - 10-settings: compaction, retry, terminal settings - 11-sessions: persistence options - 12-full-control: replace everything Also exports FileSlashCommand type from index.ts
This commit is contained in:
parent
86cfe6a436
commit
56121dcac1
15 changed files with 723 additions and 0 deletions
29
packages/coding-agent/examples/README.md
Normal file
29
packages/coding-agent/examples/README.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Examples
|
||||
|
||||
Example code for pi-coding-agent.
|
||||
|
||||
## Directories
|
||||
|
||||
### [sdk/](sdk/)
|
||||
Programmatic usage via `createAgentSession()`. Shows how to customize models, prompts, tools, hooks, and session management.
|
||||
|
||||
### [hooks/](hooks/)
|
||||
Example hooks for intercepting tool calls, adding safety gates, and integrating with external systems.
|
||||
|
||||
### [custom-tools/](custom-tools/)
|
||||
Example custom tools that extend the agent's capabilities.
|
||||
|
||||
## Running Examples
|
||||
|
||||
```bash
|
||||
cd packages/coding-agent
|
||||
npx tsx examples/sdk/01-minimal.ts
|
||||
npx tsx examples/hooks/permission-gate.ts
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [SDK Reference](sdk/README.md)
|
||||
- [Hooks Documentation](../docs/hooks.md)
|
||||
- [Custom Tools Documentation](../docs/custom-tools.md)
|
||||
- [Skills Documentation](../docs/skills.md)
|
||||
22
packages/coding-agent/examples/sdk/01-minimal.ts
Normal file
22
packages/coding-agent/examples/sdk/01-minimal.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Minimal SDK Usage
|
||||
*
|
||||
* Uses all defaults: discovers skills, hooks, tools, context files
|
||||
* from cwd and ~/.pi/agent. Model chosen from settings or first available.
|
||||
*/
|
||||
|
||||
import { createAgentSession } from "../../src/index.js";
|
||||
|
||||
const { session } = await createAgentSession();
|
||||
|
||||
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?");
|
||||
session.state.messages.forEach((msg) => {
|
||||
console.log(msg);
|
||||
});
|
||||
console.log();
|
||||
36
packages/coding-agent/examples/sdk/02-custom-model.ts
Normal file
36
packages/coding-agent/examples/sdk/02-custom-model.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Custom Model Selection
|
||||
*
|
||||
* Shows how to select a specific model and thinking level.
|
||||
*/
|
||||
|
||||
import { createAgentSession, findModel, discoverAvailableModels } from "../../src/index.js";
|
||||
|
||||
// Option 1: Find a specific model by provider/id
|
||||
const { model: sonnet } = findModel("anthropic", "claude-sonnet-4-20250514");
|
||||
if (sonnet) {
|
||||
console.log(`Found model: ${sonnet.provider}/${sonnet.id}`);
|
||||
}
|
||||
|
||||
// Option 2: Pick from available models (have valid API keys)
|
||||
const available = await discoverAvailableModels();
|
||||
console.log(
|
||||
"Available models:",
|
||||
available.map((m) => `${m.provider}/${m.id}`),
|
||||
);
|
||||
|
||||
if (available.length > 0) {
|
||||
const { session } = await createAgentSession({
|
||||
model: available[0],
|
||||
thinkingLevel: "medium", // off, low, medium, high
|
||||
});
|
||||
|
||||
session.subscribe((event) => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
|
||||
await session.prompt("Say hello in one sentence.");
|
||||
console.log();
|
||||
}
|
||||
44
packages/coding-agent/examples/sdk/03-custom-prompt.ts
Normal file
44
packages/coding-agent/examples/sdk/03-custom-prompt.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Custom System Prompt
|
||||
*
|
||||
* Shows how to replace or modify the default system prompt.
|
||||
*/
|
||||
|
||||
import { createAgentSession, SessionManager } from "../../src/index.js";
|
||||
|
||||
// Option 1: Replace prompt entirely
|
||||
const { session: session1 } = await createAgentSession({
|
||||
systemPrompt: `You are a helpful assistant that speaks like a pirate.
|
||||
Always end responses with "Arrr!"`,
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session1.subscribe((event) => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
|
||||
console.log("=== Replace prompt ===");
|
||||
await session1.prompt("What is 2 + 2?");
|
||||
console.log("\n");
|
||||
|
||||
// Option 2: Modify default prompt (receives default, returns modified)
|
||||
const { session: session2 } = await createAgentSession({
|
||||
systemPrompt: (defaultPrompt) => `${defaultPrompt}
|
||||
|
||||
## Additional Instructions
|
||||
- Always be concise
|
||||
- Use bullet points when listing things`,
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session2.subscribe((event) => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
|
||||
console.log("=== Modify prompt ===");
|
||||
await session2.prompt("List 3 benefits of TypeScript.");
|
||||
console.log();
|
||||
44
packages/coding-agent/examples/sdk/04-skills.ts
Normal file
44
packages/coding-agent/examples/sdk/04-skills.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Skills Configuration
|
||||
*
|
||||
* Skills provide specialized instructions loaded into the system prompt.
|
||||
* Discover, filter, merge, or replace them.
|
||||
*/
|
||||
|
||||
import { createAgentSession, discoverSkills, SessionManager, type Skill } from "../../src/index.js";
|
||||
|
||||
// Discover all skills from cwd/.pi/skills, ~/.pi/agent/skills, etc.
|
||||
const allSkills = discoverSkills();
|
||||
console.log(
|
||||
"Discovered skills:",
|
||||
allSkills.map((s) => s.name),
|
||||
);
|
||||
|
||||
// Filter to specific skills
|
||||
const filteredSkills = allSkills.filter((s) => s.name.includes("browser") || s.name.includes("search"));
|
||||
|
||||
// Or define custom skills inline
|
||||
const customSkill: Skill = {
|
||||
name: "my-skill",
|
||||
description: "Custom project instructions",
|
||||
filePath: "/virtual/SKILL.md",
|
||||
baseDir: "/virtual",
|
||||
source: "custom",
|
||||
};
|
||||
|
||||
// Use filtered + custom skills
|
||||
const { session } = await createAgentSession({
|
||||
skills: [...filteredSkills, customSkill],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
console.log(`Session created with ${filteredSkills.length + 1} skills`);
|
||||
|
||||
// To disable all skills:
|
||||
// skills: []
|
||||
|
||||
// To use discovery with filtering via settings:
|
||||
// discoverSkills(process.cwd(), undefined, {
|
||||
// ignoredSkills: ["browser-tools"], // glob patterns to exclude
|
||||
// includeSkills: ["brave-*"], // glob patterns to include (empty = all)
|
||||
// })
|
||||
67
packages/coding-agent/examples/sdk/05-tools.ts
Normal file
67
packages/coding-agent/examples/sdk/05-tools.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Tools Configuration
|
||||
*
|
||||
* Use built-in tool sets, individual tools, or add custom tools.
|
||||
*/
|
||||
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import {
|
||||
createAgentSession,
|
||||
discoverCustomTools,
|
||||
SessionManager,
|
||||
codingTools, // read, bash, edit, write (default)
|
||||
readOnlyTools, // read, bash
|
||||
readTool,
|
||||
bashTool,
|
||||
grepTool,
|
||||
type CustomAgentTool,
|
||||
} from "../../src/index.js";
|
||||
|
||||
// Read-only mode (no edit/write)
|
||||
const { session: readOnly } = await createAgentSession({
|
||||
tools: readOnlyTools,
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
console.log("Read-only session created");
|
||||
|
||||
// Custom tool selection
|
||||
const { session: custom } = await createAgentSession({
|
||||
tools: [readTool, bashTool, grepTool],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
console.log("Custom tools session created");
|
||||
|
||||
// Inline custom tool (needs TypeBox schema)
|
||||
const weatherTool: CustomAgentTool = {
|
||||
name: "get_weather",
|
||||
label: "Get Weather",
|
||||
description: "Get current weather for a city",
|
||||
parameters: Type.Object({
|
||||
city: Type.String({ description: "City name" }),
|
||||
}),
|
||||
execute: async (_toolCallId, params) => ({
|
||||
content: [{ type: "text", text: `Weather in ${(params as { city: string }).city}: 22°C, sunny` }],
|
||||
details: {},
|
||||
}),
|
||||
};
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
customTools: [{ tool: weatherTool }],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session.subscribe((event) => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
|
||||
await session.prompt("What's the weather in Tokyo?");
|
||||
console.log();
|
||||
|
||||
// Merge with discovered tools from cwd/.pi/tools and ~/.pi/agent/tools:
|
||||
// const discovered = await discoverCustomTools();
|
||||
// customTools: [...discovered, { tool: myTool }]
|
||||
|
||||
// Or add paths without replacing discovery:
|
||||
// additionalCustomToolPaths: ["/extra/tools"]
|
||||
61
packages/coding-agent/examples/sdk/06-hooks.ts
Normal file
61
packages/coding-agent/examples/sdk/06-hooks.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Hooks Configuration
|
||||
*
|
||||
* Hooks intercept agent events for logging, blocking, or modification.
|
||||
*/
|
||||
|
||||
import { createAgentSession, discoverHooks, SessionManager, type HookFactory } from "../../src/index.js";
|
||||
|
||||
// Logging hook
|
||||
const loggingHook: HookFactory = (api) => {
|
||||
api.on("agent_start", async () => {
|
||||
console.log("[Hook] Agent starting");
|
||||
});
|
||||
|
||||
api.on("tool_call", async (event) => {
|
||||
console.log(`[Hook] Tool: ${event.toolName}`);
|
||||
return undefined; // Don't block
|
||||
});
|
||||
|
||||
api.on("agent_end", async (event) => {
|
||||
console.log(`[Hook] Done, ${event.messages.length} messages`);
|
||||
});
|
||||
};
|
||||
|
||||
// Blocking hook (returns { block: true, reason: "..." })
|
||||
const safetyHook: HookFactory = (api) => {
|
||||
api.on("tool_call", async (event) => {
|
||||
if (event.toolName === "bash") {
|
||||
const cmd = (event.input as { command?: string }).command ?? "";
|
||||
if (cmd.includes("rm -rf")) {
|
||||
return { block: true, reason: "Dangerous command blocked" };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
};
|
||||
|
||||
// Use inline hooks
|
||||
const { session } = await createAgentSession({
|
||||
hooks: [{ factory: loggingHook }, { factory: safetyHook }],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session.subscribe((event) => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
|
||||
await session.prompt("List files in the current directory.");
|
||||
console.log();
|
||||
|
||||
// Disable all hooks:
|
||||
// hooks: []
|
||||
|
||||
// Merge with discovered hooks:
|
||||
// const discovered = await discoverHooks();
|
||||
// hooks: [...discovered, { factory: myHook }]
|
||||
|
||||
// Add paths without replacing discovery:
|
||||
// additionalHookPaths: ["/extra/hooks"]
|
||||
36
packages/coding-agent/examples/sdk/07-context-files.ts
Normal file
36
packages/coding-agent/examples/sdk/07-context-files.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Context Files (AGENTS.md)
|
||||
*
|
||||
* Context files provide project-specific instructions loaded into the system prompt.
|
||||
*/
|
||||
|
||||
import { createAgentSession, discoverContextFiles, SessionManager } from "../../src/index.js";
|
||||
|
||||
// Discover AGENTS.md files walking up from cwd
|
||||
const discovered = discoverContextFiles();
|
||||
console.log("Discovered context files:");
|
||||
for (const file of discovered) {
|
||||
console.log(` - ${file.path} (${file.content.length} chars)`);
|
||||
}
|
||||
|
||||
// Use custom context files
|
||||
const { session } = await createAgentSession({
|
||||
contextFiles: [
|
||||
...discovered,
|
||||
{
|
||||
path: "/virtual/AGENTS.md",
|
||||
content: `# Project Guidelines
|
||||
|
||||
## Code Style
|
||||
- Use TypeScript strict mode
|
||||
- No any types
|
||||
- Prefer const over let`,
|
||||
},
|
||||
],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
console.log(`Session created with ${discovered.length + 1} context files`);
|
||||
|
||||
// Disable context files:
|
||||
// contextFiles: []
|
||||
37
packages/coding-agent/examples/sdk/08-slash-commands.ts
Normal file
37
packages/coding-agent/examples/sdk/08-slash-commands.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Slash Commands
|
||||
*
|
||||
* File-based commands that inject content when invoked with /commandname.
|
||||
*/
|
||||
|
||||
import { createAgentSession, discoverSlashCommands, SessionManager, type FileSlashCommand } from "../../src/index.js";
|
||||
|
||||
// Discover commands from cwd/.pi/commands/ and ~/.pi/agent/commands/
|
||||
const discovered = discoverSlashCommands();
|
||||
console.log("Discovered slash commands:");
|
||||
for (const cmd of discovered) {
|
||||
console.log(` /${cmd.name}: ${cmd.description}`);
|
||||
}
|
||||
|
||||
// Define custom commands
|
||||
const deployCommand: FileSlashCommand = {
|
||||
name: "deploy",
|
||||
description: "Deploy the application",
|
||||
source: "(custom)",
|
||||
content: `# Deploy Instructions
|
||||
|
||||
1. Build: npm run build
|
||||
2. Test: npm test
|
||||
3. Deploy: npm run deploy`,
|
||||
};
|
||||
|
||||
// Use discovered + custom commands
|
||||
const { session } = await createAgentSession({
|
||||
slashCommands: [...discovered, deployCommand],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
console.log(`Session created with ${discovered.length + 1} slash commands`);
|
||||
|
||||
// Disable slash commands:
|
||||
// slashCommands: []
|
||||
45
packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts
Normal file
45
packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* API Keys and OAuth
|
||||
*
|
||||
* Configure API key resolution. Default checks: models.json, OAuth, env vars.
|
||||
*/
|
||||
|
||||
import {
|
||||
createAgentSession,
|
||||
configureOAuthStorage,
|
||||
defaultGetApiKey,
|
||||
SessionManager,
|
||||
} from "../../src/index.js";
|
||||
import { getAgentDir } from "../../src/config.js";
|
||||
|
||||
// Default: uses env vars (ANTHROPIC_API_KEY, etc.), OAuth, and models.json
|
||||
const { session: defaultSession } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
console.log("Session with default API key resolution");
|
||||
|
||||
// Custom resolver
|
||||
const { session: customSession } = await createAgentSession({
|
||||
getApiKey: async (model) => {
|
||||
// Custom logic (secrets manager, database, etc.)
|
||||
if (model.provider === "anthropic") {
|
||||
return process.env.MY_ANTHROPIC_KEY;
|
||||
}
|
||||
// Fall back to default
|
||||
return defaultGetApiKey()(model);
|
||||
},
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
console.log("Session with custom API key resolver");
|
||||
|
||||
// Use OAuth from ~/.pi/agent while customizing everything else
|
||||
configureOAuthStorage(getAgentDir()); // Must call before createAgentSession
|
||||
|
||||
const { session: hybridSession } = await createAgentSession({
|
||||
agentDir: "/tmp/custom-config", // Custom config location
|
||||
// But OAuth tokens still come from ~/.pi/agent/oauth.json
|
||||
systemPrompt: "You are helpful.",
|
||||
skills: [],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
console.log("Session with OAuth from default location, custom config elsewhere");
|
||||
33
packages/coding-agent/examples/sdk/10-settings.ts
Normal file
33
packages/coding-agent/examples/sdk/10-settings.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Settings Configuration
|
||||
*
|
||||
* Override settings from agentDir/settings.json.
|
||||
*/
|
||||
|
||||
import { createAgentSession, loadSettings, SessionManager } from "../../src/index.js";
|
||||
|
||||
// Load current settings
|
||||
const settings = loadSettings();
|
||||
console.log("Current settings:", JSON.stringify(settings, null, 2));
|
||||
|
||||
// Override specific settings
|
||||
const { session } = await createAgentSession({
|
||||
settings: {
|
||||
// Disable auto-compaction
|
||||
compaction: { enabled: false },
|
||||
|
||||
// Custom retry behavior
|
||||
retry: {
|
||||
enabled: true,
|
||||
maxRetries: 5,
|
||||
baseDelayMs: 1000,
|
||||
},
|
||||
|
||||
// Terminal options
|
||||
terminal: { showImages: true },
|
||||
hideThinkingBlock: true,
|
||||
},
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
console.log("Session created with custom settings");
|
||||
46
packages/coding-agent/examples/sdk/11-sessions.ts
Normal file
46
packages/coding-agent/examples/sdk/11-sessions.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Session Management
|
||||
*
|
||||
* Control session persistence: in-memory, new file, continue, or open specific.
|
||||
*/
|
||||
|
||||
import { createAgentSession, SessionManager } from "../../src/index.js";
|
||||
|
||||
// In-memory (no persistence)
|
||||
const { session: inMemory } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
console.log("In-memory session:", inMemory.sessionFile ?? "(none)");
|
||||
|
||||
// New persistent session
|
||||
const { session: newSession } = await createAgentSession({
|
||||
sessionManager: SessionManager.create(process.cwd()),
|
||||
});
|
||||
console.log("New session file:", newSession.sessionFile);
|
||||
|
||||
// Continue most recent session (or create new if none)
|
||||
const { session: continued, modelFallbackMessage } = await createAgentSession({
|
||||
sessionManager: SessionManager.continueRecent(process.cwd()),
|
||||
});
|
||||
if (modelFallbackMessage) console.log("Note:", modelFallbackMessage);
|
||||
console.log("Continued session:", continued.sessionFile);
|
||||
|
||||
// List and open specific session
|
||||
const sessions = SessionManager.list(process.cwd());
|
||||
console.log(`\nFound ${sessions.length} sessions:`);
|
||||
for (const info of sessions.slice(0, 3)) {
|
||||
console.log(` ${info.id.slice(0, 8)}... - "${info.firstMessage.slice(0, 30)}..."`);
|
||||
}
|
||||
|
||||
if (sessions.length > 0) {
|
||||
const { session: opened } = await createAgentSession({
|
||||
sessionManager: SessionManager.open(sessions[0].path),
|
||||
});
|
||||
console.log(`\nOpened: ${opened.sessionId}`);
|
||||
}
|
||||
|
||||
// Custom session directory
|
||||
// const { session } = await createAgentSession({
|
||||
// agentDir: "/custom/agent",
|
||||
// sessionManager: SessionManager.create(process.cwd(), "/custom/agent"),
|
||||
// });
|
||||
84
packages/coding-agent/examples/sdk/12-full-control.ts
Normal file
84
packages/coding-agent/examples/sdk/12-full-control.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Full Control
|
||||
*
|
||||
* Replace everything - no discovery, explicit configuration.
|
||||
* Still uses OAuth from ~/.pi/agent for convenience.
|
||||
*/
|
||||
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import {
|
||||
createAgentSession,
|
||||
configureOAuthStorage,
|
||||
defaultGetApiKey,
|
||||
findModel,
|
||||
SessionManager,
|
||||
readTool,
|
||||
bashTool,
|
||||
type HookFactory,
|
||||
type CustomAgentTool,
|
||||
} from "../../src/index.js";
|
||||
import { getAgentDir } from "../../src/config.js";
|
||||
|
||||
// Use OAuth from default location
|
||||
configureOAuthStorage(getAgentDir());
|
||||
|
||||
// Custom API key with fallback
|
||||
const getApiKey = async (model: { provider: string }) => {
|
||||
if (model.provider === "anthropic" && process.env.MY_ANTHROPIC_KEY) {
|
||||
return process.env.MY_ANTHROPIC_KEY;
|
||||
}
|
||||
return defaultGetApiKey()(model as any);
|
||||
};
|
||||
|
||||
// Inline hook
|
||||
const auditHook: HookFactory = (api) => {
|
||||
api.on("tool_call", async (event) => {
|
||||
console.log(`[Audit] ${event.toolName}`);
|
||||
return undefined;
|
||||
});
|
||||
};
|
||||
|
||||
// Inline custom tool
|
||||
const statusTool: CustomAgentTool = {
|
||||
name: "status",
|
||||
label: "Status",
|
||||
description: "Get system status",
|
||||
parameters: Type.Object({}),
|
||||
execute: async () => ({
|
||||
content: [{ type: "text", text: `Uptime: ${process.uptime()}s, Node: ${process.version}` }],
|
||||
details: {},
|
||||
}),
|
||||
};
|
||||
|
||||
const { model } = findModel("anthropic", "claude-sonnet-4-20250514");
|
||||
if (!model) throw new Error("Model not found");
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
cwd: process.cwd(),
|
||||
agentDir: "/tmp/my-agent",
|
||||
|
||||
model,
|
||||
thinkingLevel: "off",
|
||||
getApiKey,
|
||||
|
||||
systemPrompt: `You are a minimal assistant.
|
||||
Available: read, bash, status. Be concise.`,
|
||||
|
||||
tools: [readTool, bashTool],
|
||||
customTools: [{ tool: statusTool }],
|
||||
hooks: [{ factory: auditHook }],
|
||||
skills: [],
|
||||
contextFiles: [],
|
||||
slashCommands: [],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
settings: { compaction: { enabled: false } },
|
||||
});
|
||||
|
||||
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.");
|
||||
console.log();
|
||||
138
packages/coding-agent/examples/sdk/README.md
Normal file
138
packages/coding-agent/examples/sdk/README.md
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
# SDK Examples
|
||||
|
||||
Programmatic usage of pi-coding-agent via `createAgentSession()`.
|
||||
|
||||
## Examples
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `01-minimal.ts` | Simplest usage with all defaults |
|
||||
| `02-custom-model.ts` | Select model and thinking level |
|
||||
| `03-custom-prompt.ts` | Replace or modify system prompt |
|
||||
| `04-skills.ts` | Discover, filter, or replace skills |
|
||||
| `05-tools.ts` | Built-in tools, custom tools |
|
||||
| `06-hooks.ts` | Logging, blocking, result modification |
|
||||
| `07-context-files.ts` | AGENTS.md context files |
|
||||
| `08-slash-commands.ts` | File-based slash commands |
|
||||
| `09-api-keys-and-oauth.ts` | API key resolution, OAuth config |
|
||||
| `10-settings.ts` | Override compaction, retry, terminal settings |
|
||||
| `11-sessions.ts` | In-memory, persistent, continue, list sessions |
|
||||
| `12-full-control.ts` | Replace everything, no discovery |
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
cd packages/coding-agent
|
||||
npx tsx examples/sdk/01-minimal.ts
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createAgentSession,
|
||||
configureOAuthStorage,
|
||||
discoverSkills,
|
||||
discoverHooks,
|
||||
discoverCustomTools,
|
||||
discoverContextFiles,
|
||||
discoverSlashCommands,
|
||||
discoverAvailableModels,
|
||||
findModel,
|
||||
defaultGetApiKey,
|
||||
loadSettings,
|
||||
buildSystemPrompt,
|
||||
SessionManager,
|
||||
codingTools,
|
||||
readOnlyTools,
|
||||
readTool, bashTool, editTool, writeTool,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
|
||||
// Minimal
|
||||
const { session } = await createAgentSession();
|
||||
|
||||
// Custom model
|
||||
const { model } = findModel("anthropic", "claude-sonnet-4-20250514");
|
||||
const { session } = await createAgentSession({ model, thinkingLevel: "high" });
|
||||
|
||||
// Modify prompt
|
||||
const { session } = await createAgentSession({
|
||||
systemPrompt: (defaultPrompt) => defaultPrompt + "\n\nBe concise.",
|
||||
});
|
||||
|
||||
// Read-only
|
||||
const { session } = await createAgentSession({ tools: readOnlyTools });
|
||||
|
||||
// In-memory
|
||||
const { session } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
// Full control
|
||||
configureOAuthStorage(); // Use OAuth from ~/.pi/agent
|
||||
const { session } = await createAgentSession({
|
||||
model,
|
||||
getApiKey: async (m) => process.env.MY_KEY,
|
||||
systemPrompt: "You are helpful.",
|
||||
tools: [readTool, bashTool],
|
||||
customTools: [{ tool: myTool }],
|
||||
hooks: [{ factory: myHook }],
|
||||
skills: [],
|
||||
contextFiles: [],
|
||||
slashCommands: [],
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
settings: { compaction: { enabled: false } },
|
||||
});
|
||||
|
||||
// Run prompts
|
||||
session.subscribe((event) => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
await session.prompt("Hello");
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `cwd` | `process.cwd()` | Working directory |
|
||||
| `agentDir` | `~/.pi/agent` | Config directory |
|
||||
| `model` | From settings/first available | Model to use |
|
||||
| `thinkingLevel` | From settings/"off" | off, low, medium, high |
|
||||
| `getApiKey` | Built-in resolver | API key function |
|
||||
| `systemPrompt` | Discovered | String or `(default) => modified` |
|
||||
| `tools` | `codingTools` | Built-in tools |
|
||||
| `customTools` | Discovered | Replaces discovery |
|
||||
| `additionalCustomToolPaths` | `[]` | Merge with discovery |
|
||||
| `hooks` | Discovered | Replaces discovery |
|
||||
| `additionalHookPaths` | `[]` | Merge with discovery |
|
||||
| `skills` | Discovered | Skills for prompt |
|
||||
| `contextFiles` | Discovered | AGENTS.md files |
|
||||
| `slashCommands` | Discovered | File commands |
|
||||
| `sessionManager` | `SessionManager.create(cwd)` | Persistence |
|
||||
| `settings` | From agentDir | Overrides |
|
||||
|
||||
## Events
|
||||
|
||||
```typescript
|
||||
session.subscribe((event) => {
|
||||
switch (event.type) {
|
||||
case "message_update":
|
||||
if (event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
break;
|
||||
case "tool_execution_start":
|
||||
console.log(`Tool: ${event.toolName}`);
|
||||
break;
|
||||
case "tool_execution_end":
|
||||
console.log(`Result: ${event.result}`);
|
||||
break;
|
||||
case "agent_end":
|
||||
console.log("Done");
|
||||
break;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
|
@ -103,6 +103,7 @@ export {
|
|||
discoverModels,
|
||||
discoverSkills,
|
||||
discoverSlashCommands,
|
||||
type FileSlashCommand,
|
||||
findModel as findModelByProviderAndId,
|
||||
loadSettings,
|
||||
// Tools
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue