@kingingwang/pi-darwin-arm64 1.0.4 → 1.2.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.
Files changed (45) hide show
  1. package/bin/CHANGELOG.md +115 -0
  2. package/bin/docs/cli-integration.md +1 -1
  3. package/bin/docs/cli.md +5 -5
  4. package/bin/docs/codemode.md +24 -4
  5. package/bin/docs/compaction.md +2 -2
  6. package/bin/docs/environment-variables.md +3 -1
  7. package/bin/docs/extensions.md +7 -4
  8. package/bin/docs/json.md +3 -3
  9. package/bin/docs/keybindings.md +1 -0
  10. package/bin/docs/llama-cpp.md +8 -1
  11. package/bin/docs/mcp.md +1 -1
  12. package/bin/docs/message-types.md +22 -4
  13. package/bin/docs/models.md +5 -1
  14. package/bin/docs/providers.md +47 -0
  15. package/bin/docs/settings.md +6 -4
  16. package/bin/docs/terminal-setup.md +14 -0
  17. package/bin/docs/themes.md +4 -2
  18. package/bin/docs/tui.md +1 -1
  19. package/bin/examples/README.md +0 -3
  20. package/bin/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  21. package/bin/examples/extensions/custom-provider-anthropic/package.json +1 -1
  22. package/bin/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  23. package/bin/examples/extensions/dynamic-resources/dynamic.json +1 -1
  24. package/bin/examples/extensions/gondolin/package-lock.json +2 -2
  25. package/bin/examples/extensions/gondolin/package.json +1 -1
  26. package/bin/examples/extensions/overlay-test.ts +2 -2
  27. package/bin/examples/extensions/plan-mode/index.ts +6 -2
  28. package/bin/examples/extensions/sandbox/package-lock.json +2 -2
  29. package/bin/examples/extensions/sandbox/package.json +1 -1
  30. package/bin/examples/extensions/with-deps/package-lock.json +2 -2
  31. package/bin/examples/extensions/with-deps/package.json +1 -1
  32. package/bin/export-html/tool-renderer.d.ts.map +1 -1
  33. package/bin/export-html/tool-renderer.js +2 -0
  34. package/bin/export-html/tool-renderer.js.map +1 -1
  35. package/bin/package.json +10 -21
  36. package/bin/pi +2 -2
  37. package/bin/theme/dark.json +1 -1
  38. package/bin/theme/light.json +1 -1
  39. package/package.json +1 -1
  40. package/bin/examples/plugins/pi-example-plugin/README.md +0 -38
  41. package/bin/examples/plugins/pi-example-plugin/package.json +0 -10
  42. package/bin/examples/plugins/pi-example-plugin/src/contract.ts +0 -13
  43. package/bin/examples/plugins/pi-example-plugin/src/session.ts +0 -24
  44. package/bin/examples/plugins/pi-example-plugin/src/tui.ts +0 -31
  45. package/bin/theme/theme-schema.json +0 -361
@@ -217,3 +217,17 @@ Pi automatically detects OSC 8 hyperlinks, inline image protocols, and truecolor
217
217
  Settings take precedence over environment variables. An unset value or `auto` preserves automatic detection.
218
218
 
219
219
  Only force a capability supported by the complete terminal path. Unsupported escape sequences can corrupt rendering. See [Environment Variables](environment-variables.md#pi-process-configuration) and [Settings](settings.md) for the canonical value definitions.
220
+
221
+ ## Program status
222
+
223
+ Pi reports its state with the [Program Status Protocol (OSC 7501)](https://www.superlogical.com/rex/docs/build/program-status), so terminals and agent dashboards can show whether it is working, waiting for you, done, or failed:
224
+
225
+ | State | When |
226
+ |---|---|
227
+ | `working` | An agent run or compaction is in progress. The message is the session name. |
228
+ | `blocked` | An extension dialog or login waits for you. The message is the dialog title. |
229
+ | `done` | A run finished. The message is the session name. |
230
+ | `error` | A run ended with an error that is not retried. The message is the first line of the error. |
231
+ | `idle` | Pi started, or you cancelled the run. |
232
+
233
+ Reports never contain prompts or model output. Pi sends them only after the terminal answers the protocol's support query; tmux and screen do not forward them. Set `PI_PROGRAM_STATUS=1` to send reports without asking, or `PI_PROGRAM_STATUS=0` to turn them off.
@@ -58,7 +58,7 @@ See [CLI resources](cli.md#resources) for the command-line option.
58
58
 
59
59
  ## Create a custom theme
60
60
 
61
- Copy one of the [built-in themes](https://github.com/earendil-works/pi/tree/main/packages/coding-agent/src/modes/interactive/theme) or create a new JSON file conforming to the [schema](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json). The built-in themes use OKHSL colors, with variables for colors that several roles share, so you can adjust a hue, saturation, or lightness directly.
61
+ Copy one of the [built-in themes](https://github.com/earendil-works/pi/tree/main/packages/coding-agent/src/modes/interactive/theme) or create a new JSON file conforming to the [schema](https://pi.dev/schemas/theme.schema.json). The built-in themes use OKHSL colors, with variables for colors that several roles share, so you can adjust a hue, saturation, or lightness directly.
62
62
 
63
63
  1. Save the file as `<agent-dir>/themes/my-theme.json`. The agent directory defaults to `~/.pi/agent`.
64
64
  2. Set its `name` to `my-theme`.
@@ -78,6 +78,8 @@ Use the theme name as the filename. Pi hot-reloads the active user theme only fr
78
78
  | `colors` | Yes | Assigns colors to terminal UI roles. The schema identifies required and optional roles. |
79
79
  | `export` | No | Overrides page and panel backgrounds in HTML exports. |
80
80
 
81
+ Theme objects are strict: only documented top-level fields and color tokens are accepted. Define reusable custom colors under `vars`; custom keys under `colors` or `export` and additional top-level metadata are rejected.
82
+
81
83
  A color can be written in six forms:
82
84
 
83
85
  | Form | Example | Meaning |
@@ -93,7 +95,7 @@ Terminal default colors render as the terminal's own colors. Where Pi needs a co
93
95
 
94
96
  Pi resolves chained variable references. A missing variable or circular reference makes the theme invalid. Pi uses truecolor when available, gamut-maps OKLCH to sRGB, and approximates colors for 256-color terminals. HTML exports convert OKHSL values to hexadecimal because CSS does not support them. If colors differ from their source values, check your terminal's truecolor detection and contrast settings. See [Configure Your Terminal](terminal-setup.md#override-detected-capabilities).
95
97
 
96
- Use the [theme JSON schema](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json) for the exact properties, required colors, and accepted value types.
98
+ Use the [theme JSON schema](https://pi.dev/schemas/theme.schema.json) for the exact properties, required colors, and accepted value types.
97
99
 
98
100
  Pi reports invalid theme files during startup and `/reload`.
99
101
 
package/bin/docs/tui.md CHANGED
@@ -45,7 +45,7 @@ Prefer these components over rebuilding selection, scrolling, text editing, or w
45
45
 
46
46
  Use `matchesKey()` and `Key` for terminal keyboard input. The parser accounts for supported terminal protocols and key modifiers. Extension components should use the injected `KeybindingsManager` for configurable application actions.
47
47
 
48
- A component that displays a text cursor should implement `Focusable` and place `CURSOR_MARKER` immediately before its visual cursor. The TUI uses that marker to position the hardware cursor for input method editors.
48
+ A component that displays a text cursor should implement `Focusable` and place `CURSOR_MARKER` immediately before its visual cursor. Wrap the cursor cell in `renderFakeCursor()` so the TUI draws it in reverse video, or hides it after `CURSOR_MARKER` when the hardware cursor is shown. The TUI uses the marker to position the hardware cursor for input method editors.
49
49
 
50
50
  Containers that wrap an `Input` or `Editor` must propagate their `focused` state to that child. Without propagation, Chinese, Japanese, Korean, and other IME candidate windows can appear at the wrong screen position.
51
51
 
@@ -28,9 +28,6 @@ Example extensions demonstrating:
28
28
  - External integrations (SSH, file watchers, system theme sync)
29
29
  - Custom providers (Anthropic with custom streaming, GitLab Duo)
30
30
 
31
- ### [plugins/pi-example-plugin/](plugins/pi-example-plugin/)
32
- An experimental plugin package that Pi automatically builds into separate Session-worker and TUI Chord facets.
33
-
34
31
  ## Documentation
35
32
 
36
33
  - [SDK Examples](sdk/README.md)
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "1.0.4",
9
+ "version": "1.2.0",
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.0.4",
4
+ "version": "1.2.0",
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.0.4",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://pi.dev/schemas/theme.schema.json",
3
3
  "name": "dynamic-resources",
4
4
  "vars": {
5
5
  "cyan": "#00d7ff",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "1.0.4",
9
+ "version": "1.2.0",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent";
12
- import { CURSOR_MARKER, type Focusable, matchesKey, visibleWidth } from "@earendil-works/pi-tui";
12
+ import { CURSOR_MARKER, type Focusable, matchesKey, renderFakeCursor, visibleWidth } from "@earendil-works/pi-tui";
13
13
 
14
14
  export default function (pi: ExtensionAPI) {
15
15
  pi.registerCommand("overlay-test", {
@@ -131,7 +131,7 @@ class OverlayTestComponent implements Focusable {
131
131
  const after = inputDisplay.slice(item.cursor + 1);
132
132
  // Emit hardware cursor marker for IME support when focused
133
133
  const marker = this.focused ? CURSOR_MARKER : "";
134
- inputDisplay = `${before}${marker}\x1b[7m${cursorChar}\x1b[27m${after}`;
134
+ inputDisplay = `${before}${marker}${renderFakeCursor(cursorChar)}${after}`;
135
135
  }
136
136
  content = `${prefix + label} ${inputDisplay}`;
137
137
  } else {
@@ -197,8 +197,12 @@ export default function planModeExtension(pi: ExtensionAPI): void {
197
197
  };
198
198
  });
199
199
 
200
- // Inject plan/execution context before agent starts
201
- pi.on("before_agent_start", async () => {
200
+ // Inject plan/execution context before a user prompt. Runs started by custom messages, such as
201
+ // background task notifications, skip it: the context from the last prompt is still in the
202
+ // conversation, and adding it again on every notification would only repeat it.
203
+ pi.on("before_agent_start", async (event) => {
204
+ if (event.messageType !== "user") return;
205
+
202
206
  if (planModeEnabled) {
203
207
  return {
204
208
  message: {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "1.0.4",
9
+ "version": "1.2.0",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "1.0.4",
9
+ "version": "1.2.0",
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.0.4",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1 +1 @@
1
- {"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACpC,sFAAsF;IACtF,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC9D,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,yGAAyG;IACzG,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAkHnF"}
1
+ {"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACpC,sFAAsF;IACtF,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC9D,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,yGAAyG;IACzG,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAoHnF"}
@@ -52,6 +52,8 @@ export function createToolHtmlRenderer(deps) {
52
52
  expanded,
53
53
  showImages: false,
54
54
  isError,
55
+ durationMs: undefined,
56
+ outputPad: 1,
55
57
  };
56
58
  };
57
59
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { Component } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolRenderContext, ToolRenderers } from \"../extensions/types.ts\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.ts\";\n\nexport interface ToolHtmlRendererDeps {\n\t/** Renderers of calls to a tool, as resolved by extensions and the registered tool */\n\tgetToolRenderers: (name: string) => ToolRenderers | undefined;\n\t/** Theme for styling */\n\ttheme: Theme;\n\t/** Working directory for render context */\n\tcwd: string;\n\t/** Terminal width for rendering (default: 100) */\n\twidth?: number;\n}\n\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to collapsed/expanded HTML. Returns undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[\\d;]*m/g;\n\nfunction isBlankRenderedLine(line: string): boolean {\n\treturn line.replace(ANSI_ESCAPE_REGEX, \"\").trim().length === 0;\n}\n\nfunction trimRenderedResultLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && isBlankRenderedLine(lines[start])) start++;\n\twhile (end > start && isBlankRenderedLine(lines[end - 1])) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function createToolHtmlRenderer(deps: ToolHtmlRendererDeps): ToolHtmlRenderer {\n\tconst { getToolRenderers, theme, cwd, width = 100 } = deps;\n\n\tconst renderedCallComponents = new Map<string, Component>();\n\tconst renderedResultComponents = new Map<string, Component>();\n\tconst renderedStates = new Map<string, any>();\n\tconst renderedArgs = new Map<string, unknown>();\n\n\tconst getState = (toolCallId: string): any => {\n\t\tlet state = renderedStates.get(toolCallId);\n\t\tif (!state) {\n\t\t\tstate = {};\n\t\t\trenderedStates.set(toolCallId, state);\n\t\t}\n\t\treturn state;\n\t};\n\n\tconst createRenderContext = (\n\t\ttoolCallId: string,\n\t\tlastComponent: Component | undefined,\n\t\texpanded: boolean,\n\t\tisPartial: boolean,\n\t\tisError: boolean,\n\t): ToolRenderContext => {\n\t\treturn {\n\t\t\targs: renderedArgs.get(toolCallId),\n\t\t\ttoolCallId,\n\t\t\tinvalidate: () => {},\n\t\t\tlastComponent,\n\t\t\tstate: getState(toolCallId),\n\t\t\tcwd,\n\t\t\texecutionStarted: true,\n\t\t\targsComplete: true,\n\t\t\tisPartial,\n\t\t\texpanded,\n\t\t\tshowImages: false,\n\t\t\tisError,\n\t\t};\n\t};\n\n\treturn {\n\t\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined {\n\t\t\ttry {\n\t\t\t\trenderedArgs.set(toolCallId, args);\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderCall) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst component = toolDef.renderCall(\n\t\t\t\t\targs,\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedCallComponents.get(toolCallId), false, true, false),\n\t\t\t\t);\n\t\t\t\trenderedCallComponents.set(toolCallId, component);\n\t\t\t\tconst lines = component.render(width);\n\t\t\t\treturn ansiLinesToHtml(lines);\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\trenderResult(\n\t\t\ttoolCallId: string,\n\t\t\ttoolName: string,\n\t\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\t\tdetails: unknown,\n\t\t\tisError: boolean,\n\t\t): { collapsed?: string; expanded?: string } | undefined {\n\t\t\ttry {\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderResult) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build AgentToolResult from content array\n\t\t\t\t// Cast content since session storage uses generic object types\n\t\t\t\tconst agentToolResult = {\n\t\t\t\t\tcontent: result as (TextContent | ImageContent)[],\n\t\t\t\t\tdetails,\n\t\t\t\t\tisError,\n\t\t\t\t};\n\n\t\t\t\t// Render collapsed\n\t\t\t\tconst collapsedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: false, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), false, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, collapsedComponent);\n\t\t\t\tconst collapsed = ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width)));\n\n\t\t\t\t// Render expanded\n\t\t\t\tconst expandedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: true, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), true, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, expandedComponent);\n\t\t\t\tconst expanded = ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(collapsed && collapsed !== expanded ? { collapsed } : {}),\n\t\t\t\t\texpanded,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { Component } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolRenderContext, ToolRenderers } from \"../extensions/types.ts\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.ts\";\n\nexport interface ToolHtmlRendererDeps {\n\t/** Renderers of calls to a tool, as resolved by extensions and the registered tool */\n\tgetToolRenderers: (name: string) => ToolRenderers | undefined;\n\t/** Theme for styling */\n\ttheme: Theme;\n\t/** Working directory for render context */\n\tcwd: string;\n\t/** Terminal width for rendering (default: 100) */\n\twidth?: number;\n}\n\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to collapsed/expanded HTML. Returns undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[\\d;]*m/g;\n\nfunction isBlankRenderedLine(line: string): boolean {\n\treturn line.replace(ANSI_ESCAPE_REGEX, \"\").trim().length === 0;\n}\n\nfunction trimRenderedResultLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && isBlankRenderedLine(lines[start])) start++;\n\twhile (end > start && isBlankRenderedLine(lines[end - 1])) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function createToolHtmlRenderer(deps: ToolHtmlRendererDeps): ToolHtmlRenderer {\n\tconst { getToolRenderers, theme, cwd, width = 100 } = deps;\n\n\tconst renderedCallComponents = new Map<string, Component>();\n\tconst renderedResultComponents = new Map<string, Component>();\n\tconst renderedStates = new Map<string, any>();\n\tconst renderedArgs = new Map<string, unknown>();\n\n\tconst getState = (toolCallId: string): any => {\n\t\tlet state = renderedStates.get(toolCallId);\n\t\tif (!state) {\n\t\t\tstate = {};\n\t\t\trenderedStates.set(toolCallId, state);\n\t\t}\n\t\treturn state;\n\t};\n\n\tconst createRenderContext = (\n\t\ttoolCallId: string,\n\t\tlastComponent: Component | undefined,\n\t\texpanded: boolean,\n\t\tisPartial: boolean,\n\t\tisError: boolean,\n\t): ToolRenderContext => {\n\t\treturn {\n\t\t\targs: renderedArgs.get(toolCallId),\n\t\t\ttoolCallId,\n\t\t\tinvalidate: () => {},\n\t\t\tlastComponent,\n\t\t\tstate: getState(toolCallId),\n\t\t\tcwd,\n\t\t\texecutionStarted: true,\n\t\t\targsComplete: true,\n\t\t\tisPartial,\n\t\t\texpanded,\n\t\t\tshowImages: false,\n\t\t\tisError,\n\t\t\tdurationMs: undefined,\n\t\t\toutputPad: 1,\n\t\t};\n\t};\n\n\treturn {\n\t\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined {\n\t\t\ttry {\n\t\t\t\trenderedArgs.set(toolCallId, args);\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderCall) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst component = toolDef.renderCall(\n\t\t\t\t\targs,\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedCallComponents.get(toolCallId), false, true, false),\n\t\t\t\t);\n\t\t\t\trenderedCallComponents.set(toolCallId, component);\n\t\t\t\tconst lines = component.render(width);\n\t\t\t\treturn ansiLinesToHtml(lines);\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\trenderResult(\n\t\t\ttoolCallId: string,\n\t\t\ttoolName: string,\n\t\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\t\tdetails: unknown,\n\t\t\tisError: boolean,\n\t\t): { collapsed?: string; expanded?: string } | undefined {\n\t\t\ttry {\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderResult) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build AgentToolResult from content array\n\t\t\t\t// Cast content since session storage uses generic object types\n\t\t\t\tconst agentToolResult = {\n\t\t\t\t\tcontent: result as (TextContent | ImageContent)[],\n\t\t\t\t\tdetails,\n\t\t\t\t\tisError,\n\t\t\t\t};\n\n\t\t\t\t// Render collapsed\n\t\t\t\tconst collapsedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: false, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), false, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, collapsedComponent);\n\t\t\t\tconst collapsed = ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width)));\n\n\t\t\t\t// Render expanded\n\t\t\t\tconst expandedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: true, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), true, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, expandedComponent);\n\t\t\t\tconst expanded = ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(collapsed && collapsed !== expanded ? { collapsed } : {}),\n\t\t\t\t\texpanded,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
package/bin/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -18,21 +18,13 @@
18
18
  },
19
19
  "./rpc-entry": {
20
20
  "import": "./dist/bundle/rpc-entry.js"
21
- },
22
- "./client": {
23
- "source": "./src/client/index.ts"
24
- },
25
- "./experimental/plugin": {
26
- "source": "./src/experimental/plugin.ts"
27
21
  }
28
22
  },
29
23
  "files": [
30
24
  "dist",
31
- "!dist/client",
32
- "!dist/experimental",
33
- "!dist/cli/experimental",
34
25
  "docs",
35
26
  "examples",
27
+ "schemas",
36
28
  "containerization.md",
37
29
  "CHANGELOG.md"
38
30
  ],
@@ -40,19 +32,19 @@
40
32
  "clean": "shx rm -rf dist",
41
33
  "build": "npm run build:unbundled && node ../../scripts/build-coding-agent-bundle.mjs",
42
34
  "build:unbundled": "tsc -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
43
- "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm --prefix ../protocol run build && npm --prefix ../client run build && npm run build && bun build --compile --no-compile-autoload-bunfig ./dist/bun/cli.js ./src/utils/image-resize-worker.ts ./src/extensions/codemode/worker.ts --outfile dist/pi && npm run copy-binary-assets",
35
+ "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile --no-compile-autoload-bunfig --no-compile-autoload-dotenv ./dist/bun/cli.js ./src/utils/image-resize-worker.ts ./src/extensions/codemode/worker.ts --outfile dist/pi && npm run copy-binary-assets",
44
36
  "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
45
37
  "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
46
38
  "test": "vitest --run",
39
+ "generate:schemas": "node --import ./src/experimental/source-resolver.ts scripts/generate-schemas.ts",
47
40
  "prepublishOnly": "npm run clean && npm run build"
48
41
  },
49
42
  "dependencies": {
50
- "@earendil-works/chord": "^1.0.4",
51
- "@earendil-works/pi-agent-core": "^1.0.4",
52
- "@earendil-works/pi-ai": "^1.0.4",
53
- "@earendil-works/pi-codemode": "^1.0.4",
54
- "@earendil-works/pi-mcp": "^1.0.4",
55
- "@earendil-works/pi-tui": "^1.0.4",
43
+ "@earendil-works/pi-agent-core": "^1.2.0",
44
+ "@earendil-works/pi-ai": "^1.2.0",
45
+ "@earendil-works/pi-codemode": "^1.2.0",
46
+ "@earendil-works/pi-mcp": "^1.2.0",
47
+ "@earendil-works/pi-tui": "^1.2.0",
56
48
  "@silvia-odwyer/photon-node": "0.3.4",
57
49
  "brace-expansion": "5.0.12",
58
50
  "chalk": "6.0.0",
@@ -75,16 +67,13 @@
75
67
  "protobufjs": "7.6.6"
76
68
  },
77
69
  "devDependencies": {
78
- "@earendil-works/pi-client": "^1.0.4",
79
- "@earendil-works/pi-protocol": "^1.0.4",
80
- "@earendil-works/pi-server": "^1.0.4",
81
70
  "@types/cross-spawn": "6.0.6",
82
71
  "@types/hosted-git-info": "3.0.5",
83
72
  "@types/node": "22.19.19",
84
73
  "@types/proper-lockfile": "4.1.4",
85
74
  "@types/semver": "7.7.1",
86
75
  "marked": "18.0.11",
87
- "shx": "0.4.0",
76
+ "shx": "0.3.4",
88
77
  "vitest": "4.1.11"
89
78
  },
90
79
  "keywords": [
package/bin/pi CHANGED
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/bin/pi
3
- size: 76870370 bytes
4
- sha256: bceb3f3b317940c58de01bddd9decdcb0755ffb544ae793fac1745502da6ddc2
3
+ size: 77101538 bytes
4
+ sha256: 6b55223a5c40fbbcb4e266add65398063cbadcc5cb98a73afbbde8de2d7e943d
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://pi.dev/schemas/theme.schema.json",
3
3
  "name": "dark",
4
4
  "appearance": "dark",
5
5
  "vars": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://pi.dev/schemas/theme.schema.json",
3
3
  "name": "light",
4
4
  "appearance": "light",
5
5
  "vars": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kingingwang/pi-darwin-arm64",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "description": "Pi standalone binary for darwin-arm64 (fork distribution)",
5
5
  "license": "MIT",
6
6
  "os": [
@@ -1,38 +0,0 @@
1
- # `@earendil-works/pi-example-plugin`
2
-
3
- This package provides conventional `session` and `tui` Chord facets. The Session-worker facet provides a remote greeting service. The TUI facet contributes `/hello` and calls that service.
4
-
5
- The package needs no build script. Pi asks Chord to discover `src/session.ts` and `src/tui.ts`, builds both entries into its server-owned plugin cache, and sends the TUI artifact to clients.
6
-
7
- From the repository root:
8
-
9
- ```bash
10
- PI_EXPERIMENTAL=1 ./pi-test.sh server \
11
- -e "$PWD/packages/coding-agent/examples/plugins/pi-example-plugin"
12
- ```
13
-
14
- Alternatively, a client can select the plugin for the Session it creates or resumes on one local server:
15
-
16
- ```bash
17
- PI_EXPERIMENTAL=1 ./pi-test.sh client \
18
- -e "$PWD/packages/coding-agent/examples/plugins/pi-example-plugin"
19
- ```
20
-
21
- Repeat `-e` to select multiple plugin packages. Client paths are resolved locally and sent only to a Unix server; Radius clients cannot select server filesystem paths. The Session and matching TUI facets are stored with that Session, so later server generations and clients can resume it without plugin arguments. Other Sessions and their workers are unaffected. An active Session rejects a different package selection instead of being restarted.
22
-
23
- `server -e` establishes the server profile's default Session and TUI facets. Starting an explicit foreground server without `-e` clears that default. Client selection never changes the server's root facet generation.
24
-
25
- Run `/hello Armin` in the TUI. After editing a facet, run `/reload`. The server atomically rebuilds the package, reloads the attached Session-worker generation, updates the current TUI generation, and serves the new artifact to future clients.
26
-
27
- Package metadata can override or disable conventional entries:
28
-
29
- ```json
30
- {
31
- "chord": {
32
- "facets": {
33
- "session": "./src/worker.ts",
34
- "tui": false
35
- }
36
- }
37
- }
38
- ```
@@ -1,10 +0,0 @@
1
- {
2
- "name": "@earendil-works/pi-example-plugin",
3
- "version": "1.0.0",
4
- "private": true,
5
- "type": "module",
6
- "peerDependencies": {
7
- "@earendil-works/chord": "^0.84.4",
8
- "@earendil-works/pi-coding-agent": "^0.84.4"
9
- }
10
- }
@@ -1,13 +0,0 @@
1
- import { type Context, defineService, type ReplicatedState } from "@earendil-works/chord";
2
-
3
- export interface ExampleFacetReply {
4
- readonly message: string;
5
- readonly workerActivations: number;
6
- }
7
-
8
- export interface ExampleFacetService {
9
- readonly workerActivations: ReplicatedState<{ count: number }>;
10
- greet(input: { readonly name: string }, context: Context): Promise<ExampleFacetReply>;
11
- }
12
-
13
- export const ExampleFacetService = defineService<ExampleFacetService>("pi.example-plugin.greeting");
@@ -1,24 +0,0 @@
1
- import { defineFacet } from "@earendil-works/chord";
2
- import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
3
- import { ExampleFacetService } from "./contract.ts";
4
-
5
- export default defineFacet({
6
- id: "@earendil-works/pi-example-plugin/session",
7
- setup(env) {
8
- const workerActivations = env.replicatedState({ count: 0 });
9
- env.provide(ExampleFacetService, {
10
- workerActivations,
11
- async greet({ name }) {
12
- return {
13
- message: `Hello ${name} from the bundled Session worker facet!!!`,
14
- workerActivations: workerActivations.value.count,
15
- };
16
- },
17
- });
18
- env.onActivate(() => {
19
- workerActivations.change(BACKGROUND_CONTEXT, (draft) => {
20
- draft.count += 1;
21
- });
22
- });
23
- },
24
- });
@@ -1,31 +0,0 @@
1
- import { defineFacet } from "@earendil-works/chord";
2
- import { AgentController, PresentationUI, SlashCommands } from "@earendil-works/pi-coding-agent/experimental/plugin";
3
- import { ExampleFacetService } from "./contract.ts";
4
-
5
- export default defineFacet({
6
- id: "@earendil-works/pi-example-plugin/tui",
7
- setup(env) {
8
- const example = env.use(ExampleFacetService);
9
- const commands = env.use(SlashCommands);
10
- const controller = env.use(AgentController);
11
- const ui = env.use(PresentationUI);
12
- env.onActivate(() => {
13
- env.own(
14
- commands.replace({
15
- name: "hello",
16
- description: "Call the bundled Session worker facet",
17
- argumentHint: "<name>",
18
- async run(args, context) {
19
- const message = args.length === 0 ? "from the TUI" : args;
20
- const reply = await example.greet({ name: message }, context);
21
- ui.showStatus(
22
- `We got this: ${reply.message} Worker activations: ${reply.workerActivations}.`,
23
- context,
24
- );
25
- return controller.prompt({ message: `pong: ${message}`, images: null }, context);
26
- },
27
- }),
28
- );
29
- });
30
- },
31
- });