@mariozechner/pi-coding-agent 0.55.3 → 0.55.4

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +0 -8
  3. package/dist/core/agent-session.d.ts +9 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +141 -44
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  8. package/dist/core/export-html/tool-renderer.js +6 -0
  9. package/dist/core/export-html/tool-renderer.js.map +1 -1
  10. package/dist/core/extensions/loader.d.ts.map +1 -1
  11. package/dist/core/extensions/loader.js +3 -0
  12. package/dist/core/extensions/loader.js.map +1 -1
  13. package/dist/core/extensions/runner.d.ts.map +1 -1
  14. package/dist/core/extensions/runner.js +1 -0
  15. package/dist/core/extensions/runner.js.map +1 -1
  16. package/dist/core/extensions/types.d.ts +8 -2
  17. package/dist/core/extensions/types.d.ts.map +1 -1
  18. package/dist/core/extensions/types.js.map +1 -1
  19. package/dist/core/system-prompt.d.ts +4 -0
  20. package/dist/core/system-prompt.d.ts.map +1 -1
  21. package/dist/core/system-prompt.js +34 -12
  22. package/dist/core/system-prompt.js.map +1 -1
  23. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  24. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  25. package/dist/modes/interactive/components/tool-execution.js +28 -3
  26. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  27. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  28. package/dist/modes/interactive/interactive-mode.js +0 -1
  29. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  30. package/docs/extensions.md +20 -1
  31. package/examples/extensions/README.md +1 -0
  32. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  33. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  34. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  35. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  36. package/examples/extensions/dynamic-tools.ts +74 -0
  37. package/examples/extensions/with-deps/package-lock.json +2 -2
  38. package/examples/extensions/with-deps/package.json +1 -1
  39. package/package.json +4 -4
@@ -880,6 +880,14 @@ Subscribe to events. See [Events](#events) for event types and return values.
880
880
 
881
881
  Register a custom tool callable by the LLM. See [Custom Tools](#custom-tools) for full details.
882
882
 
883
+ `pi.registerTool()` works both during extension load and after startup. You can call it inside `session_start`, command handlers, or other event handlers. New tools are refreshed immediately in the same session, so they appear in `pi.getAllTools()` and are callable by the LLM without `/reload`.
884
+
885
+ Use `pi.setActiveTools()` to enable or disable tools (including dynamically added tools) at runtime.
886
+
887
+ Use `promptSnippet` to customize that tool's one-line entry in `Available tools`, and `promptGuidelines` to append tool-specific bullets to the default `Guidelines` section when the tool is active.
888
+
889
+ See [dynamic-tools.ts](../examples/extensions/dynamic-tools.ts) for a full example.
890
+
883
891
  ```typescript
884
892
  import { Type } from "@sinclair/typebox";
885
893
  import { StringEnum } from "@mariozechner/pi-ai";
@@ -888,6 +896,8 @@ pi.registerTool({
888
896
  name: "my_tool",
889
897
  label: "My Tool",
890
898
  description: "What this tool does",
899
+ promptSnippet: "Summarize or transform text according to action",
900
+ promptGuidelines: ["Use this tool when the user asks to summarize previously generated text."],
891
901
  parameters: Type.Object({
892
902
  action: StringEnum(["list", "add"] as const),
893
903
  text: Type.Optional(Type.String()),
@@ -1116,7 +1126,7 @@ const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
1116
1126
 
1117
1127
  ### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
1118
1128
 
1119
- Manage active tools.
1129
+ Manage active tools. This works for both built-in tools and dynamically registered tools.
1120
1130
 
1121
1131
  ```typescript
1122
1132
  const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
@@ -1276,6 +1286,10 @@ export default function (pi: ExtensionAPI) {
1276
1286
 
1277
1287
  Register tools the LLM can call via `pi.registerTool()`. Tools appear in the system prompt and can have custom rendering.
1278
1288
 
1289
+ Use `promptSnippet` for a short one-line entry in the `Available tools` section in the default system prompt. If omitted, pi falls back to `description`.
1290
+
1291
+ Use `promptGuidelines` to add tool-specific bullets to the default system prompt `Guidelines` section. These bullets are included only while the tool is active (for example, after `pi.setActiveTools([...])`).
1292
+
1279
1293
  Note: Some models are idiots and include the @ prefix in tool path arguments. Built-in tools strip a leading @ before resolving paths. If your custom tool accepts a path, normalize a leading @ as well.
1280
1294
 
1281
1295
  ### Tool Definition
@@ -1289,6 +1303,10 @@ pi.registerTool({
1289
1303
  name: "my_tool",
1290
1304
  label: "My Tool",
1291
1305
  description: "What this tool does (shown to LLM)",
1306
+ promptSnippet: "List or add items in the project todo list",
1307
+ promptGuidelines: [
1308
+ "Use this tool for todo planning instead of direct file edits when the user asks for a task list."
1309
+ ],
1292
1310
  parameters: Type.Object({
1293
1311
  action: StringEnum(["list", "add"] as const), // Use StringEnum for Google compatibility
1294
1312
  text: Type.Optional(Type.String()),
@@ -1886,6 +1904,7 @@ All examples in [examples/extensions/](../examples/extensions/).
1886
1904
  | `question.ts` | Tool with user interaction | `registerTool`, `ui.select` |
1887
1905
  | `questionnaire.ts` | Multi-step wizard tool | `registerTool`, `ui.custom` |
1888
1906
  | `todo.ts` | Stateful tool with persistence | `registerTool`, `appendEntry`, `renderResult`, session events |
1907
+ | `dynamic-tools.ts` | Register tools after startup and during commands | `registerTool`, `session_start`, `registerCommand` |
1889
1908
  | `truncated-tool.ts` | Output truncation example | `registerTool`, `truncateHead` |
1890
1909
  | `tool-override.ts` | Override built-in read tool | `registerTool` (same name as built-in) |
1891
1910
  | **Commands** |||
@@ -33,6 +33,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
33
33
  | `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions with custom UI |
34
34
  | `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
35
35
  | `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
36
+ | `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
36
37
  | `built-in-tool-renderer.ts` | Custom compact rendering for built-in tools (read, bash, edit, write) while keeping original behavior |
37
38
  | `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
38
39
  | `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "1.6.3",
9
+ "version": "1.6.4",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "1.6.3",
4
+ "version": "1.6.4",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "1.6.3",
4
+ "version": "1.6.4",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-qwen-cli",
3
3
  "private": true,
4
- "version": "1.5.3",
4
+ "version": "1.5.4",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Dynamic Tools Extension
3
+ *
4
+ * Demonstrates registering tools after session initialization.
5
+ *
6
+ * - Registers one tool during session_start
7
+ * - Registers additional tools at runtime via /add-echo-tool <name>
8
+ */
9
+
10
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
11
+ import { Type } from "@sinclair/typebox";
12
+
13
+ const ECHO_PARAMS = Type.Object({
14
+ message: Type.String({ description: "Message to echo" }),
15
+ });
16
+
17
+ function normalizeToolName(input: string): string | undefined {
18
+ const trimmed = input.trim().toLowerCase();
19
+ if (!trimmed) return undefined;
20
+ if (!/^[a-z0-9_]+$/.test(trimmed)) return undefined;
21
+ return trimmed;
22
+ }
23
+
24
+ export default function dynamicToolsExtension(pi: ExtensionAPI) {
25
+ const registeredToolNames = new Set<string>();
26
+
27
+ const registerEchoTool = (name: string, label: string, prefix: string): boolean => {
28
+ if (registeredToolNames.has(name)) {
29
+ return false;
30
+ }
31
+
32
+ registeredToolNames.add(name);
33
+ pi.registerTool({
34
+ name,
35
+ label,
36
+ description: `Echo a message with prefix: ${prefix}`,
37
+ promptSnippet: `Echo back user-provided text with ${prefix.trim()} prefix`,
38
+ promptGuidelines: ["Use this tool when the user asks for exact echo output."],
39
+ parameters: ECHO_PARAMS,
40
+ async execute(_toolCallId, params) {
41
+ return {
42
+ content: [{ type: "text", text: `${prefix}${params.message}` }],
43
+ details: { tool: name, prefix },
44
+ };
45
+ },
46
+ });
47
+
48
+ return true;
49
+ };
50
+
51
+ pi.on("session_start", (_event, ctx) => {
52
+ registerEchoTool("echo_session", "Echo Session", "[session] ");
53
+ ctx.ui.notify("Registered dynamic tool: echo_session", "info");
54
+ });
55
+
56
+ pi.registerCommand("add-echo-tool", {
57
+ description: "Register a new echo tool dynamically: /add-echo-tool <tool_name>",
58
+ handler: async (args, ctx) => {
59
+ const toolName = normalizeToolName(args);
60
+ if (!toolName) {
61
+ ctx.ui.notify("Usage: /add-echo-tool <tool_name> (lowercase, numbers, underscores)", "warning");
62
+ return;
63
+ }
64
+
65
+ const created = registerEchoTool(toolName, `Echo ${toolName}`, `[${toolName}] `);
66
+ if (!created) {
67
+ ctx.ui.notify(`Tool already registered: ${toolName}`, "warning");
68
+ return;
69
+ }
70
+
71
+ ctx.ui.notify(`Registered dynamic tool: ${toolName}`, "info");
72
+ },
73
+ });
74
+ }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "1.19.3",
3
+ "version": "1.19.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "1.19.3",
9
+ "version": "1.19.4",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "1.19.3",
4
+ "version": "1.19.4",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mariozechner/pi-coding-agent",
3
- "version": "0.55.3",
3
+ "version": "0.55.4",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -40,9 +40,9 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@mariozechner/jiti": "^2.6.2",
43
- "@mariozechner/pi-agent-core": "^0.55.3",
44
- "@mariozechner/pi-ai": "^0.55.3",
45
- "@mariozechner/pi-tui": "^0.55.3",
43
+ "@mariozechner/pi-agent-core": "^0.55.4",
44
+ "@mariozechner/pi-ai": "^0.55.4",
45
+ "@mariozechner/pi-tui": "^0.55.4",
46
46
  "@silvia-odwyer/photon-node": "^0.3.4",
47
47
  "chalk": "^5.5.0",
48
48
  "cli-highlight": "^2.1.11",