@oh-my-pi/pi-coding-agent 1.337.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1228 -0
- package/README.md +1041 -0
- package/docs/compaction.md +403 -0
- package/docs/custom-tools.md +541 -0
- package/docs/extension-loading.md +1004 -0
- package/docs/hooks.md +867 -0
- package/docs/rpc.md +1040 -0
- package/docs/sdk.md +994 -0
- package/docs/session-tree-plan.md +441 -0
- package/docs/session.md +240 -0
- package/docs/skills.md +290 -0
- package/docs/theme.md +637 -0
- package/docs/tree.md +197 -0
- package/docs/tui.md +341 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +124 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/custom-tools/question/index.ts +84 -0
- package/examples/custom-tools/subagent/README.md +172 -0
- package/examples/custom-tools/subagent/agents/planner.md +37 -0
- package/examples/custom-tools/subagent/agents/reviewer.md +35 -0
- package/examples/custom-tools/subagent/agents/scout.md +50 -0
- package/examples/custom-tools/subagent/agents/worker.md +24 -0
- package/examples/custom-tools/subagent/agents.ts +156 -0
- package/examples/custom-tools/subagent/commands/implement-and-review.md +10 -0
- package/examples/custom-tools/subagent/commands/implement.md +10 -0
- package/examples/custom-tools/subagent/commands/scout-and-plan.md +9 -0
- package/examples/custom-tools/subagent/index.ts +1002 -0
- package/examples/custom-tools/todo/index.ts +212 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +49 -0
- package/examples/hooks/confirm-destructive.ts +59 -0
- package/examples/hooks/custom-compaction.ts +116 -0
- package/examples/hooks/dirty-repo-guard.ts +52 -0
- package/examples/hooks/file-trigger.ts +41 -0
- package/examples/hooks/git-checkpoint.ts +53 -0
- package/examples/hooks/handoff.ts +150 -0
- package/examples/hooks/permission-gate.ts +34 -0
- package/examples/hooks/protected-paths.ts +30 -0
- package/examples/hooks/qna.ts +119 -0
- package/examples/hooks/snake.ts +343 -0
- package/examples/hooks/status-line.ts +40 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +44 -0
- package/examples/sdk/04-skills.ts +44 -0
- package/examples/sdk/05-tools.ts +90 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +36 -0
- package/examples/sdk/08-slash-commands.ts +42 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +55 -0
- package/examples/sdk/10-settings.ts +38 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +95 -0
- package/examples/sdk/README.md +154 -0
- package/package.json +81 -0
- package/src/cli/args.ts +246 -0
- package/src/cli/file-processor.ts +72 -0
- package/src/cli/list-models.ts +104 -0
- package/src/cli/plugin-cli.ts +650 -0
- package/src/cli/session-picker.ts +41 -0
- package/src/cli.ts +10 -0
- package/src/commands/init.md +20 -0
- package/src/config.ts +159 -0
- package/src/core/agent-session.ts +1900 -0
- package/src/core/auth-storage.ts +236 -0
- package/src/core/bash-executor.ts +196 -0
- package/src/core/compaction/branch-summarization.ts +343 -0
- package/src/core/compaction/compaction.ts +742 -0
- package/src/core/compaction/index.ts +7 -0
- package/src/core/compaction/utils.ts +154 -0
- package/src/core/custom-tools/index.ts +21 -0
- package/src/core/custom-tools/loader.ts +248 -0
- package/src/core/custom-tools/types.ts +169 -0
- package/src/core/custom-tools/wrapper.ts +28 -0
- package/src/core/exec.ts +129 -0
- package/src/core/export-html/index.ts +211 -0
- package/src/core/export-html/template.css +781 -0
- package/src/core/export-html/template.html +54 -0
- package/src/core/export-html/template.js +1185 -0
- package/src/core/export-html/vendor/highlight.min.js +1213 -0
- package/src/core/export-html/vendor/marked.min.js +6 -0
- package/src/core/hooks/index.ts +16 -0
- package/src/core/hooks/loader.ts +312 -0
- package/src/core/hooks/runner.ts +434 -0
- package/src/core/hooks/tool-wrapper.ts +99 -0
- package/src/core/hooks/types.ts +773 -0
- package/src/core/index.ts +52 -0
- package/src/core/mcp/client.ts +158 -0
- package/src/core/mcp/config.ts +154 -0
- package/src/core/mcp/index.ts +45 -0
- package/src/core/mcp/loader.ts +68 -0
- package/src/core/mcp/manager.ts +181 -0
- package/src/core/mcp/tool-bridge.ts +148 -0
- package/src/core/mcp/transports/http.ts +316 -0
- package/src/core/mcp/transports/index.ts +6 -0
- package/src/core/mcp/transports/stdio.ts +252 -0
- package/src/core/mcp/types.ts +220 -0
- package/src/core/messages.ts +189 -0
- package/src/core/model-registry.ts +317 -0
- package/src/core/model-resolver.ts +393 -0
- package/src/core/plugins/doctor.ts +59 -0
- package/src/core/plugins/index.ts +38 -0
- package/src/core/plugins/installer.ts +189 -0
- package/src/core/plugins/loader.ts +338 -0
- package/src/core/plugins/manager.ts +672 -0
- package/src/core/plugins/parser.ts +105 -0
- package/src/core/plugins/paths.ts +32 -0
- package/src/core/plugins/types.ts +190 -0
- package/src/core/sdk.ts +760 -0
- package/src/core/session-manager.ts +1128 -0
- package/src/core/settings-manager.ts +443 -0
- package/src/core/skills.ts +437 -0
- package/src/core/slash-commands.ts +248 -0
- package/src/core/system-prompt.ts +439 -0
- package/src/core/timings.ts +25 -0
- package/src/core/tools/ask.ts +211 -0
- package/src/core/tools/bash-interceptor.ts +120 -0
- package/src/core/tools/bash.ts +250 -0
- package/src/core/tools/context.ts +32 -0
- package/src/core/tools/edit-diff.ts +475 -0
- package/src/core/tools/edit.ts +208 -0
- package/src/core/tools/exa/company.ts +59 -0
- package/src/core/tools/exa/index.ts +64 -0
- package/src/core/tools/exa/linkedin.ts +59 -0
- package/src/core/tools/exa/logger.ts +56 -0
- package/src/core/tools/exa/mcp-client.ts +368 -0
- package/src/core/tools/exa/render.ts +196 -0
- package/src/core/tools/exa/researcher.ts +90 -0
- package/src/core/tools/exa/search.ts +337 -0
- package/src/core/tools/exa/types.ts +168 -0
- package/src/core/tools/exa/websets.ts +248 -0
- package/src/core/tools/find.ts +261 -0
- package/src/core/tools/grep.ts +555 -0
- package/src/core/tools/index.ts +202 -0
- package/src/core/tools/ls.ts +140 -0
- package/src/core/tools/lsp/client.ts +605 -0
- package/src/core/tools/lsp/config.ts +147 -0
- package/src/core/tools/lsp/edits.ts +101 -0
- package/src/core/tools/lsp/index.ts +804 -0
- package/src/core/tools/lsp/render.ts +447 -0
- package/src/core/tools/lsp/rust-analyzer.ts +145 -0
- package/src/core/tools/lsp/types.ts +463 -0
- package/src/core/tools/lsp/utils.ts +486 -0
- package/src/core/tools/notebook.ts +229 -0
- package/src/core/tools/path-utils.ts +61 -0
- package/src/core/tools/read.ts +240 -0
- package/src/core/tools/renderers.ts +540 -0
- package/src/core/tools/task/agents.ts +153 -0
- package/src/core/tools/task/artifacts.ts +114 -0
- package/src/core/tools/task/bundled-agents/browser.md +71 -0
- package/src/core/tools/task/bundled-agents/explore.md +82 -0
- package/src/core/tools/task/bundled-agents/plan.md +54 -0
- package/src/core/tools/task/bundled-agents/reviewer.md +59 -0
- package/src/core/tools/task/bundled-agents/task.md +53 -0
- package/src/core/tools/task/bundled-commands/architect-plan.md +10 -0
- package/src/core/tools/task/bundled-commands/implement-with-critic.md +11 -0
- package/src/core/tools/task/bundled-commands/implement.md +11 -0
- package/src/core/tools/task/commands.ts +213 -0
- package/src/core/tools/task/discovery.ts +208 -0
- package/src/core/tools/task/executor.ts +367 -0
- package/src/core/tools/task/index.ts +388 -0
- package/src/core/tools/task/model-resolver.ts +115 -0
- package/src/core/tools/task/parallel.ts +38 -0
- package/src/core/tools/task/render.ts +232 -0
- package/src/core/tools/task/types.ts +99 -0
- package/src/core/tools/truncate.ts +265 -0
- package/src/core/tools/web-fetch.ts +2370 -0
- package/src/core/tools/web-search/auth.ts +193 -0
- package/src/core/tools/web-search/index.ts +537 -0
- package/src/core/tools/web-search/providers/anthropic.ts +198 -0
- package/src/core/tools/web-search/providers/exa.ts +302 -0
- package/src/core/tools/web-search/providers/perplexity.ts +195 -0
- package/src/core/tools/web-search/render.ts +182 -0
- package/src/core/tools/web-search/types.ts +180 -0
- package/src/core/tools/write.ts +99 -0
- package/src/index.ts +176 -0
- package/src/main.ts +464 -0
- package/src/migrations.ts +135 -0
- package/src/modes/index.ts +43 -0
- package/src/modes/interactive/components/armin.ts +382 -0
- package/src/modes/interactive/components/assistant-message.ts +86 -0
- package/src/modes/interactive/components/bash-execution.ts +196 -0
- package/src/modes/interactive/components/bordered-loader.ts +41 -0
- package/src/modes/interactive/components/branch-summary-message.ts +42 -0
- package/src/modes/interactive/components/compaction-summary-message.ts +45 -0
- package/src/modes/interactive/components/custom-editor.ts +122 -0
- package/src/modes/interactive/components/diff.ts +147 -0
- package/src/modes/interactive/components/dynamic-border.ts +25 -0
- package/src/modes/interactive/components/footer.ts +381 -0
- package/src/modes/interactive/components/hook-editor.ts +117 -0
- package/src/modes/interactive/components/hook-input.ts +64 -0
- package/src/modes/interactive/components/hook-message.ts +96 -0
- package/src/modes/interactive/components/hook-selector.ts +91 -0
- package/src/modes/interactive/components/model-selector.ts +247 -0
- package/src/modes/interactive/components/oauth-selector.ts +120 -0
- package/src/modes/interactive/components/plugin-settings.ts +479 -0
- package/src/modes/interactive/components/queue-mode-selector.ts +56 -0
- package/src/modes/interactive/components/session-selector.ts +204 -0
- package/src/modes/interactive/components/settings-selector.ts +453 -0
- package/src/modes/interactive/components/show-images-selector.ts +45 -0
- package/src/modes/interactive/components/theme-selector.ts +62 -0
- package/src/modes/interactive/components/thinking-selector.ts +64 -0
- package/src/modes/interactive/components/tool-execution.ts +675 -0
- package/src/modes/interactive/components/tree-selector.ts +866 -0
- package/src/modes/interactive/components/user-message-selector.ts +159 -0
- package/src/modes/interactive/components/user-message.ts +18 -0
- package/src/modes/interactive/components/visual-truncate.ts +50 -0
- package/src/modes/interactive/components/welcome.ts +183 -0
- package/src/modes/interactive/interactive-mode.ts +2516 -0
- package/src/modes/interactive/theme/dark.json +101 -0
- package/src/modes/interactive/theme/light.json +98 -0
- package/src/modes/interactive/theme/theme-schema.json +308 -0
- package/src/modes/interactive/theme/theme.ts +998 -0
- package/src/modes/print-mode.ts +128 -0
- package/src/modes/rpc/rpc-client.ts +527 -0
- package/src/modes/rpc/rpc-mode.ts +483 -0
- package/src/modes/rpc/rpc-types.ts +203 -0
- package/src/utils/changelog.ts +99 -0
- package/src/utils/clipboard.ts +265 -0
- package/src/utils/fuzzy.ts +108 -0
- package/src/utils/mime.ts +30 -0
- package/src/utils/shell.ts +276 -0
- package/src/utils/tools-manager.ts +274 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Line Hook
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates ctx.ui.setStatus() for displaying persistent status text in the footer.
|
|
5
|
+
* Shows turn progress with themed colors.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
|
9
|
+
|
|
10
|
+
export default function (pi: HookAPI) {
|
|
11
|
+
let turnCount = 0;
|
|
12
|
+
|
|
13
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
14
|
+
const theme = ctx.ui.theme;
|
|
15
|
+
ctx.ui.setStatus("status-demo", theme.fg("dim", "Ready"));
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
pi.on("turn_start", async (_event, ctx) => {
|
|
19
|
+
turnCount++;
|
|
20
|
+
const theme = ctx.ui.theme;
|
|
21
|
+
const spinner = theme.fg("accent", "●");
|
|
22
|
+
const text = theme.fg("dim", ` Turn ${turnCount}...`);
|
|
23
|
+
ctx.ui.setStatus("status-demo", spinner + text);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
pi.on("turn_end", async (_event, ctx) => {
|
|
27
|
+
const theme = ctx.ui.theme;
|
|
28
|
+
const check = theme.fg("success", "✓");
|
|
29
|
+
const text = theme.fg("dim", ` Turn ${turnCount} complete`);
|
|
30
|
+
ctx.ui.setStatus("status-demo", check + text);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
pi.on("session_switch", async (event, ctx) => {
|
|
34
|
+
if (event.reason === "new") {
|
|
35
|
+
turnCount = 0;
|
|
36
|
+
const theme = ctx.ui.theme;
|
|
37
|
+
ctx.ui.setStatus("status-demo", theme.fg("dim", "Ready"));
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal SDK Usage
|
|
3
|
+
*
|
|
4
|
+
* Uses all defaults: discovers skills, hooks, tools, context files
|
|
5
|
+
* from cwd and ~/.pi/agent. Model chosen from settings or first available.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createAgentSession } from "@oh-my-pi/pi-coding-agent";
|
|
9
|
+
|
|
10
|
+
const { session } = await createAgentSession();
|
|
11
|
+
|
|
12
|
+
session.subscribe((event) => {
|
|
13
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
14
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await session.prompt("What files are in the current directory?");
|
|
19
|
+
session.state.messages.forEach((msg) => {
|
|
20
|
+
console.log(msg);
|
|
21
|
+
});
|
|
22
|
+
console.log();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Model Selection
|
|
3
|
+
*
|
|
4
|
+
* Shows how to select a specific model and thinking level.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getModel } from "@oh-my-pi/pi-ai";
|
|
8
|
+
import { createAgentSession, discoverAuthStorage, discoverModels } from "@oh-my-pi/pi-coding-agent";
|
|
9
|
+
|
|
10
|
+
// Set up auth storage and model registry
|
|
11
|
+
const authStorage = discoverAuthStorage();
|
|
12
|
+
const modelRegistry = discoverModels(authStorage);
|
|
13
|
+
|
|
14
|
+
// Option 1: Find a specific built-in model by provider/id
|
|
15
|
+
const opus = getModel("anthropic", "claude-opus-4-5");
|
|
16
|
+
if (opus) {
|
|
17
|
+
console.log(`Found model: ${opus.provider}/${opus.id}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Option 2: Find model via registry (includes custom models from models.json)
|
|
21
|
+
const customModel = modelRegistry.find("my-provider", "my-model");
|
|
22
|
+
if (customModel) {
|
|
23
|
+
console.log(`Found custom model: ${customModel.provider}/${customModel.id}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Option 3: Pick from available models (have valid API keys)
|
|
27
|
+
const available = await modelRegistry.getAvailable();
|
|
28
|
+
console.log(
|
|
29
|
+
"Available models:",
|
|
30
|
+
available.map((m) => `${m.provider}/${m.id}`),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (available.length > 0) {
|
|
34
|
+
const { session } = await createAgentSession({
|
|
35
|
+
model: available[0],
|
|
36
|
+
thinkingLevel: "medium", // off, low, medium, high
|
|
37
|
+
authStorage,
|
|
38
|
+
modelRegistry,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
session.subscribe((event) => {
|
|
42
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
43
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
await session.prompt("Say hello in one sentence.");
|
|
48
|
+
console.log();
|
|
49
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom System Prompt
|
|
3
|
+
*
|
|
4
|
+
* Shows how to replace or modify the default system prompt.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createAgentSession, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
|
8
|
+
|
|
9
|
+
// Option 1: Replace prompt entirely
|
|
10
|
+
const { session: session1 } = await createAgentSession({
|
|
11
|
+
systemPrompt: `You are a helpful assistant that speaks like a pirate.
|
|
12
|
+
Always end responses with "Arrr!"`,
|
|
13
|
+
sessionManager: SessionManager.inMemory(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
session1.subscribe((event) => {
|
|
17
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
18
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
console.log("=== Replace prompt ===");
|
|
23
|
+
await session1.prompt("What is 2 + 2?");
|
|
24
|
+
console.log("\n");
|
|
25
|
+
|
|
26
|
+
// Option 2: Modify default prompt (receives default, returns modified)
|
|
27
|
+
const { session: session2 } = await createAgentSession({
|
|
28
|
+
systemPrompt: (defaultPrompt) => `${defaultPrompt}
|
|
29
|
+
|
|
30
|
+
## Additional Instructions
|
|
31
|
+
- Always be concise
|
|
32
|
+
- Use bullet points when listing things`,
|
|
33
|
+
sessionManager: SessionManager.inMemory(),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
session2.subscribe((event) => {
|
|
37
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
38
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
console.log("=== Modify prompt ===");
|
|
43
|
+
await session2.prompt("List 3 benefits of TypeScript.");
|
|
44
|
+
console.log();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills Configuration
|
|
3
|
+
*
|
|
4
|
+
* Skills provide specialized instructions loaded into the system prompt.
|
|
5
|
+
* Discover, filter, merge, or replace them.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createAgentSession, discoverSkills, SessionManager, type Skill } from "@oh-my-pi/pi-coding-agent";
|
|
9
|
+
|
|
10
|
+
// Discover all skills from cwd/.pi/skills, ~/.pi/agent/skills, etc.
|
|
11
|
+
const allSkills = discoverSkills();
|
|
12
|
+
console.log(
|
|
13
|
+
"Discovered skills:",
|
|
14
|
+
allSkills.map((s) => s.name),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// Filter to specific skills
|
|
18
|
+
const filteredSkills = allSkills.filter((s) => s.name.includes("browser") || s.name.includes("search"));
|
|
19
|
+
|
|
20
|
+
// Or define custom skills inline
|
|
21
|
+
const customSkill: Skill = {
|
|
22
|
+
name: "my-skill",
|
|
23
|
+
description: "Custom project instructions",
|
|
24
|
+
filePath: "/virtual/SKILL.md",
|
|
25
|
+
baseDir: "/virtual",
|
|
26
|
+
source: "custom",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Use filtered + custom skills
|
|
30
|
+
await createAgentSession({
|
|
31
|
+
skills: [...filteredSkills, customSkill],
|
|
32
|
+
sessionManager: SessionManager.inMemory(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(`Session created with ${filteredSkills.length + 1} skills`);
|
|
36
|
+
|
|
37
|
+
// To disable all skills:
|
|
38
|
+
// skills: []
|
|
39
|
+
|
|
40
|
+
// To use discovery with filtering via settings:
|
|
41
|
+
// discoverSkills(process.cwd(), undefined, {
|
|
42
|
+
// ignoredSkills: ["browser-tools"], // glob patterns to exclude
|
|
43
|
+
// includeSkills: ["brave-*"], // glob patterns to include (empty = all)
|
|
44
|
+
// })
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools Configuration
|
|
3
|
+
*
|
|
4
|
+
* Use built-in tool sets, individual tools, or add custom tools.
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: When using a custom `cwd`, you must use the tool factory functions
|
|
7
|
+
* (createCodingTools, createReadOnlyTools, createReadTool, etc.) to ensure
|
|
8
|
+
* tools resolve paths relative to your cwd, not process.cwd().
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
bashTool, // read, bash, edit, write - uses process.cwd()
|
|
13
|
+
type CustomTool,
|
|
14
|
+
createAgentSession,
|
|
15
|
+
createBashTool,
|
|
16
|
+
createCodingTools, // Factory: creates tools for specific cwd
|
|
17
|
+
createGrepTool,
|
|
18
|
+
createReadTool,
|
|
19
|
+
grepTool,
|
|
20
|
+
readOnlyTools, // read, grep, find, ls - uses process.cwd()
|
|
21
|
+
readTool,
|
|
22
|
+
SessionManager,
|
|
23
|
+
} from "@oh-my-pi/pi-coding-agent";
|
|
24
|
+
import { Type } from "@sinclair/typebox";
|
|
25
|
+
|
|
26
|
+
// Read-only mode (no edit/write) - uses process.cwd()
|
|
27
|
+
await createAgentSession({
|
|
28
|
+
tools: readOnlyTools,
|
|
29
|
+
sessionManager: SessionManager.inMemory(),
|
|
30
|
+
});
|
|
31
|
+
console.log("Read-only session created");
|
|
32
|
+
|
|
33
|
+
// Custom tool selection - uses process.cwd()
|
|
34
|
+
await createAgentSession({
|
|
35
|
+
tools: [readTool, bashTool, grepTool],
|
|
36
|
+
sessionManager: SessionManager.inMemory(),
|
|
37
|
+
});
|
|
38
|
+
console.log("Custom tools session created");
|
|
39
|
+
|
|
40
|
+
// With custom cwd - MUST use factory functions!
|
|
41
|
+
const customCwd = "/path/to/project";
|
|
42
|
+
await createAgentSession({
|
|
43
|
+
cwd: customCwd,
|
|
44
|
+
tools: createCodingTools(customCwd), // Tools resolve paths relative to customCwd
|
|
45
|
+
sessionManager: SessionManager.inMemory(),
|
|
46
|
+
});
|
|
47
|
+
console.log("Custom cwd session created");
|
|
48
|
+
|
|
49
|
+
// Or pick specific tools for custom cwd
|
|
50
|
+
await createAgentSession({
|
|
51
|
+
cwd: customCwd,
|
|
52
|
+
tools: [createReadTool(customCwd), createBashTool(customCwd), createGrepTool(customCwd)],
|
|
53
|
+
sessionManager: SessionManager.inMemory(),
|
|
54
|
+
});
|
|
55
|
+
console.log("Specific tools with custom cwd session created");
|
|
56
|
+
|
|
57
|
+
// Inline custom tool (needs TypeBox schema)
|
|
58
|
+
const weatherTool: CustomTool = {
|
|
59
|
+
name: "get_weather",
|
|
60
|
+
label: "Get Weather",
|
|
61
|
+
description: "Get current weather for a city",
|
|
62
|
+
parameters: Type.Object({
|
|
63
|
+
city: Type.String({ description: "City name" }),
|
|
64
|
+
}),
|
|
65
|
+
execute: async (_toolCallId, params) => ({
|
|
66
|
+
content: [{ type: "text", text: `Weather in ${(params as { city: string }).city}: 22°C, sunny` }],
|
|
67
|
+
details: {},
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const { session } = await createAgentSession({
|
|
72
|
+
customTools: [{ tool: weatherTool }],
|
|
73
|
+
sessionManager: SessionManager.inMemory(),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
session.subscribe((event) => {
|
|
77
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
78
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await session.prompt("What's the weather in Tokyo?");
|
|
83
|
+
console.log();
|
|
84
|
+
|
|
85
|
+
// Merge with discovered tools from cwd/.pi/tools and ~/.pi/agent/tools:
|
|
86
|
+
// const discovered = await discoverCustomTools();
|
|
87
|
+
// customTools: [...discovered, { tool: myTool }]
|
|
88
|
+
|
|
89
|
+
// Or add paths without replacing discovery:
|
|
90
|
+
// additionalCustomToolPaths: ["/extra/tools"]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hooks Configuration
|
|
3
|
+
*
|
|
4
|
+
* Hooks intercept agent events for logging, blocking, or modification.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createAgentSession, type HookFactory, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
|
8
|
+
|
|
9
|
+
// Logging hook
|
|
10
|
+
const loggingHook: HookFactory = (api) => {
|
|
11
|
+
api.on("agent_start", async () => {
|
|
12
|
+
console.log("[Hook] Agent starting");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
api.on("tool_call", async (event) => {
|
|
16
|
+
console.log(`[Hook] Tool: ${event.toolName}`);
|
|
17
|
+
return undefined; // Don't block
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
api.on("agent_end", async (event) => {
|
|
21
|
+
console.log(`[Hook] Done, ${event.messages.length} messages`);
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Blocking hook (returns { block: true, reason: "..." })
|
|
26
|
+
const safetyHook: HookFactory = (api) => {
|
|
27
|
+
api.on("tool_call", async (event) => {
|
|
28
|
+
if (event.toolName === "bash") {
|
|
29
|
+
const cmd = (event.input as { command?: string }).command ?? "";
|
|
30
|
+
if (cmd.includes("rm -rf")) {
|
|
31
|
+
return { block: true, reason: "Dangerous command blocked" };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Use inline hooks
|
|
39
|
+
const { session } = await createAgentSession({
|
|
40
|
+
hooks: [{ factory: loggingHook }, { factory: safetyHook }],
|
|
41
|
+
sessionManager: SessionManager.inMemory(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
session.subscribe((event) => {
|
|
45
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
46
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
await session.prompt("List files in the current directory.");
|
|
51
|
+
console.log();
|
|
52
|
+
|
|
53
|
+
// Disable all hooks:
|
|
54
|
+
// hooks: []
|
|
55
|
+
|
|
56
|
+
// Merge with discovered hooks:
|
|
57
|
+
// const discovered = await discoverHooks();
|
|
58
|
+
// hooks: [...discovered, { factory: myHook }]
|
|
59
|
+
|
|
60
|
+
// Add paths without replacing discovery:
|
|
61
|
+
// additionalHookPaths: ["/extra/hooks"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Files (AGENTS.md)
|
|
3
|
+
*
|
|
4
|
+
* Context files provide project-specific instructions loaded into the system prompt.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createAgentSession, discoverContextFiles, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
|
8
|
+
|
|
9
|
+
// Discover AGENTS.md files walking up from cwd
|
|
10
|
+
const discovered = discoverContextFiles();
|
|
11
|
+
console.log("Discovered context files:");
|
|
12
|
+
for (const file of discovered) {
|
|
13
|
+
console.log(` - ${file.path} (${file.content.length} chars)`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Use custom context files
|
|
17
|
+
await createAgentSession({
|
|
18
|
+
contextFiles: [
|
|
19
|
+
...discovered,
|
|
20
|
+
{
|
|
21
|
+
path: "/virtual/AGENTS.md",
|
|
22
|
+
content: `# Project Guidelines
|
|
23
|
+
|
|
24
|
+
## Code Style
|
|
25
|
+
- Use TypeScript strict mode
|
|
26
|
+
- No any types
|
|
27
|
+
- Prefer const over let`,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
sessionManager: SessionManager.inMemory(),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(`Session created with ${discovered.length + 1} context files`);
|
|
34
|
+
|
|
35
|
+
// Disable context files:
|
|
36
|
+
// contextFiles: []
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash Commands
|
|
3
|
+
*
|
|
4
|
+
* File-based commands that inject content when invoked with /commandname.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
createAgentSession,
|
|
9
|
+
discoverSlashCommands,
|
|
10
|
+
type FileSlashCommand,
|
|
11
|
+
SessionManager,
|
|
12
|
+
} from "@oh-my-pi/pi-coding-agent";
|
|
13
|
+
|
|
14
|
+
// Discover commands from cwd/.pi/commands/ and ~/.pi/agent/commands/
|
|
15
|
+
const discovered = discoverSlashCommands();
|
|
16
|
+
console.log("Discovered slash commands:");
|
|
17
|
+
for (const cmd of discovered) {
|
|
18
|
+
console.log(` /${cmd.name}: ${cmd.description}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Define custom commands
|
|
22
|
+
const deployCommand: FileSlashCommand = {
|
|
23
|
+
name: "deploy",
|
|
24
|
+
description: "Deploy the application",
|
|
25
|
+
source: "(custom)",
|
|
26
|
+
content: `# Deploy Instructions
|
|
27
|
+
|
|
28
|
+
1. Build: npm run build
|
|
29
|
+
2. Test: npm test
|
|
30
|
+
3. Deploy: npm run deploy`,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Use discovered + custom commands
|
|
34
|
+
await createAgentSession({
|
|
35
|
+
slashCommands: [...discovered, deployCommand],
|
|
36
|
+
sessionManager: SessionManager.inMemory(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log(`Session created with ${discovered.length + 1} slash commands`);
|
|
40
|
+
|
|
41
|
+
// Disable slash commands:
|
|
42
|
+
// slashCommands: []
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Keys and OAuth
|
|
3
|
+
*
|
|
4
|
+
* Configure API key resolution via AuthStorage and ModelRegistry.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
AuthStorage,
|
|
9
|
+
createAgentSession,
|
|
10
|
+
discoverAuthStorage,
|
|
11
|
+
discoverModels,
|
|
12
|
+
ModelRegistry,
|
|
13
|
+
SessionManager,
|
|
14
|
+
} from "@oh-my-pi/pi-coding-agent";
|
|
15
|
+
|
|
16
|
+
// Default: discoverAuthStorage() uses ~/.pi/agent/auth.json
|
|
17
|
+
// discoverModels() loads built-in + custom models from ~/.pi/agent/models.json
|
|
18
|
+
const authStorage = discoverAuthStorage();
|
|
19
|
+
const modelRegistry = discoverModels(authStorage);
|
|
20
|
+
|
|
21
|
+
await createAgentSession({
|
|
22
|
+
sessionManager: SessionManager.inMemory(),
|
|
23
|
+
authStorage,
|
|
24
|
+
modelRegistry,
|
|
25
|
+
});
|
|
26
|
+
console.log("Session with default auth storage and model registry");
|
|
27
|
+
|
|
28
|
+
// Custom auth storage location
|
|
29
|
+
const customAuthStorage = new AuthStorage("/tmp/my-app/auth.json");
|
|
30
|
+
const customModelRegistry = new ModelRegistry(customAuthStorage, "/tmp/my-app/models.json");
|
|
31
|
+
|
|
32
|
+
await createAgentSession({
|
|
33
|
+
sessionManager: SessionManager.inMemory(),
|
|
34
|
+
authStorage: customAuthStorage,
|
|
35
|
+
modelRegistry: customModelRegistry,
|
|
36
|
+
});
|
|
37
|
+
console.log("Session with custom auth storage location");
|
|
38
|
+
|
|
39
|
+
// Runtime API key override (not persisted to disk)
|
|
40
|
+
authStorage.setRuntimeApiKey("anthropic", "sk-my-temp-key");
|
|
41
|
+
await createAgentSession({
|
|
42
|
+
sessionManager: SessionManager.inMemory(),
|
|
43
|
+
authStorage,
|
|
44
|
+
modelRegistry,
|
|
45
|
+
});
|
|
46
|
+
console.log("Session with runtime API key override");
|
|
47
|
+
|
|
48
|
+
// No models.json - only built-in models
|
|
49
|
+
const simpleRegistry = new ModelRegistry(authStorage); // null = no models.json
|
|
50
|
+
await createAgentSession({
|
|
51
|
+
sessionManager: SessionManager.inMemory(),
|
|
52
|
+
authStorage,
|
|
53
|
+
modelRegistry: simpleRegistry,
|
|
54
|
+
});
|
|
55
|
+
console.log("Session with only built-in models");
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Configuration
|
|
3
|
+
*
|
|
4
|
+
* Override settings using SettingsManager.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createAgentSession, loadSettings, SessionManager, SettingsManager } from "@oh-my-pi/pi-coding-agent";
|
|
8
|
+
|
|
9
|
+
// Load current settings (merged global + project)
|
|
10
|
+
const settings = loadSettings();
|
|
11
|
+
console.log("Current settings:", JSON.stringify(settings, null, 2));
|
|
12
|
+
|
|
13
|
+
// Override specific settings
|
|
14
|
+
const settingsManager = SettingsManager.create();
|
|
15
|
+
settingsManager.applyOverrides({
|
|
16
|
+
compaction: { enabled: false },
|
|
17
|
+
retry: { enabled: true, maxRetries: 5, baseDelayMs: 1000 },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await createAgentSession({
|
|
21
|
+
settingsManager,
|
|
22
|
+
sessionManager: SessionManager.inMemory(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.log("Session created with custom settings");
|
|
26
|
+
|
|
27
|
+
// For testing without file I/O:
|
|
28
|
+
const inMemorySettings = SettingsManager.inMemory({
|
|
29
|
+
compaction: { enabled: false },
|
|
30
|
+
retry: { enabled: false },
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await createAgentSession({
|
|
34
|
+
settingsManager: inMemorySettings,
|
|
35
|
+
sessionManager: SessionManager.inMemory(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
console.log("Test session created with in-memory settings");
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Management
|
|
3
|
+
*
|
|
4
|
+
* Control session persistence: in-memory, new file, continue, or open specific.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createAgentSession, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
|
8
|
+
|
|
9
|
+
// In-memory (no persistence)
|
|
10
|
+
const { session: inMemory } = await createAgentSession({
|
|
11
|
+
sessionManager: SessionManager.inMemory(),
|
|
12
|
+
});
|
|
13
|
+
console.log("In-memory session:", inMemory.sessionFile ?? "(none)");
|
|
14
|
+
|
|
15
|
+
// New persistent session
|
|
16
|
+
const { session: newSession } = await createAgentSession({
|
|
17
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
18
|
+
});
|
|
19
|
+
console.log("New session file:", newSession.sessionFile);
|
|
20
|
+
|
|
21
|
+
// Continue most recent session (or create new if none)
|
|
22
|
+
const { session: continued, modelFallbackMessage } = await createAgentSession({
|
|
23
|
+
sessionManager: SessionManager.continueRecent(process.cwd()),
|
|
24
|
+
});
|
|
25
|
+
if (modelFallbackMessage) console.log("Note:", modelFallbackMessage);
|
|
26
|
+
console.log("Continued session:", continued.sessionFile);
|
|
27
|
+
|
|
28
|
+
// List and open specific session
|
|
29
|
+
const sessions = SessionManager.list(process.cwd());
|
|
30
|
+
console.log(`\nFound ${sessions.length} sessions:`);
|
|
31
|
+
for (const info of sessions.slice(0, 3)) {
|
|
32
|
+
console.log(` ${info.id.slice(0, 8)}... - "${info.firstMessage.slice(0, 30)}..."`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (sessions.length > 0) {
|
|
36
|
+
const { session: opened } = await createAgentSession({
|
|
37
|
+
sessionManager: SessionManager.open(sessions[0].path),
|
|
38
|
+
});
|
|
39
|
+
console.log(`\nOpened: ${opened.sessionId}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Custom session directory (no cwd encoding)
|
|
43
|
+
// const customDir = "/path/to/my-sessions";
|
|
44
|
+
// const { session } = await createAgentSession({
|
|
45
|
+
// sessionManager: SessionManager.create(process.cwd(), customDir),
|
|
46
|
+
// });
|
|
47
|
+
// SessionManager.list(process.cwd(), customDir);
|
|
48
|
+
// SessionManager.continueRecent(process.cwd(), customDir);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full Control
|
|
3
|
+
*
|
|
4
|
+
* Replace everything - no discovery, explicit configuration.
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: When providing `tools` with a custom `cwd`, use the tool factory
|
|
7
|
+
* functions (createReadTool, createBashTool, etc.) to ensure tools resolve
|
|
8
|
+
* paths relative to your cwd.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { getModel } from "@oh-my-pi/pi-ai";
|
|
12
|
+
import {
|
|
13
|
+
AuthStorage,
|
|
14
|
+
type CustomTool,
|
|
15
|
+
createAgentSession,
|
|
16
|
+
createBashTool,
|
|
17
|
+
createReadTool,
|
|
18
|
+
type HookFactory,
|
|
19
|
+
ModelRegistry,
|
|
20
|
+
SessionManager,
|
|
21
|
+
SettingsManager,
|
|
22
|
+
} from "@oh-my-pi/pi-coding-agent";
|
|
23
|
+
import { Type } from "@sinclair/typebox";
|
|
24
|
+
|
|
25
|
+
// Custom auth storage location
|
|
26
|
+
const authStorage = new AuthStorage("/tmp/my-agent/auth.json");
|
|
27
|
+
|
|
28
|
+
// Runtime API key override (not persisted)
|
|
29
|
+
if (process.env.MY_ANTHROPIC_KEY) {
|
|
30
|
+
authStorage.setRuntimeApiKey("anthropic", process.env.MY_ANTHROPIC_KEY);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Model registry with no custom models.json
|
|
34
|
+
const modelRegistry = new ModelRegistry(authStorage);
|
|
35
|
+
|
|
36
|
+
// Inline hook
|
|
37
|
+
const auditHook: HookFactory = (api) => {
|
|
38
|
+
api.on("tool_call", async (event) => {
|
|
39
|
+
console.log(`[Audit] ${event.toolName}`);
|
|
40
|
+
return undefined;
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Inline custom tool
|
|
45
|
+
const statusTool: CustomTool = {
|
|
46
|
+
name: "status",
|
|
47
|
+
label: "Status",
|
|
48
|
+
description: "Get system status",
|
|
49
|
+
parameters: Type.Object({}),
|
|
50
|
+
execute: async () => ({
|
|
51
|
+
content: [{ type: "text", text: `Uptime: ${process.uptime()}s, Node: ${process.version}` }],
|
|
52
|
+
details: {},
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const model = getModel("anthropic", "claude-opus-4-5");
|
|
57
|
+
if (!model) throw new Error("Model not found");
|
|
58
|
+
|
|
59
|
+
// In-memory settings with overrides
|
|
60
|
+
const settingsManager = SettingsManager.inMemory({
|
|
61
|
+
compaction: { enabled: false },
|
|
62
|
+
retry: { enabled: true, maxRetries: 2 },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// When using a custom cwd with explicit tools, use the factory functions
|
|
66
|
+
const cwd = process.cwd();
|
|
67
|
+
|
|
68
|
+
const { session } = await createAgentSession({
|
|
69
|
+
cwd,
|
|
70
|
+
agentDir: "/tmp/my-agent",
|
|
71
|
+
model,
|
|
72
|
+
thinkingLevel: "off",
|
|
73
|
+
authStorage,
|
|
74
|
+
modelRegistry,
|
|
75
|
+
systemPrompt: `You are a minimal assistant.
|
|
76
|
+
Available: read, bash, status. Be concise.`,
|
|
77
|
+
// Use factory functions with the same cwd to ensure path resolution works correctly
|
|
78
|
+
tools: [createReadTool(cwd), createBashTool(cwd)],
|
|
79
|
+
customTools: [{ tool: statusTool }],
|
|
80
|
+
hooks: [{ factory: auditHook }],
|
|
81
|
+
skills: [],
|
|
82
|
+
contextFiles: [],
|
|
83
|
+
slashCommands: [],
|
|
84
|
+
sessionManager: SessionManager.inMemory(),
|
|
85
|
+
settingsManager,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
session.subscribe((event) => {
|
|
89
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
90
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await session.prompt("Get status and list files.");
|
|
95
|
+
console.log();
|