@mariozechner/pi-coding-agent 0.34.1 → 0.35.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 +224 -18
- package/README.md +233 -105
- package/dist/cli/args.d.ts +3 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +13 -18
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +39 -50
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +166 -197
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +6 -5
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/extensions/index.d.ts +10 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +21 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +400 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +88 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/{hooks → extensions}/runner.js +52 -141
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +461 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/{hooks → extensions}/types.js +7 -4
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +25 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/{hooks/tool-wrapper.js → extensions/wrapper.js} +39 -24
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/messages.d.ts +7 -7
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +4 -4
- package/dist/core/messages.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +40 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/{slash-commands.js → prompt-templates.js} +31 -31
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/sdk.d.ts +29 -52
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +111 -211
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +17 -17
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +25 -10
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -6
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +4 -11
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +4 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +36 -33
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +7 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +93 -4
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +2 -2
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +4 -4
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +18 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-message.js → custom-message.js} +3 -3
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +2 -2
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +2 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/{hook-editor.d.ts → extension-editor.d.ts} +3 -3
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-editor.js → extension-editor.js} +4 -4
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/{hook-input.d.ts → extension-input.d.ts} +3 -3
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-input.js → extension-input.js} +3 -3
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/{hook-selector.d.ts → extension-selector.d.ts} +3 -3
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-selector.js → extension-selector.js} +3 -3
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +3 -3
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -3
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +9 -9
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +37 -44
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +143 -189
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +10 -33
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -3
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +3 -3
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +33 -57
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +16 -16
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/extensions.md +1053 -0
- package/docs/rpc.md +4 -4
- package/docs/sdk.md +62 -93
- package/docs/session.md +22 -19
- package/docs/skills.md +1 -1
- package/docs/tui.md +1 -1
- package/examples/README.md +9 -15
- package/examples/extensions/README.md +141 -0
- package/examples/{hooks → extensions}/auto-commit-on-exit.ts +3 -3
- package/examples/extensions/chalk-logger.ts +26 -0
- package/examples/{hooks → extensions}/confirm-destructive.ts +3 -3
- package/examples/{hooks → extensions}/custom-compaction.ts +6 -6
- package/examples/{hooks → extensions}/dirty-repo-guard.ts +8 -4
- package/examples/{hooks → extensions}/file-trigger.ts +3 -3
- package/examples/{hooks → extensions}/git-checkpoint.ts +3 -3
- package/examples/{hooks → extensions}/handoff.ts +3 -3
- package/examples/extensions/hello.ts +25 -0
- package/examples/{hooks → extensions}/permission-gate.ts +3 -3
- package/examples/{hooks → extensions}/pirate.ts +5 -5
- package/examples/{hooks → extensions}/plan-mode.ts +6 -6
- package/examples/{hooks → extensions}/protected-paths.ts +3 -3
- package/examples/{hooks → extensions}/qna.ts +3 -3
- package/examples/{custom-tools/question/index.ts → extensions/question.ts} +13 -17
- package/examples/{hooks → extensions}/snake.ts +3 -3
- package/examples/{hooks → extensions}/status-line.ts +3 -3
- package/examples/{custom-tools → extensions}/subagent/README.md +15 -15
- package/examples/{custom-tools → extensions}/subagent/index.ts +22 -43
- package/examples/{custom-tools/todo/index.ts → extensions/todo.ts} +122 -39
- package/examples/{hooks → extensions}/tools.ts +5 -5
- package/examples/extensions/with-deps/index.ts +40 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +16 -0
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/05-tools.ts +7 -41
- package/examples/sdk/06-extensions.ts +81 -0
- package/examples/sdk/08-prompt-templates.ts +42 -0
- package/examples/sdk/12-full-control.ts +10 -29
- package/examples/sdk/README.md +5 -5
- package/package.json +4 -4
- package/dist/core/custom-tools/index.d.ts +0 -7
- package/dist/core/custom-tools/index.d.ts.map +0 -1
- package/dist/core/custom-tools/index.js +0 -6
- package/dist/core/custom-tools/index.js.map +0 -1
- package/dist/core/custom-tools/loader.d.ts +0 -30
- package/dist/core/custom-tools/loader.d.ts.map +0 -1
- package/dist/core/custom-tools/loader.js +0 -276
- package/dist/core/custom-tools/loader.js.map +0 -1
- package/dist/core/custom-tools/types.d.ts +0 -144
- package/dist/core/custom-tools/types.d.ts.map +0 -1
- package/dist/core/custom-tools/types.js +0 -8
- package/dist/core/custom-tools/types.js.map +0 -1
- package/dist/core/custom-tools/wrapper.d.ts +0 -15
- package/dist/core/custom-tools/wrapper.d.ts.map +0 -1
- package/dist/core/custom-tools/wrapper.js +0 -23
- package/dist/core/custom-tools/wrapper.js.map +0 -1
- package/dist/core/hooks/index.d.ts +0 -6
- package/dist/core/hooks/index.d.ts.map +0 -1
- package/dist/core/hooks/index.js +0 -6
- package/dist/core/hooks/index.js.map +0 -1
- package/dist/core/hooks/loader.d.ts +0 -146
- package/dist/core/hooks/loader.d.ts.map +0 -1
- package/dist/core/hooks/loader.js +0 -275
- package/dist/core/hooks/loader.js.map +0 -1
- package/dist/core/hooks/runner.d.ts +0 -173
- package/dist/core/hooks/runner.d.ts.map +0 -1
- package/dist/core/hooks/runner.js.map +0 -1
- package/dist/core/hooks/tool-wrapper.d.ts +0 -17
- package/dist/core/hooks/tool-wrapper.d.ts.map +0 -1
- package/dist/core/hooks/tool-wrapper.js.map +0 -1
- package/dist/core/hooks/types.d.ts +0 -767
- package/dist/core/hooks/types.d.ts.map +0 -1
- package/dist/core/hooks/types.js.map +0 -1
- package/dist/core/slash-commands.d.ts +0 -40
- package/dist/core/slash-commands.d.ts.map +0 -1
- package/dist/core/slash-commands.js.map +0 -1
- package/dist/modes/interactive/components/hook-editor.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-editor.js.map +0 -1
- package/dist/modes/interactive/components/hook-input.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-input.js.map +0 -1
- package/dist/modes/interactive/components/hook-message.d.ts +0 -18
- package/dist/modes/interactive/components/hook-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-message.js.map +0 -1
- package/dist/modes/interactive/components/hook-selector.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-selector.js.map +0 -1
- package/docs/custom-tools.md +0 -514
- package/docs/extension-loading.md +0 -1004
- package/docs/hooks.md +0 -979
- package/docs/session-tree-plan.md +0 -441
- package/examples/custom-tools/README.md +0 -114
- package/examples/custom-tools/hello/index.ts +0 -21
- package/examples/hooks/README.md +0 -60
- package/examples/hooks/todo/index.ts +0 -134
- package/examples/sdk/06-hooks.ts +0 -61
- package/examples/sdk/08-slash-commands.ts +0 -42
- /package/examples/{custom-tools → extensions}/subagent/agents/planner.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents/reviewer.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents/scout.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents/worker.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents.ts +0 -0
- /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/implement-and-review.md +0 -0
- /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/implement.md +0 -0
- /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/scout-and-plan.md +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example extension that uses a 3rd party dependency (chalk).
|
|
3
|
+
* Tests that jiti can resolve npm modules correctly.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
|
|
9
|
+
export default function (pi: ExtensionAPI) {
|
|
10
|
+
// Log with colors using chalk
|
|
11
|
+
console.log(`${chalk.green("✓")} ${chalk.bold("chalk-logger extension loaded")}`);
|
|
12
|
+
|
|
13
|
+
pi.on("agent_start", async () => {
|
|
14
|
+
console.log(`${chalk.blue("[chalk-logger]")} Agent starting`);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
pi.on("tool_call", async (event) => {
|
|
18
|
+
console.log(`${chalk.yellow("[chalk-logger]")} Tool: ${chalk.cyan(event.toolName)}`);
|
|
19
|
+
return undefined;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
pi.on("agent_end", async (event) => {
|
|
23
|
+
const count = event.messages.length;
|
|
24
|
+
console.log(`${chalk.green("[chalk-logger]")} Done with ${chalk.bold(String(count))} messages`);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Confirm Destructive Actions
|
|
2
|
+
* Confirm Destructive Actions Extension
|
|
3
3
|
*
|
|
4
4
|
* Prompts for confirmation before destructive session actions (clear, switch, branch).
|
|
5
5
|
* Demonstrates how to cancel session events using the before_* events.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ExtensionAPI, SessionBeforeSwitchEvent, SessionMessageEntry } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
|
|
10
|
-
export default function (pi:
|
|
10
|
+
export default function (pi: ExtensionAPI) {
|
|
11
11
|
pi.on("session_before_switch", async (event: SessionBeforeSwitchEvent, ctx) => {
|
|
12
12
|
if (!ctx.hasUI) return;
|
|
13
13
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Custom Compaction
|
|
2
|
+
* Custom Compaction Extension
|
|
3
3
|
*
|
|
4
4
|
* Replaces the default compaction behavior with a full summary of the entire context.
|
|
5
|
-
* Instead of keeping the last 20k tokens of conversation turns, this
|
|
5
|
+
* Instead of keeping the last 20k tokens of conversation turns, this extension:
|
|
6
6
|
* 1. Summarizes ALL messages (messagesToSummarize + turnPrefixMessages)
|
|
7
7
|
* 2. Discards all old turns completely, keeping only the summary
|
|
8
8
|
*
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
* which can be cheaper/faster than the main conversation model.
|
|
11
11
|
*
|
|
12
12
|
* Usage:
|
|
13
|
-
* pi --
|
|
13
|
+
* pi --extension examples/extensions/custom-compaction.ts
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { complete, getModel } from "@mariozechner/pi-ai";
|
|
17
|
-
import type {
|
|
17
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
18
18
|
import { convertToLlm, serializeConversation } from "@mariozechner/pi-coding-agent";
|
|
19
19
|
|
|
20
|
-
export default function (pi:
|
|
20
|
+
export default function (pi: ExtensionAPI) {
|
|
21
21
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
22
|
-
ctx.ui.notify("Custom compaction
|
|
22
|
+
ctx.ui.notify("Custom compaction extension triggered", "info");
|
|
23
23
|
|
|
24
24
|
const { preparation, branchEntries: _, signal } = event;
|
|
25
25
|
const { messagesToSummarize, turnPrefixMessages, tokensBefore, firstKeptEntryId, previousSummary } = preparation;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dirty Repo Guard
|
|
2
|
+
* Dirty Repo Guard Extension
|
|
3
3
|
*
|
|
4
4
|
* Prevents session changes when there are uncommitted git changes.
|
|
5
5
|
* Useful to ensure work is committed before switching context.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
|
|
10
|
-
async function checkDirtyRepo(
|
|
10
|
+
async function checkDirtyRepo(
|
|
11
|
+
pi: ExtensionAPI,
|
|
12
|
+
ctx: ExtensionContext,
|
|
13
|
+
action: string,
|
|
14
|
+
): Promise<{ cancel: boolean } | undefined> {
|
|
11
15
|
// Check for uncommitted changes
|
|
12
16
|
const { stdout, code } = await pi.exec("git", ["status", "--porcelain"]);
|
|
13
17
|
|
|
@@ -40,7 +44,7 @@ async function checkDirtyRepo(pi: HookAPI, ctx: HookContext, action: string): Pr
|
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
export default function (pi:
|
|
47
|
+
export default function (pi: ExtensionAPI) {
|
|
44
48
|
pi.on("session_before_switch", async (event, ctx) => {
|
|
45
49
|
const action = event.reason === "new" ? "new session" : "switch session";
|
|
46
50
|
return checkDirtyRepo(pi, ctx, action);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* File Trigger
|
|
2
|
+
* File Trigger Extension
|
|
3
3
|
*
|
|
4
4
|
* Watches a trigger file and injects its contents into the conversation.
|
|
5
5
|
* Useful for external systems to send messages to the agent.
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
|
-
import type {
|
|
12
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
13
13
|
|
|
14
|
-
export default function (pi:
|
|
14
|
+
export default function (pi: ExtensionAPI) {
|
|
15
15
|
pi.on("session_start", async (_event, ctx) => {
|
|
16
16
|
const triggerFile = "/tmp/agent-trigger.txt";
|
|
17
17
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Git Checkpoint
|
|
2
|
+
* Git Checkpoint Extension
|
|
3
3
|
*
|
|
4
4
|
* Creates git stash checkpoints at each turn so /branch can restore code state.
|
|
5
5
|
* When branching, offers to restore code to that point in history.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
|
|
10
|
-
export default function (pi:
|
|
10
|
+
export default function (pi: ExtensionAPI) {
|
|
11
11
|
const checkpoints = new Map<string, string>();
|
|
12
12
|
let currentEntryId: string | undefined;
|
|
13
13
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Handoff
|
|
2
|
+
* Handoff extension - transfer context to a new focused session
|
|
3
3
|
*
|
|
4
4
|
* Instead of compacting (which is lossy), handoff extracts what matters
|
|
5
5
|
* for your next task and creates a new session with a generated prompt.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { complete, type Message } from "@mariozechner/pi-ai";
|
|
16
|
-
import type {
|
|
16
|
+
import type { ExtensionAPI, SessionEntry } from "@mariozechner/pi-coding-agent";
|
|
17
17
|
import { BorderedLoader, convertToLlm, serializeConversation } from "@mariozechner/pi-coding-agent";
|
|
18
18
|
|
|
19
19
|
const SYSTEM_PROMPT = `You are a context transfer assistant. Given a conversation history and the user's goal for a new thread, generate a focused prompt that:
|
|
@@ -38,7 +38,7 @@ Files involved:
|
|
|
38
38
|
## Task
|
|
39
39
|
[Clear description of what to do next based on user's goal]`;
|
|
40
40
|
|
|
41
|
-
export default function (pi:
|
|
41
|
+
export default function (pi: ExtensionAPI) {
|
|
42
42
|
pi.registerCommand("handoff", {
|
|
43
43
|
description: "Transfer context to a new focused session",
|
|
44
44
|
handler: async (args, ctx) => {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hello Tool - Minimal custom tool example
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
6
|
+
import { Type } from "@sinclair/typebox";
|
|
7
|
+
|
|
8
|
+
export default function (pi: ExtensionAPI) {
|
|
9
|
+
pi.registerTool({
|
|
10
|
+
name: "hello",
|
|
11
|
+
label: "Hello",
|
|
12
|
+
description: "A simple greeting tool",
|
|
13
|
+
parameters: Type.Object({
|
|
14
|
+
name: Type.String({ description: "Name to greet" }),
|
|
15
|
+
}),
|
|
16
|
+
|
|
17
|
+
async execute(_toolCallId, params, _onUpdate, _ctx, _signal) {
|
|
18
|
+
const { name } = params as { name: string };
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: `Hello, ${name}!` }],
|
|
21
|
+
details: { greeted: name },
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Permission Gate
|
|
2
|
+
* Permission Gate Extension
|
|
3
3
|
*
|
|
4
4
|
* Prompts for confirmation before running potentially dangerous bash commands.
|
|
5
5
|
* Patterns checked: rm -rf, sudo, chmod/chown 777
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
|
|
10
|
-
export default function (pi:
|
|
10
|
+
export default function (pi: ExtensionAPI) {
|
|
11
11
|
const dangerousPatterns = [/\brm\s+(-rf?|--recursive)/i, /\bsudo\b/i, /\b(chmod|chown)\b.*777/i];
|
|
12
12
|
|
|
13
13
|
pi.on("tool_call", async (event, ctx) => {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pirate
|
|
2
|
+
* Pirate Extension
|
|
3
3
|
*
|
|
4
4
|
* Demonstrates using systemPromptAppend in before_agent_start to dynamically
|
|
5
|
-
* modify the system prompt based on
|
|
5
|
+
* modify the system prompt based on extension state.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
* 1. Copy this file to ~/.pi/agent/
|
|
8
|
+
* 1. Copy this file to ~/.pi/agent/extensions/ or your project's .pi/extensions/
|
|
9
9
|
* 2. Use /pirate to toggle pirate mode
|
|
10
10
|
* 3. When enabled, the agent will respond like a pirate
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import type {
|
|
13
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
14
14
|
|
|
15
|
-
export default function
|
|
15
|
+
export default function pirateExtension(pi: ExtensionAPI) {
|
|
16
16
|
let pirateMode = false;
|
|
17
17
|
|
|
18
18
|
// Register /pirate command to toggle pirate mode
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Plan Mode
|
|
2
|
+
* Plan Mode Extension
|
|
3
3
|
*
|
|
4
4
|
* Provides a Claude Code-style "plan mode" for safe code exploration.
|
|
5
5
|
* When enabled, the agent can only use read-only tools and cannot modify files.
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
* - Uses ID-based tracking: agent outputs [DONE:id] to mark steps complete
|
|
15
15
|
*
|
|
16
16
|
* Usage:
|
|
17
|
-
* 1. Copy this file to ~/.pi/agent/
|
|
17
|
+
* 1. Copy this file to ~/.pi/agent/extensions/ or your project's .pi/extensions/
|
|
18
18
|
* 2. Use /plan to toggle plan mode on/off
|
|
19
19
|
* 3. Or start in plan mode with --plan flag
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type {
|
|
22
|
+
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
23
23
|
import { Key } from "@mariozechner/pi-tui";
|
|
24
24
|
|
|
25
25
|
// Read-only tools for plan mode
|
|
@@ -207,7 +207,7 @@ function extractTodoItems(message: string): TodoItem[] {
|
|
|
207
207
|
return items;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
export default function
|
|
210
|
+
export default function planModeExtension(pi: ExtensionAPI) {
|
|
211
211
|
let planModeEnabled = false;
|
|
212
212
|
let toolsCalledThisTurn = false;
|
|
213
213
|
let executionMode = false;
|
|
@@ -221,7 +221,7 @@ export default function planModeHook(pi: HookAPI) {
|
|
|
221
221
|
});
|
|
222
222
|
|
|
223
223
|
// Helper to update status displays
|
|
224
|
-
function updateStatus(ctx:
|
|
224
|
+
function updateStatus(ctx: ExtensionContext) {
|
|
225
225
|
if (executionMode && todoItems.length > 0) {
|
|
226
226
|
const completed = todoItems.filter((t) => t.completed).length;
|
|
227
227
|
ctx.ui.setStatus("plan-mode", ctx.ui.theme.fg("accent", `📋 ${completed}/${todoItems.length}`));
|
|
@@ -249,7 +249,7 @@ export default function planModeHook(pi: HookAPI) {
|
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
function togglePlanMode(ctx:
|
|
252
|
+
function togglePlanMode(ctx: ExtensionContext) {
|
|
253
253
|
planModeEnabled = !planModeEnabled;
|
|
254
254
|
executionMode = false;
|
|
255
255
|
todoItems = [];
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Protected Paths
|
|
2
|
+
* Protected Paths Extension
|
|
3
3
|
*
|
|
4
4
|
* Blocks write and edit operations to protected paths.
|
|
5
5
|
* Useful for preventing accidental modifications to sensitive files.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
|
|
10
|
-
export default function (pi:
|
|
10
|
+
export default function (pi: ExtensionAPI) {
|
|
11
11
|
const protectedPaths = [".env", ".git/", "node_modules/"];
|
|
12
12
|
|
|
13
13
|
pi.on("tool_call", async (event, ctx) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Q&A extraction
|
|
2
|
+
* Q&A extraction extension - extracts questions from assistant responses
|
|
3
3
|
*
|
|
4
4
|
* Demonstrates the "prompt generator" pattern:
|
|
5
5
|
* 1. /qna command gets the last assistant message
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { complete, type UserMessage } from "@mariozechner/pi-ai";
|
|
11
|
-
import type {
|
|
11
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
12
12
|
import { BorderedLoader } from "@mariozechner/pi-coding-agent";
|
|
13
13
|
|
|
14
14
|
const SYSTEM_PROMPT = `You are a question extractor. Given text from a conversation, extract any questions that need answering and format them for the user to fill in.
|
|
@@ -27,7 +27,7 @@ A:
|
|
|
27
27
|
|
|
28
28
|
Keep questions in the order they appeared. Be concise.`;
|
|
29
29
|
|
|
30
|
-
export default function (pi:
|
|
30
|
+
export default function (pi: ExtensionAPI) {
|
|
31
31
|
pi.registerCommand("qna", {
|
|
32
32
|
description: "Extract questions from last assistant message into editor",
|
|
33
33
|
handler: async (_args, ctx) => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Question Tool - Let the LLM ask the user a question with options
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
6
6
|
import { Text } from "@mariozechner/pi-tui";
|
|
7
7
|
import { Type } from "@sinclair/typebox";
|
|
8
8
|
|
|
@@ -17,40 +17,40 @@ const QuestionParams = Type.Object({
|
|
|
17
17
|
options: Type.Array(Type.String(), { description: "Options for the user to choose from" }),
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
export default function (pi: ExtensionAPI) {
|
|
21
|
+
pi.registerTool({
|
|
22
22
|
name: "question",
|
|
23
23
|
label: "Question",
|
|
24
24
|
description: "Ask the user a question and let them pick from options. Use when you need user input to proceed.",
|
|
25
25
|
parameters: QuestionParams,
|
|
26
26
|
|
|
27
|
-
async execute(_toolCallId, params, _onUpdate,
|
|
28
|
-
if (!
|
|
27
|
+
async execute(_toolCallId, params, _onUpdate, ctx, _signal) {
|
|
28
|
+
if (!ctx.hasUI) {
|
|
29
29
|
return {
|
|
30
30
|
content: [{ type: "text", text: "Error: UI not available (running in non-interactive mode)" }],
|
|
31
|
-
details: { question: params.question, options: params.options, answer: null },
|
|
31
|
+
details: { question: params.question, options: params.options, answer: null } as QuestionDetails,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (params.options.length === 0) {
|
|
36
36
|
return {
|
|
37
37
|
content: [{ type: "text", text: "Error: No options provided" }],
|
|
38
|
-
details: { question: params.question, options: [], answer: null },
|
|
38
|
+
details: { question: params.question, options: [], answer: null } as QuestionDetails,
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const answer = await
|
|
42
|
+
const answer = await ctx.ui.select(params.question, params.options);
|
|
43
43
|
|
|
44
44
|
if (answer === undefined) {
|
|
45
45
|
return {
|
|
46
46
|
content: [{ type: "text", text: "User cancelled the selection" }],
|
|
47
|
-
details: { question: params.question, options: params.options, answer: null },
|
|
47
|
+
details: { question: params.question, options: params.options, answer: null } as QuestionDetails,
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
return {
|
|
52
52
|
content: [{ type: "text", text: `User selected: ${answer}` }],
|
|
53
|
-
details: { question: params.question, options: params.options, answer },
|
|
53
|
+
details: { question: params.question, options: params.options, answer } as QuestionDetails,
|
|
54
54
|
};
|
|
55
55
|
},
|
|
56
56
|
|
|
@@ -63,7 +63,7 @@ const factory: CustomToolFactory = (pi) => {
|
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
renderResult(result, _options, theme) {
|
|
66
|
-
const
|
|
66
|
+
const details = result.details as QuestionDetails | undefined;
|
|
67
67
|
if (!details) {
|
|
68
68
|
const text = result.content[0];
|
|
69
69
|
return new Text(text?.type === "text" ? text.text : "", 0, 0);
|
|
@@ -75,9 +75,5 @@ const factory: CustomToolFactory = (pi) => {
|
|
|
75
75
|
|
|
76
76
|
return new Text(theme.fg("success", "✓ ") + theme.fg("accent", details.answer), 0, 0);
|
|
77
77
|
},
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
return tool;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export default factory;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Snake game
|
|
2
|
+
* Snake game extension - play snake with /snake command
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
6
6
|
import { matchesKey, visibleWidth } from "@mariozechner/pi-tui";
|
|
7
7
|
|
|
8
8
|
const GAME_WIDTH = 40;
|
|
@@ -306,7 +306,7 @@ class SnakeComponent {
|
|
|
306
306
|
|
|
307
307
|
const SNAKE_SAVE_TYPE = "snake-save";
|
|
308
308
|
|
|
309
|
-
export default function (pi:
|
|
309
|
+
export default function (pi: ExtensionAPI) {
|
|
310
310
|
pi.registerCommand("snake", {
|
|
311
311
|
description: "Play Snake!",
|
|
312
312
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Status Line
|
|
2
|
+
* Status Line Extension
|
|
3
3
|
*
|
|
4
4
|
* Demonstrates ctx.ui.setStatus() for displaying persistent status text in the footer.
|
|
5
5
|
* Shows turn progress with themed colors.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
|
|
10
|
-
export default function (pi:
|
|
10
|
+
export default function (pi: ExtensionAPI) {
|
|
11
11
|
let turnCount = 0;
|
|
12
12
|
|
|
13
13
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -16,14 +16,14 @@ Delegate tasks to specialized subagents with isolated context windows.
|
|
|
16
16
|
```
|
|
17
17
|
subagent/
|
|
18
18
|
├── README.md # This file
|
|
19
|
-
├── index.ts # The
|
|
19
|
+
├── index.ts # The extension (entry point)
|
|
20
20
|
├── agents.ts # Agent discovery logic
|
|
21
21
|
├── agents/ # Sample agent definitions
|
|
22
22
|
│ ├── scout.md # Fast recon, returns compressed context
|
|
23
23
|
│ ├── planner.md # Creates implementation plans
|
|
24
24
|
│ ├── reviewer.md # Code review
|
|
25
25
|
│ └── worker.md # General-purpose (full capabilities)
|
|
26
|
-
└──
|
|
26
|
+
└── prompts/ # Workflow presets (prompt templates)
|
|
27
27
|
├── implement.md # scout -> planner -> worker
|
|
28
28
|
├── scout-and-plan.md # scout -> planner (no implementation)
|
|
29
29
|
└── implement-and-review.md # worker -> reviewer -> worker
|
|
@@ -34,21 +34,21 @@ subagent/
|
|
|
34
34
|
From the repository root, symlink the files:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
# Symlink the
|
|
38
|
-
mkdir -p ~/.pi/agent/
|
|
39
|
-
ln -sf "$(pwd)/packages/coding-agent/examples/
|
|
40
|
-
ln -sf "$(pwd)/packages/coding-agent/examples/
|
|
37
|
+
# Symlink the extension (must be in a subdirectory with index.ts)
|
|
38
|
+
mkdir -p ~/.pi/agent/extensions/subagent
|
|
39
|
+
ln -sf "$(pwd)/packages/coding-agent/examples/extensions/subagent/index.ts" ~/.pi/agent/extensions/subagent/index.ts
|
|
40
|
+
ln -sf "$(pwd)/packages/coding-agent/examples/extensions/subagent/agents.ts" ~/.pi/agent/extensions/subagent/agents.ts
|
|
41
41
|
|
|
42
42
|
# Symlink agents
|
|
43
43
|
mkdir -p ~/.pi/agent/agents
|
|
44
|
-
for f in packages/coding-agent/examples/
|
|
44
|
+
for f in packages/coding-agent/examples/extensions/subagent/agents/*.md; do
|
|
45
45
|
ln -sf "$(pwd)/$f" ~/.pi/agent/agents/$(basename "$f")
|
|
46
46
|
done
|
|
47
47
|
|
|
48
|
-
# Symlink workflow
|
|
49
|
-
mkdir -p ~/.pi/agent/
|
|
50
|
-
for f in packages/coding-agent/examples/
|
|
51
|
-
ln -sf "$(pwd)/$f" ~/.pi/agent/
|
|
48
|
+
# Symlink workflow prompts
|
|
49
|
+
mkdir -p ~/.pi/agent/prompts
|
|
50
|
+
for f in packages/coding-agent/examples/extensions/subagent/prompts/*.md; do
|
|
51
|
+
ln -sf "$(pwd)/$f" ~/.pi/agent/prompts/$(basename "$f")
|
|
52
52
|
done
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -81,7 +81,7 @@ Run 2 scouts in parallel: one to find models, one to find providers
|
|
|
81
81
|
Use a chain: first have scout find the read tool, then have planner suggest improvements
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
### Workflow
|
|
84
|
+
### Workflow prompts
|
|
85
85
|
```
|
|
86
86
|
/implement add Redis caching to the session store
|
|
87
87
|
/scout-and-plan refactor auth to support OAuth
|
|
@@ -150,10 +150,10 @@ Project agents override user agents with the same name when `agentScope: "both"`
|
|
|
150
150
|
| `reviewer` | Code review | Sonnet | read, grep, find, ls, bash |
|
|
151
151
|
| `worker` | General-purpose | Sonnet | (all default) |
|
|
152
152
|
|
|
153
|
-
## Workflow
|
|
153
|
+
## Workflow Prompts
|
|
154
154
|
|
|
155
|
-
|
|
|
156
|
-
|
|
155
|
+
| Prompt | Flow |
|
|
156
|
+
|--------|------|
|
|
157
157
|
| `/implement <query>` | scout → planner → worker |
|
|
158
158
|
| `/scout-and-plan <query>` | scout → planner |
|
|
159
159
|
| `/implement-and-review <query>` | worker → reviewer → worker |
|