mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 11:02:17 +00:00
Breaking changes: - Settings: 'hooks' and 'customTools' arrays replaced with 'extensions' - CLI: '--hook' and '--tool' flags replaced with '--extension' / '-e' - API: HookMessage renamed to CustomMessage, role 'hookMessage' to 'custom' - API: FileSlashCommand renamed to PromptTemplate - API: discoverSlashCommands() renamed to discoverPromptTemplates() - Directories: commands/ renamed to prompts/ for prompt templates Migration: - Session version bumped to 3 (auto-migrates v2 sessions) - Old 'hookMessage' role entries converted to 'custom' Structural changes: - src/core/hooks/ and src/core/custom-tools/ merged into src/core/extensions/ - src/core/slash-commands.ts renamed to src/core/prompt-templates.ts - examples/hooks/ and examples/custom-tools/ merged into examples/extensions/ - docs/hooks.md and docs/custom-tools.md merged into docs/extensions.md New test coverage: - test/extensions-runner.test.ts (10 tests) - test/extensions-discovery.test.ts (26 tests) - test/prompt-templates.test.ts
141 lines
4.6 KiB
Markdown
141 lines
4.6 KiB
Markdown
# Extension Examples
|
|
|
|
Example extensions for pi-coding-agent.
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
# Load an extension with --extension flag
|
|
pi --extension examples/extensions/permission-gate.ts
|
|
|
|
# Or copy to extensions directory for auto-discovery
|
|
cp permission-gate.ts ~/.pi/agent/extensions/
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Lifecycle & Safety
|
|
|
|
| Extension | Description |
|
|
|-----------|-------------|
|
|
| `permission-gate.ts` | Prompts for confirmation before dangerous bash commands (rm -rf, sudo, etc.) |
|
|
| `protected-paths.ts` | Blocks writes to protected paths (.env, .git/, node_modules/) |
|
|
| `confirm-destructive.ts` | Confirms before destructive session actions (clear, switch, branch) |
|
|
| `dirty-repo-guard.ts` | Prevents session changes with uncommitted git changes |
|
|
|
|
### Custom Tools
|
|
|
|
| Extension | Description |
|
|
|-----------|-------------|
|
|
| `todo.ts` | Todo list tool + `/todos` command with custom rendering and state persistence |
|
|
| `hello/` | Minimal custom tool example |
|
|
| `question/` | Demonstrates `pi.ui.select()` for asking the user questions |
|
|
| `subagent/` | Delegate tasks to specialized subagents with isolated context windows |
|
|
|
|
### Commands & UI
|
|
|
|
| Extension | Description |
|
|
|-----------|-------------|
|
|
| `plan-mode.ts` | Claude Code-style plan mode for read-only exploration with `/plan` command |
|
|
| `tools.ts` | Interactive `/tools` command to enable/disable tools with session persistence |
|
|
| `handoff.ts` | Transfer context to a new focused session via `/handoff <goal>` |
|
|
| `qna.ts` | Extracts questions from last response into editor via `ctx.ui.setEditorText()` |
|
|
| `status-line.ts` | Shows turn progress in footer via `ctx.ui.setStatus()` with themed colors |
|
|
| `snake.ts` | Snake game with custom UI, keyboard handling, and session persistence |
|
|
|
|
### Git Integration
|
|
|
|
| Extension | Description |
|
|
|-----------|-------------|
|
|
| `git-checkpoint.ts` | Creates git stash checkpoints at each turn for code restoration on branch |
|
|
| `auto-commit-on-exit.ts` | Auto-commits on exit using last assistant message for commit message |
|
|
|
|
### System Prompt & Compaction
|
|
|
|
| Extension | Description |
|
|
|-----------|-------------|
|
|
| `pirate.ts` | Demonstrates `systemPromptAppend` to dynamically modify system prompt |
|
|
| `custom-compaction.ts` | Custom compaction that summarizes entire conversation |
|
|
|
|
### External Dependencies
|
|
|
|
| Extension | Description |
|
|
|-----------|-------------|
|
|
| `chalk-logger.ts` | Uses chalk from parent node_modules (demonstrates jiti module resolution) |
|
|
| `with-deps/` | Extension with its own package.json and dependencies |
|
|
| `file-trigger.ts` | Watches a trigger file and injects contents into conversation |
|
|
|
|
## Writing Extensions
|
|
|
|
See [docs/extensions.md](../../docs/extensions.md) for full documentation.
|
|
|
|
```typescript
|
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
import { Type } from "@sinclair/typebox";
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
// Subscribe to lifecycle events
|
|
pi.on("tool_call", async (event, ctx) => {
|
|
if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
|
|
const ok = await ctx.ui.confirm("Dangerous!", "Allow rm -rf?");
|
|
if (!ok) return { block: true, reason: "Blocked by user" };
|
|
}
|
|
});
|
|
|
|
// Register custom tools
|
|
pi.registerTool({
|
|
name: "greet",
|
|
label: "Greeting",
|
|
description: "Generate a greeting",
|
|
parameters: Type.Object({
|
|
name: Type.String({ description: "Name to greet" }),
|
|
}),
|
|
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
|
return {
|
|
content: [{ type: "text", text: `Hello, ${params.name}!` }],
|
|
details: {},
|
|
};
|
|
},
|
|
});
|
|
|
|
// Register commands
|
|
pi.registerCommand("hello", {
|
|
description: "Say hello",
|
|
handler: async (args, ctx) => {
|
|
ctx.ui.notify("Hello!", "info");
|
|
},
|
|
});
|
|
}
|
|
```
|
|
|
|
## Key Patterns
|
|
|
|
**Use StringEnum for string parameters** (required for Google API compatibility):
|
|
```typescript
|
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
|
|
// Good
|
|
action: StringEnum(["list", "add"] as const)
|
|
|
|
// Bad - doesn't work with Google
|
|
action: Type.Union([Type.Literal("list"), Type.Literal("add")])
|
|
```
|
|
|
|
**State persistence via details:**
|
|
```typescript
|
|
// Store state in tool result details for proper branching support
|
|
return {
|
|
content: [{ type: "text", text: "Done" }],
|
|
details: { todos: [...todos], nextId }, // Persisted in session
|
|
};
|
|
|
|
// Reconstruct on session events
|
|
pi.on("session_start", async (_event, ctx) => {
|
|
for (const entry of ctx.sessionManager.getBranch()) {
|
|
if (entry.type === "message" && entry.message.toolName === "my_tool") {
|
|
const details = entry.message.details;
|
|
// Reconstruct state from details
|
|
}
|
|
}
|
|
});
|
|
```
|