@earendil-works/pi-coding-agent 0.80.6 → 0.80.7
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 +37 -0
- package/README.md +3 -1
- package/dist/core/agent-session.d.ts +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -4
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +5 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +22 -3
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/keybindings.d.ts +8 -3
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +7 -3
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +18 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +7 -2
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/radius.d.ts +21 -0
- package/dist/core/radius.d.ts.map +1 -0
- package/dist/core/radius.js +30 -0
- package/dist/core/radius.js.map +1 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -11
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +1 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +4 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +9 -2
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +5 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +49 -12
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +45 -41
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +13 -0
- package/dist/utils/clipboard.js.map +1 -1
- package/docs/custom-provider.md +2 -0
- package/docs/extensions.md +138 -0
- package/docs/keybindings.md +1 -0
- package/docs/models.md +2 -0
- package/docs/providers.md +3 -0
- package/docs/quickstart.md +1 -1
- package/docs/usage.md +1 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard-native.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard-native.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC7C,CAAC;AAEF,KAAK,gBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;AAMhD,wBAAgB,mBAAmB,CAClC,QAAQ,GAAE,SAAS,gBAAgB,EAA0C,GAC3E,eAAe,GAAG,IAAI,CASxB;AAED,QAAA,MAAM,SAAS,wBAA2E,CAAC;AAE3F,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type ClipboardModule = {\n\tsetText: (text: string) => Promise<void>;\n\thasImage: () => boolean;\n\tgetImageBinary: () => Promise<Array<number>>;\n};\n\ntype ClipboardRequire = (id: string) => unknown;\n\nconst moduleRequire = createRequire(import.meta.url);\nconst executableDirRequire = createRequire(pathToFileURL(join(dirname(process.execPath), \"package.json\")).href);\nconst hasDisplay = process.platform !== \"linux\" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);\n\nexport function loadClipboardNative(\n\trequires: readonly ClipboardRequire[] = [moduleRequire, executableDirRequire],\n): ClipboardModule | null {\n\tfor (const requireClipboard of requires) {\n\t\ttry {\n\t\t\treturn requireClipboard(\"@mariozechner/clipboard\") as ClipboardModule;\n\t\t} catch {\n\t\t\t// Try the next resolution root.\n\t\t}\n\t}\n\treturn null;\n}\n\nconst clipboard = !process.env.TERMUX_VERSION && hasDisplay ? loadClipboardNative() : null;\n\nexport { clipboard };\n"]}
|
|
1
|
+
{"version":3,"file":"clipboard-native.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard-native.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC7C,CAAC;AAEF,KAAK,gBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;AAMhD,wBAAgB,mBAAmB,CAClC,QAAQ,GAAE,SAAS,gBAAgB,EAA0C,GAC3E,eAAe,GAAG,IAAI,CASxB;AAED,QAAA,MAAM,SAAS,wBAA2E,CAAC;AAE3F,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type ClipboardModule = {\n\tgetText: () => Promise<string>;\n\tsetText: (text: string) => Promise<void>;\n\thasImage: () => boolean;\n\tgetImageBinary: () => Promise<Array<number>>;\n};\n\ntype ClipboardRequire = (id: string) => unknown;\n\nconst moduleRequire = createRequire(import.meta.url);\nconst executableDirRequire = createRequire(pathToFileURL(join(dirname(process.execPath), \"package.json\")).href);\nconst hasDisplay = process.platform !== \"linux\" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);\n\nexport function loadClipboardNative(\n\trequires: readonly ClipboardRequire[] = [moduleRequire, executableDirRequire],\n): ClipboardModule | null {\n\tfor (const requireClipboard of requires) {\n\t\ttry {\n\t\t\treturn requireClipboard(\"@mariozechner/clipboard\") as ClipboardModule;\n\t\t} catch {\n\t\t\t// Try the next resolution root.\n\t\t}\n\t}\n\treturn null;\n}\n\nconst clipboard = !process.env.TERMUX_VERSION && hasDisplay ? loadClipboardNative() : null;\n\nexport { clipboard };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard-native.js","sourceRoot":"","sources":["../../src/utils/clipboard-native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"clipboard-native.js","sourceRoot":"","sources":["../../src/utils/clipboard-native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAWpC,MAAM,aAAa,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AACrD,MAAM,oBAAoB,GAAG,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAChH,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AAE/G,MAAM,UAAU,mBAAmB,CAClC,QAAQ,GAAgC,CAAC,aAAa,EAAE,oBAAoB,CAAC,EACpD;IACzB,KAAK,MAAM,gBAAgB,IAAI,QAAQ,EAAE,CAAC;QACzC,IAAI,CAAC;YACJ,OAAO,gBAAgB,CAAC,yBAAyB,CAAoB,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACR,gCAAgC;QACjC,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACZ;AAED,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,UAAU,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAE3F,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type ClipboardModule = {\n\tgetText: () => Promise<string>;\n\tsetText: (text: string) => Promise<void>;\n\thasImage: () => boolean;\n\tgetImageBinary: () => Promise<Array<number>>;\n};\n\ntype ClipboardRequire = (id: string) => unknown;\n\nconst moduleRequire = createRequire(import.meta.url);\nconst executableDirRequire = createRequire(pathToFileURL(join(dirname(process.execPath), \"package.json\")).href);\nconst hasDisplay = process.platform !== \"linux\" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);\n\nexport function loadClipboardNative(\n\trequires: readonly ClipboardRequire[] = [moduleRequire, executableDirRequire],\n): ClipboardModule | null {\n\tfor (const requireClipboard of requires) {\n\t\ttry {\n\t\t\treturn requireClipboard(\"@mariozechner/clipboard\") as ClipboardModule;\n\t\t} catch {\n\t\t\t// Try the next resolution root.\n\t\t}\n\t}\n\treturn null;\n}\n\nconst clipboard = !process.env.TERMUX_VERSION && hasDisplay ? loadClipboardNative() : null;\n\nexport { clipboard };\n"]}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
/** Read plain text from the system clipboard, if native clipboard access is available. */
|
|
2
|
+
export declare function readClipboardText(): Promise<string | null>;
|
|
1
3
|
export declare function copyToClipboard(text: string): Promise<void>;
|
|
2
4
|
//# sourceMappingURL=clipboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAkCA,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FjE","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { clipboard } from \"./clipboard-native.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\nfunction isRemoteSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession();\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: [\"pipe\", \"ignore\", \"ignore\"] };\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(process.env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(process.env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead\n\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\t\t\tproc.unref();\n\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tif (remote || !copied) {\n\t\tconst osc52Copied = emitOsc52(text);\n\t\tcopied = copied || osc52Copied;\n\t}\n\n\tif (!copied) {\n\t\tthrow new Error(\"Failed to copy to clipboard\");\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAkCA,0FAA0F;AAC1F,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWhE;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FjE","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { clipboard } from \"./clipboard-native.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\nfunction isRemoteSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\n/** Read plain text from the system clipboard, if native clipboard access is available. */\nexport async function readClipboardText(): Promise<string | null> {\n\tif (!clipboard) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst text = await clipboard.getText();\n\t\treturn text || null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession();\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: [\"pipe\", \"ignore\", \"ignore\"] };\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(process.env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(process.env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead\n\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\t\t\tproc.unref();\n\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tif (remote || !copied) {\n\t\tconst osc52Copied = emitOsc52(text);\n\t\tcopied = copied || osc52Copied;\n\t}\n\n\tif (!copied) {\n\t\tthrow new Error(\"Failed to copy to clipboard\");\n\t}\n}\n"]}
|
package/dist/utils/clipboard.js
CHANGED
|
@@ -22,6 +22,19 @@ function emitOsc52(text) {
|
|
|
22
22
|
process.stdout.write(`\x1b]52;c;${encoded}\x07`);
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
|
+
/** Read plain text from the system clipboard, if native clipboard access is available. */
|
|
26
|
+
export async function readClipboardText() {
|
|
27
|
+
if (!clipboard) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const text = await clipboard.getText();
|
|
32
|
+
return text || null;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
25
38
|
export async function copyToClipboard(text) {
|
|
26
39
|
let copied = false;
|
|
27
40
|
const p = platform();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { clipboard } from \"./clipboard-native.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\nfunction isRemoteSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession();\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: [\"pipe\", \"ignore\", \"ignore\"] };\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(process.env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(process.env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead\n\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\t\t\tproc.unref();\n\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tif (remote || !copied) {\n\t\tconst osc52Copied = emitOsc52(text);\n\t\tcopied = copied || osc52Copied;\n\t}\n\n\tif (!copied) {\n\t\tthrow new Error(\"Failed to copy to clipboard\");\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { clipboard } from \"./clipboard-native.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\nfunction isRemoteSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\n/** Read plain text from the system clipboard, if native clipboard access is available. */\nexport async function readClipboardText(): Promise<string | null> {\n\tif (!clipboard) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst text = await clipboard.getText();\n\t\treturn text || null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession();\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: [\"pipe\", \"ignore\", \"ignore\"] };\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(process.env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(process.env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead\n\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\t\t\tproc.unref();\n\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tif (remote || !copied) {\n\t\tconst osc52Copied = emitOsc52(text);\n\t\tcopied = copied || osc52Copied;\n\t}\n\n\tif (!copied) {\n\t\tthrow new Error(\"Failed to copy to clipboard\");\n\t}\n}\n"]}
|
package/docs/custom-provider.md
CHANGED
|
@@ -722,6 +722,8 @@ interface ProviderModelConfig {
|
|
|
722
722
|
thinkingFormat?: "openai" | "openrouter" | "deepseek" | "together" | "zai" | "qwen" | "chat-template" | "qwen-chat-template" | "string-thinking" | "ant-ling";
|
|
723
723
|
chatTemplateKwargs?: Record<string, string | number | boolean | null | { "$var": "thinking.enabled" | "thinking.effort"; omitWhenOff?: boolean }>;
|
|
724
724
|
cacheControlFormat?: "anthropic";
|
|
725
|
+
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter";
|
|
726
|
+
sendSessionAffinityHeaders?: boolean;
|
|
725
727
|
|
|
726
728
|
// anthropic-messages
|
|
727
729
|
supportsEagerToolInputStreaming?: boolean;
|
package/docs/extensions.md
CHANGED
|
@@ -47,6 +47,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
47
47
|
- [ExtensionAPI Methods](#extensionapi-methods)
|
|
48
48
|
- [State Management](#state-management)
|
|
49
49
|
- [Custom Tools](#custom-tools)
|
|
50
|
+
- [Dynamic Tool Loading](#dynamic-tool-loading)
|
|
50
51
|
- [Custom UI](#custom-ui)
|
|
51
52
|
- [Error Handling](#error-handling)
|
|
52
53
|
- [Mode Behavior](#mode-behavior)
|
|
@@ -2229,6 +2230,143 @@ If a slot renderer is not defined or throws:
|
|
|
2229
2230
|
- `renderCall`: Shows the tool name
|
|
2230
2231
|
- `renderResult`: Shows raw text from `content`
|
|
2231
2232
|
|
|
2233
|
+
### Dynamic Tool Loading
|
|
2234
|
+
|
|
2235
|
+
Extensions can register many tools while keeping only a small initial set active. A tool can then add more tools with `pi.setActiveTools()` during execution. Pi detects purely additive changes, records the newly available tool names on that tool result, and applies the updated active set before the next model request.
|
|
2236
|
+
|
|
2237
|
+
This works with every model. Models with native deferred-loading support preserve the stable prompt prefix and load the new definitions at the tool-result position. Other models use the fallback described below.
|
|
2238
|
+
|
|
2239
|
+
The lifecycle is:
|
|
2240
|
+
|
|
2241
|
+
1. Register every tool with `pi.registerTool()` so it appears in `pi.getAllTools()`.
|
|
2242
|
+
2. Keep loader tools, such as `search_tools`, active and leave searchable tools inactive.
|
|
2243
|
+
3. During loader execution, call `pi.setActiveTools([...currentTools, ...matchingTools])`. The change must be additive: do not remove currently active tools in the same call.
|
|
2244
|
+
4. Pi records which tools were added on the loader's tool result.
|
|
2245
|
+
5. Before the next model response, Pi exposes the added definitions using native deferred loading when supported, or the normal active tool list otherwise.
|
|
2246
|
+
|
|
2247
|
+
You do not need to return provider-specific tool references or mark the loader as a special search tool. The active-tool change is the signal. Names passed to `pi.setActiveTools()` must already be registered; unknown names are ignored.
|
|
2248
|
+
|
|
2249
|
+
#### Models with native deferred loading
|
|
2250
|
+
|
|
2251
|
+
- **Anthropic**
|
|
2252
|
+
- **Models:** Sonnet, Opus, Fable version 4.5 or newer (without Haiku)
|
|
2253
|
+
- **Native representation:** Deferred definitions use `defer_loading`; the load point uses `tool_reference` content.
|
|
2254
|
+
- **OpenAI**
|
|
2255
|
+
- **Models:** `gpt-5.4` and newer family
|
|
2256
|
+
- **Native representation:** Pi adds completed client `tool_search_call` and `tool_search_output` items at the load point.
|
|
2257
|
+
|
|
2258
|
+
For a verified custom model or proxy, native handling can be enabled with `compat.supportsToolReferences: true` for `anthropic-messages`, or `compat.supportsToolSearch: true` for `openai-responses` and `openai-codex-responses`. Leave these disabled unless the endpoint and model accept the corresponding native protocol.
|
|
2259
|
+
|
|
2260
|
+
#### Fallback behavior
|
|
2261
|
+
|
|
2262
|
+
For all other models and providers, dynamic activation still works: Pi sends the complete current active tool list normally on the next request. The model can call the newly activated tools, but adding their definitions may invalidate the provider's cached prompt prefix.
|
|
2263
|
+
|
|
2264
|
+
Pi also uses this safe fallback when the active set is not purely additive, such as replacing one group of tools with another. Tool removals therefore work, but they do not use deferred loading.
|
|
2265
|
+
|
|
2266
|
+
For the best cache behavior, keep the loader tool active for the whole session and add tools instead of replacing the active set. Also note that activating a tool with `promptSnippet` or `promptGuidelines` rebuilds the system prompt; that system-prompt change can invalidate the prefix even when the provider supports deferred schemas. Lazily loaded tools should usually rely on their tool `description` and omit active-only prompt metadata.
|
|
2267
|
+
|
|
2268
|
+
#### Search tool example
|
|
2269
|
+
|
|
2270
|
+
The following extension registers two searchable tools, removes them from the initial active set, and keeps only `search_tools` as their loader. The example uses simple keyword matching, but the search implementation could use BM25, embeddings, a remote catalog, or project-specific routing.
|
|
2271
|
+
|
|
2272
|
+
```typescript
|
|
2273
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2274
|
+
import { Type } from "typebox";
|
|
2275
|
+
|
|
2276
|
+
const SEARCHABLE_TOOL_NAMES = new Set(["lookup_weather", "search_issues"]);
|
|
2277
|
+
|
|
2278
|
+
export default function (pi: ExtensionAPI) {
|
|
2279
|
+
pi.registerTool({
|
|
2280
|
+
name: "lookup_weather",
|
|
2281
|
+
label: "Lookup Weather",
|
|
2282
|
+
description: "Look up the current weather for a city",
|
|
2283
|
+
parameters: Type.Object({ city: Type.String() }),
|
|
2284
|
+
async execute(_toolCallId, params) {
|
|
2285
|
+
return {
|
|
2286
|
+
content: [{ type: "text", text: `Weather for ${params.city}: sunny` }],
|
|
2287
|
+
details: {},
|
|
2288
|
+
};
|
|
2289
|
+
},
|
|
2290
|
+
});
|
|
2291
|
+
|
|
2292
|
+
pi.registerTool({
|
|
2293
|
+
name: "search_issues",
|
|
2294
|
+
label: "Search Issues",
|
|
2295
|
+
description: "Search project issues by keyword",
|
|
2296
|
+
parameters: Type.Object({ query: Type.String() }),
|
|
2297
|
+
async execute(_toolCallId, params) {
|
|
2298
|
+
return {
|
|
2299
|
+
content: [{ type: "text", text: `No open issues matching ${params.query}` }],
|
|
2300
|
+
details: {},
|
|
2301
|
+
};
|
|
2302
|
+
},
|
|
2303
|
+
});
|
|
2304
|
+
|
|
2305
|
+
pi.registerTool({
|
|
2306
|
+
name: "search_tools",
|
|
2307
|
+
label: "Search Tools",
|
|
2308
|
+
description: "Search for and enable tools relevant to a task",
|
|
2309
|
+
promptSnippet: "Search for additional tools when the active tools cannot perform the task",
|
|
2310
|
+
promptGuidelines: [
|
|
2311
|
+
"Use search_tools when a task requires a capability that is not currently available.",
|
|
2312
|
+
],
|
|
2313
|
+
parameters: Type.Object({
|
|
2314
|
+
query: Type.String({ description: "Capability or task to search for" }),
|
|
2315
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 10 })),
|
|
2316
|
+
}),
|
|
2317
|
+
async execute(_toolCallId, params) {
|
|
2318
|
+
const terms = params.query.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
2319
|
+
const matches = pi.getAllTools()
|
|
2320
|
+
.filter((tool) => SEARCHABLE_TOOL_NAMES.has(tool.name))
|
|
2321
|
+
.map((tool) => ({
|
|
2322
|
+
tool,
|
|
2323
|
+
score: terms.reduce(
|
|
2324
|
+
(score, term) =>
|
|
2325
|
+
score + (`${tool.name} ${tool.description}`.toLowerCase().includes(term) ? 1 : 0),
|
|
2326
|
+
0,
|
|
2327
|
+
),
|
|
2328
|
+
}))
|
|
2329
|
+
.filter((match) => match.score > 0)
|
|
2330
|
+
.sort((a, b) => b.score - a.score)
|
|
2331
|
+
.slice(0, params.limit ?? 3)
|
|
2332
|
+
.map((match) => match.tool.name);
|
|
2333
|
+
|
|
2334
|
+
if (matches.length === 0) {
|
|
2335
|
+
return {
|
|
2336
|
+
content: [{ type: "text", text: `No tools found for: ${params.query}` }],
|
|
2337
|
+
details: { matches: [] },
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
const active = pi.getActiveTools();
|
|
2342
|
+
const added = matches.filter((name) => !active.includes(name));
|
|
2343
|
+
pi.setActiveTools([...new Set([...active, ...added])]);
|
|
2344
|
+
|
|
2345
|
+
return {
|
|
2346
|
+
content: [{
|
|
2347
|
+
type: "text",
|
|
2348
|
+
text: added.length > 0
|
|
2349
|
+
? `Loaded tools: ${added.join(", ")}`
|
|
2350
|
+
: `Matching tools already active: ${matches.join(", ")}`,
|
|
2351
|
+
}],
|
|
2352
|
+
details: { matches, added },
|
|
2353
|
+
};
|
|
2354
|
+
},
|
|
2355
|
+
});
|
|
2356
|
+
|
|
2357
|
+
pi.on("session_start", () => {
|
|
2358
|
+
// Keep searchable tools registered but initially inactive. Preserve built-ins
|
|
2359
|
+
// and tools owned by other extensions, and keep the loader itself active.
|
|
2360
|
+
const initialTools = pi.getActiveTools().filter(
|
|
2361
|
+
(name) => !SEARCHABLE_TOOL_NAMES.has(name),
|
|
2362
|
+
);
|
|
2363
|
+
pi.setActiveTools([...new Set([...initialTools, "search_tools"])]);
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
```
|
|
2367
|
+
|
|
2368
|
+
When `search_tools` adds a match, the model receives that definition on the immediately following request. On a native-capable model the definition is anchored after the search result without changing the initial tool-schema prefix. On other models it appears in the normal tool list on that same following request.
|
|
2369
|
+
|
|
2232
2370
|
## Custom UI
|
|
2233
2371
|
|
|
2234
2372
|
Extensions can interact with users via `ctx.ui` methods and customize how messages/tools render.
|
package/docs/keybindings.md
CHANGED
|
@@ -119,6 +119,7 @@ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, `ctrl+1
|
|
|
119
119
|
| Keybinding id | Default | Description |
|
|
120
120
|
|--------|---------|-------------|
|
|
121
121
|
| `app.tools.expand` | `ctrl+o` | Collapse or expand tool output |
|
|
122
|
+
| `app.message.copy` | `ctrl+x` | Copy the last assistant message, or the selected message in `/tree` |
|
|
122
123
|
| `app.message.followUp` | `alt+enter` | Queue follow-up message |
|
|
123
124
|
| `app.message.dequeue` | `alt+up` | Restore queued messages to editor |
|
|
124
125
|
|
package/docs/models.md
CHANGED
|
@@ -445,6 +445,8 @@ For providers with partial OpenAI compatibility, use the `compat` field.
|
|
|
445
445
|
| `thinkingFormat` | Use `reasoning_effort`, `openrouter`, `deepseek`, `together`, `zai`, `qwen`, `chat-template`, or `qwen-chat-template` thinking parameters |
|
|
446
446
|
| `chatTemplateKwargs` | `chat_template_kwargs` values for `thinkingFormat: "chat-template"`; use `{ "$var": "thinking.enabled" }` or `{ "$var": "thinking.effort" }` for pi-controlled thinking values |
|
|
447
447
|
| `cacheControlFormat` | Use Anthropic-style `cache_control` markers on the system prompt, last tool definition, and last user/assistant text content. Currently only `anthropic` is supported. |
|
|
448
|
+
| `sendSessionAffinityHeaders` | For `openai-completions`, send session-affinity headers from the session id when caching is enabled. Default: `false`. |
|
|
449
|
+
| `sessionAffinityFormat` | For `openai-completions` and `openai-responses`, the session-affinity header format: `openai` sends `session_id`/`x-client-request-id` (completions also `x-session-affinity`), `openai-nosession` omits the underscore-containing `session_id` header, `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param. Default: auto-detected. |
|
|
448
450
|
| `supportsStrictMode` | Include the `strict` field in tool definitions |
|
|
449
451
|
| `supportsLongCacheRetention` | Whether the provider accepts long cache retention when cache retention is `long`: `prompt_cache_retention: "24h"` for OpenAI prompt caching, or `cache_control.ttl: "1h"` when `cacheControlFormat` is `anthropic`. Default: `true`. |
|
|
450
452
|
| `openRouterRouting` | OpenRouter provider routing preferences. This object is sent as-is in the `provider` field of the [OpenRouter API request](https://openrouter.ai/docs/guides/routing/provider-selection). |
|
package/docs/providers.md
CHANGED
|
@@ -55,6 +55,7 @@ pi
|
|
|
55
55
|
| DeepSeek | `DEEPSEEK_API_KEY` | `deepseek` |
|
|
56
56
|
| NVIDIA NIM | `NVIDIA_API_KEY` | `nvidia` |
|
|
57
57
|
| Google Gemini | `GEMINI_API_KEY` | `google` |
|
|
58
|
+
| Amazon Bedrock | `AWS_BEARER_TOKEN_BEDROCK` | `amazon-bedrock` |
|
|
58
59
|
| Mistral | `MISTRAL_API_KEY` | `mistral` |
|
|
59
60
|
| Groq | `GROQ_API_KEY` | `groq` |
|
|
60
61
|
| Cerebras | `CEREBRAS_API_KEY` | `cerebras` |
|
|
@@ -170,6 +171,8 @@ export AZURE_OPENAI_DEPLOYMENT_NAME_MAP=gpt-4=my-gpt4,gpt-4o=my-gpt4o
|
|
|
170
171
|
|
|
171
172
|
### Amazon Bedrock
|
|
172
173
|
|
|
174
|
+
Use `/login amazon-bedrock` to store a Bedrock API key, or configure one of the ambient AWS credential sources below:
|
|
175
|
+
|
|
173
176
|
```bash
|
|
174
177
|
# Option 1: AWS Profile
|
|
175
178
|
export AWS_PROFILE=your-profile
|
package/docs/quickstart.md
CHANGED
|
@@ -113,7 +113,7 @@ pi @README.md "Summarize this"
|
|
|
113
113
|
pi @src/app.ts @src/app.test.ts "Review these together"
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
Images can be pasted with Ctrl+V (Alt+V on Windows)
|
|
116
|
+
Images or text can be pasted with Ctrl+V (Alt+V on Windows); images can also be dragged into supported terminals.
|
|
117
117
|
|
|
118
118
|
### Run shell commands
|
|
119
119
|
|
package/docs/usage.md
CHANGED
|
@@ -22,6 +22,7 @@ The editor can be replaced temporarily by built-in UI such as `/settings` or by
|
|
|
22
22
|
| File reference | Type `@` to fuzzy-search project files |
|
|
23
23
|
| Path completion | Press Tab to complete paths |
|
|
24
24
|
| Multi-line input | Shift+Enter, or Ctrl+Enter on Windows Terminal |
|
|
25
|
+
| Copy response | Ctrl+X copies the last assistant message; in `/tree`, it copies the selected message |
|
|
25
26
|
| Images | Paste with Ctrl+V, Alt+V on Windows, or drag into the terminal |
|
|
26
27
|
| Shell command | `!command` runs and sends output to the model |
|
|
27
28
|
| Hidden shell command | `!!command` runs without sending output to the model |
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "0.80.
|
|
9
|
+
"version": "0.80.7",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-gondolin",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-gondolin",
|
|
9
|
-
"version": "0.80.
|
|
9
|
+
"version": "0.80.7",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@earendil-works/gondolin": "0.12.0"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-sandbox",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-sandbox",
|
|
9
|
-
"version": "1.10.
|
|
9
|
+
"version": "1.10.7",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sandbox-runtime": "^0.0.26"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-with-deps",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-with-deps",
|
|
9
|
-
"version": "0.80.
|
|
9
|
+
"version": "0.80.7",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"ms": "^2.1.3"
|
|
12
12
|
},
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-coding-agent",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@earendil-works/pi-coding-agent",
|
|
9
|
-
"version": "0.80.
|
|
9
|
+
"version": "0.80.7",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@earendil-works/pi-agent-core": "^0.80.
|
|
13
|
-
"@earendil-works/pi-ai": "^0.80.
|
|
14
|
-
"@earendil-works/pi-tui": "^0.80.
|
|
12
|
+
"@earendil-works/pi-agent-core": "^0.80.7",
|
|
13
|
+
"@earendil-works/pi-ai": "^0.80.7",
|
|
14
|
+
"@earendil-works/pi-tui": "^0.80.7",
|
|
15
15
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
16
16
|
"chalk": "5.6.2",
|
|
17
17
|
"cross-spawn": "7.0.6",
|
|
@@ -474,11 +474,11 @@
|
|
|
474
474
|
}
|
|
475
475
|
},
|
|
476
476
|
"node_modules/@earendil-works/pi-agent-core": {
|
|
477
|
-
"version": "0.80.
|
|
478
|
-
"resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.80.
|
|
477
|
+
"version": "0.80.7",
|
|
478
|
+
"resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.80.7.tgz",
|
|
479
479
|
"license": "MIT",
|
|
480
480
|
"dependencies": {
|
|
481
|
-
"@earendil-works/pi-ai": "^0.80.
|
|
481
|
+
"@earendil-works/pi-ai": "^0.80.7",
|
|
482
482
|
"ignore": "7.0.5",
|
|
483
483
|
"typebox": "1.1.38",
|
|
484
484
|
"yaml": "2.9.0"
|
|
@@ -488,8 +488,8 @@
|
|
|
488
488
|
}
|
|
489
489
|
},
|
|
490
490
|
"node_modules/@earendil-works/pi-ai": {
|
|
491
|
-
"version": "0.80.
|
|
492
|
-
"resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.80.
|
|
491
|
+
"version": "0.80.7",
|
|
492
|
+
"resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.80.7.tgz",
|
|
493
493
|
"license": "MIT",
|
|
494
494
|
"dependencies": {
|
|
495
495
|
"@anthropic-ai/sdk": "0.91.1",
|
|
@@ -512,8 +512,8 @@
|
|
|
512
512
|
}
|
|
513
513
|
},
|
|
514
514
|
"node_modules/@earendil-works/pi-tui": {
|
|
515
|
-
"version": "0.80.
|
|
516
|
-
"resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.80.
|
|
515
|
+
"version": "0.80.7",
|
|
516
|
+
"resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.80.7.tgz",
|
|
517
517
|
"license": "MIT",
|
|
518
518
|
"dependencies": {
|
|
519
519
|
"get-east-asian-width": "1.6.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-coding-agent",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.7",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@earendil-works/pi-agent-core": "^0.80.
|
|
43
|
-
"@earendil-works/pi-ai": "^0.80.
|
|
44
|
-
"@earendil-works/pi-tui": "^0.80.
|
|
42
|
+
"@earendil-works/pi-agent-core": "^0.80.7",
|
|
43
|
+
"@earendil-works/pi-ai": "^0.80.7",
|
|
44
|
+
"@earendil-works/pi-tui": "^0.80.7",
|
|
45
45
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
46
46
|
"chalk": "5.6.2",
|
|
47
47
|
"cross-spawn": "7.0.6",
|