@vandeepunk/pi-coding-agent 0.0.4 → 0.0.6

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 (51) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +8 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +6 -6
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +3 -6
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +2 -1
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/export-html/index.d.ts.map +1 -1
  11. package/dist/core/export-html/index.js +1 -1
  12. package/dist/core/export-html/index.js.map +1 -1
  13. package/dist/core/export-html/template.css +59 -0
  14. package/dist/core/export-html/template.js +21 -1
  15. package/dist/core/extensions/runner.d.ts +2 -0
  16. package/dist/core/extensions/runner.d.ts.map +1 -1
  17. package/dist/core/extensions/runner.js +5 -0
  18. package/dist/core/extensions/runner.js.map +1 -1
  19. package/dist/core/extensions/types.d.ts +7 -2
  20. package/dist/core/extensions/types.d.ts.map +1 -1
  21. package/dist/core/extensions/types.js.map +1 -1
  22. package/dist/core/package-manager.d.ts.map +1 -1
  23. package/dist/core/package-manager.js +1 -2
  24. package/dist/core/package-manager.js.map +1 -1
  25. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  26. package/dist/modes/interactive/interactive-mode.js +14 -5
  27. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  28. package/dist/modes/print-mode.d.ts.map +1 -1
  29. package/dist/modes/print-mode.js +3 -0
  30. package/dist/modes/print-mode.js.map +1 -1
  31. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  32. package/dist/modes/rpc/rpc-mode.js +7 -0
  33. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  34. package/dist/utils/tools-manager.d.ts.map +1 -1
  35. package/dist/utils/tools-manager.js +11 -5
  36. package/dist/utils/tools-manager.js.map +1 -1
  37. package/docs/custom-provider.md +9 -0
  38. package/docs/extensions.md +61 -1
  39. package/docs/providers.md +24 -19
  40. package/docs/rpc.md +7 -1
  41. package/examples/extensions/README.md +1 -0
  42. package/examples/extensions/custom-compaction.ts +2 -2
  43. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  44. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  45. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  46. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  47. package/examples/extensions/reload-runtime.ts +37 -0
  48. package/examples/extensions/subagent/index.ts +2 -1
  49. package/examples/extensions/with-deps/package-lock.json +2 -2
  50. package/examples/extensions/with-deps/package.json +1 -1
  51. package/package.json +4 -4
@@ -623,7 +623,7 @@ UI methods for user interaction. See [Custom UI](#custom-ui) for full details.
623
623
 
624
624
  ### ctx.hasUI
625
625
 
626
- `false` in print mode (`-p`), JSON mode, and RPC mode. Always check before using `ctx.ui`.
626
+ `false` in print mode (`-p`) and JSON mode. `true` in interactive and RPC mode. In RPC mode, dialog methods (`select`, `confirm`, `input`, `editor`) work via the extension UI sub-protocol, and fire-and-forget methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) emit requests to the client. Some TUI-specific methods are no-ops or return defaults (see [rpc.md](rpc.md#extension-ui-protocol)).
627
627
 
628
628
  ### ctx.cwd
629
629
 
@@ -771,6 +771,62 @@ Options:
771
771
  - `replaceInstructions`: If true, `customInstructions` replaces the default prompt instead of being appended
772
772
  - `label`: Label to attach to the branch summary entry (or target entry if not summarizing)
773
773
 
774
+ ### ctx.reload()
775
+
776
+ Run the same reload flow as `/reload`.
777
+
778
+ ```typescript
779
+ pi.registerCommand("reload-runtime", {
780
+ description: "Reload extensions, skills, prompts, and themes",
781
+ handler: async (_args, ctx) => {
782
+ await ctx.reload();
783
+ return;
784
+ },
785
+ });
786
+ ```
787
+
788
+ Important behavior:
789
+ - `await ctx.reload()` emits `session_shutdown` for the current extension runtime
790
+ - It then reloads resources and emits `session_start` (and `resources_discover` with reason `"reload"`) for the new runtime
791
+ - The currently running command handler still continues in the old call frame
792
+ - Code after `await ctx.reload()` still runs from the pre-reload version
793
+ - Code after `await ctx.reload()` must not assume old in-memory extension state is still valid
794
+ - After the handler returns, future commands/events/tool calls use the new extension version
795
+
796
+ For predictable behavior, treat reload as terminal for that handler (`await ctx.reload(); return;`).
797
+
798
+ Tools run with `ExtensionContext`, so they cannot call `ctx.reload()` directly. Use a command as the reload entrypoint, then expose a tool that queues that command as a follow-up user message.
799
+
800
+ Example tool the LLM can call to trigger reload:
801
+
802
+ ```typescript
803
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
804
+ import { Type } from "@sinclair/typebox";
805
+
806
+ export default function (pi: ExtensionAPI) {
807
+ pi.registerCommand("reload-runtime", {
808
+ description: "Reload extensions, skills, prompts, and themes",
809
+ handler: async (_args, ctx) => {
810
+ await ctx.reload();
811
+ return;
812
+ },
813
+ });
814
+
815
+ pi.registerTool({
816
+ name: "reload_runtime",
817
+ label: "Reload Runtime",
818
+ description: "Reload extensions, skills, prompts, and themes",
819
+ parameters: Type.Object({}),
820
+ async execute() {
821
+ pi.sendUserMessage("/reload-runtime", { deliverAs: "followUp" });
822
+ return {
823
+ content: [{ type: "text", text: "Queued /reload-runtime as a follow-up command." }],
824
+ };
825
+ },
826
+ });
827
+ }
828
+ ```
829
+
774
830
  ## ExtensionAPI Methods
775
831
 
776
832
  ### pi.on(event, handler)
@@ -1556,6 +1612,9 @@ ctx.ui.setTitle("pi - my-project");
1556
1612
  ctx.ui.setEditorText("Prefill text");
1557
1613
  const current = ctx.ui.getEditorText();
1558
1614
 
1615
+ // Paste into editor (triggers paste handling, including collapse for large content)
1616
+ ctx.ui.pasteToEditor("pasted content");
1617
+
1559
1618
  // Tool output expansion
1560
1619
  const wasExpanded = ctx.ui.getToolsExpanded();
1561
1620
  ctx.ui.setToolsExpanded(true);
@@ -1775,6 +1834,7 @@ All examples in [examples/extensions/](../examples/extensions/).
1775
1834
  | `handoff.ts` | Cross-provider model handoff | `registerCommand`, `ui.editor`, `ui.custom` |
1776
1835
  | `qna.ts` | Q&A with custom UI | `registerCommand`, `ui.custom`, `setEditorText` |
1777
1836
  | `send-user-message.ts` | Inject user messages | `registerCommand`, `sendUserMessage` |
1837
+ | `reload-runtime.ts` | Reload command and LLM tool handoff | `registerCommand`, `ctx.reload()`, `sendUserMessage` |
1778
1838
  | `shutdown-command.ts` | Graceful shutdown command | `registerCommand`, `shutdown()` |
1779
1839
  | **Events & Gates** |||
1780
1840
  | `permission-gate.ts` | Block dangerous commands | `on("tool_call")`, `ui.confirm` |
package/docs/providers.md CHANGED
@@ -42,6 +42,8 @@ Use `/logout` to clear credentials. Tokens are stored in `~/.pi/agent/auth.json`
42
42
 
43
43
  ## API Keys
44
44
 
45
+ ### Environment Variables or Auth File
46
+
45
47
  Set via environment variable:
46
48
 
47
49
  ```bash
@@ -49,25 +51,28 @@ export ANTHROPIC_API_KEY=sk-ant-...
49
51
  pi
50
52
  ```
51
53
 
52
- | Provider | Environment Variable |
53
- |----------|---------------------|
54
- | Anthropic | `ANTHROPIC_API_KEY` |
55
- | OpenAI | `OPENAI_API_KEY` |
56
- | Google Gemini | `GEMINI_API_KEY` |
57
- | Mistral | `MISTRAL_API_KEY` |
58
- | Groq | `GROQ_API_KEY` |
59
- | Cerebras | `CEREBRAS_API_KEY` |
60
- | xAI | `XAI_API_KEY` |
61
- | OpenRouter | `OPENROUTER_API_KEY` |
62
- | Vercel AI Gateway | `AI_GATEWAY_API_KEY` |
63
- | ZAI | `ZAI_API_KEY` |
64
- | OpenCode Zen | `OPENCODE_API_KEY` |
65
- | Hugging Face | `HF_TOKEN` |
66
- | Kimi For Coding | `KIMI_API_KEY` |
67
- | MiniMax | `MINIMAX_API_KEY` |
68
- | MiniMax (China) | `MINIMAX_CN_API_KEY` |
69
-
70
- ## Auth File
54
+ | Provider | Environment Variable | `auth.json` key |
55
+ |----------|----------------------|------------------|
56
+ | Anthropic | `ANTHROPIC_API_KEY` | `anthropic` |
57
+ | Azure OpenAI Responses | `AZURE_OPENAI_API_KEY` | `azure-openai-responses` |
58
+ | OpenAI | `OPENAI_API_KEY` | `openai` |
59
+ | Google Gemini | `GEMINI_API_KEY` | `google` |
60
+ | Mistral | `MISTRAL_API_KEY` | `mistral` |
61
+ | Groq | `GROQ_API_KEY` | `groq` |
62
+ | Cerebras | `CEREBRAS_API_KEY` | `cerebras` |
63
+ | xAI | `XAI_API_KEY` | `xai` |
64
+ | OpenRouter | `OPENROUTER_API_KEY` | `openrouter` |
65
+ | Vercel AI Gateway | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway` |
66
+ | ZAI | `ZAI_API_KEY` | `zai` |
67
+ | OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |
68
+ | Hugging Face | `HF_TOKEN` | `huggingface` |
69
+ | Kimi For Coding | `KIMI_API_KEY` | `kimi-coding` |
70
+ | MiniMax | `MINIMAX_API_KEY` | `minimax` |
71
+ | MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
72
+
73
+ Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/env-api-keys.ts).
74
+
75
+ #### Auth File
71
76
 
72
77
  Store credentials in `~/.pi/agent/auth.json`:
73
78
 
package/docs/rpc.md CHANGED
@@ -928,11 +928,17 @@ There are two categories of extension UI methods:
928
928
 
929
929
  If a dialog method includes a `timeout` field, the agent-side will auto-resolve with a default value when the timeout expires. The client does not need to track timeouts.
930
930
 
931
- Some `ExtensionUIContext` methods are not supported in RPC mode because they require direct TUI access:
931
+ Some `ExtensionUIContext` methods are not supported or degraded in RPC mode because they require direct TUI access:
932
932
  - `custom()` returns `undefined`
933
933
  - `setWorkingMessage()`, `setFooter()`, `setHeader()`, `setEditorComponent()`, `setToolsExpanded()` are no-ops
934
934
  - `getEditorText()` returns `""`
935
935
  - `getToolsExpanded()` returns `false`
936
+ - `pasteToEditor()` delegates to `setEditorText()` (no paste/collapse handling)
937
+ - `getAllThemes()` returns `[]`
938
+ - `getTheme()` returns `undefined`
939
+ - `setTheme()` returns `{ success: false, error: "..." }`
940
+
941
+ Note: `ctx.hasUI` is `true` in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol.
936
942
 
937
943
  ### Extension UI Requests (stdout)
938
944
 
@@ -66,6 +66,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
66
66
  | `overlay-qa-tests.ts` | Comprehensive overlay QA tests: anchors, margins, stacking, overflow, animation |
67
67
  | `doom-overlay/` | DOOM game running as an overlay at 35 FPS (demonstrates real-time game rendering) |
68
68
  | `shutdown-command.ts` | Adds `/quit` command demonstrating `ctx.shutdown()` |
69
+ | `reload-runtime.ts` | Adds `/reload-runtime` and `reload_runtime` tool showing safe reload flow |
69
70
  | `interactive-shell.ts` | Run interactive commands (vim, htop) with full terminal via `user_bash` hook |
70
71
  | `inline-bash.ts` | Expands `!{command}` patterns in prompts via `input` event transformation |
71
72
 
@@ -13,7 +13,7 @@
13
13
  * pi --extension examples/extensions/custom-compaction.ts
14
14
  */
15
15
 
16
- import { complete, getModel } from "@mariozechner/pi-ai";
16
+ import { complete } from "@mariozechner/pi-ai";
17
17
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
18
18
  import { convertToLlm, serializeConversation } from "@mariozechner/pi-coding-agent";
19
19
 
@@ -25,7 +25,7 @@ export default function (pi: ExtensionAPI) {
25
25
  const { messagesToSummarize, turnPrefixMessages, tokensBefore, firstKeptEntryId, previousSummary } = preparation;
26
26
 
27
27
  // Use Gemini Flash for summarization (cheaper/faster than most conversation models)
28
- const model = getModel("google", "gemini-2.5-flash");
28
+ const model = ctx.modelRegistry.find("google", "gemini-2.5-flash");
29
29
  if (!model) {
30
30
  ctx.ui.notify(`Could not find Gemini Flash model, using default compaction`, "warning");
31
31
  return;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "1.3.7",
3
+ "version": "1.3.9",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "1.3.7",
9
+ "version": "1.3.9",
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.3.7",
4
+ "version": "1.3.9",
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.3.7",
4
+ "version": "1.3.9",
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.2.7",
4
+ "version": "1.2.9",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Reload Runtime Extension
3
+ *
4
+ * Demonstrates ctx.reload() from ExtensionCommandContext and an LLM-callable
5
+ * tool that queues a follow-up command to trigger reload.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
+ import { Type } from "@sinclair/typebox";
10
+
11
+ export default function (pi: ExtensionAPI) {
12
+ // Command entrypoint for reload.
13
+ // Treat reload as terminal for this handler.
14
+ pi.registerCommand("reload-runtime", {
15
+ description: "Reload extensions, skills, prompts, and themes",
16
+ handler: async (_args, ctx) => {
17
+ await ctx.reload();
18
+ return;
19
+ },
20
+ });
21
+
22
+ // LLM-callable tool. Tools get ExtensionContext, so they cannot call ctx.reload() directly.
23
+ // Instead, queue a follow-up user command that executes the command above.
24
+ pi.registerTool({
25
+ name: "reload_runtime",
26
+ label: "Reload Runtime",
27
+ description: "Reload extensions, skills, prompts, and themes",
28
+ parameters: Type.Object({}),
29
+ async execute() {
30
+ pi.sendUserMessage("/reload-runtime", { deliverAs: "followUp" });
31
+ return {
32
+ content: [{ type: "text", text: "Queued /reload-runtime as a follow-up command." }],
33
+ details: {},
34
+ };
35
+ },
36
+ });
37
+ }
@@ -231,13 +231,14 @@ async function runSingleAgent(
231
231
  const agent = agents.find((a) => a.name === agentName);
232
232
 
233
233
  if (!agent) {
234
+ const available = agents.map((a) => `"${a.name}"`).join(", ") || "none";
234
235
  return {
235
236
  agent: agentName,
236
237
  agentSource: "unknown",
237
238
  task,
238
239
  exitCode: 1,
239
240
  messages: [],
240
- stderr: `Unknown agent: ${agentName}`,
241
+ stderr: `Unknown agent: "${agentName}". Available agents: ${available}.`,
241
242
  usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
242
243
  step,
243
244
  };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "1.16.7",
3
+ "version": "1.16.9",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "1.16.7",
9
+ "version": "1.16.9",
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.16.7",
4
+ "version": "1.16.9",
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": "@vandeepunk/pi-coding-agent",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management forked from @mariozechner/pi-coding-agent",
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.52.7",
44
- "@mariozechner/pi-ai": "^0.52.7",
45
- "@mariozechner/pi-tui": "^0.52.7",
43
+ "@mariozechner/pi-agent-core": "^0.52.9",
44
+ "@mariozechner/pi-ai": "^0.52.9",
45
+ "@mariozechner/pi-tui": "^0.52.9",
46
46
  "@silvia-odwyer/photon-node": "^0.3.4",
47
47
  "chalk": "^5.5.0",
48
48
  "cli-highlight": "^2.1.11",