@earendil-works/pi-coding-agent 0.74.0 → 0.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +9 -7
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -16
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +32 -17
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +3 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +25 -15
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -0
- 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 +5 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +81 -26
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +6 -4
- package/dist/core/prompt-templates.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/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +39 -9
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +2 -5
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +0 -10
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +23 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +6 -1
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +5 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +19 -5
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +3 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +2 -1
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +12 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +67 -27
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +3 -1
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +59 -16
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +16 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +80 -8
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/custom-provider.md +58 -3
- package/docs/extensions.md +1 -1
- package/docs/index.md +7 -1
- package/docs/models.md +2 -2
- package/docs/packages.md +2 -2
- package/docs/providers.md +2 -0
- package/docs/sdk.md +24 -44
- package/docs/settings.md +1 -3
- package/docs/skills.md +3 -4
- package/docs/termux.md +3 -3
- package/docs/themes.md +2 -2
- 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/dynamic-resources/dynamic.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/examples/sdk/01-minimal.ts +14 -10
- package/examples/sdk/02-custom-model.ts +12 -8
- package/examples/sdk/03-custom-prompt.ts +24 -16
- package/examples/sdk/04-skills.ts +2 -2
- package/examples/sdk/05-tools.ts +8 -4
- package/examples/sdk/06-extensions.ts +11 -7
- package/examples/sdk/07-context-files.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +2 -2
- package/examples/sdk/09-api-keys-and-oauth.ts +8 -4
- package/examples/sdk/10-settings.ts +4 -4
- package/examples/sdk/11-sessions.ts +4 -0
- package/examples/sdk/12-full-control.ts +11 -7
- package/examples/sdk/README.md +5 -8
- package/package.json +8 -13
|
@@ -7,7 +7,7 @@ import * as fs from "node:fs";
|
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
9
|
import { getProviders, } from "@earendil-works/pi-ai";
|
|
10
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
|
|
10
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
|
|
11
11
|
import { spawn, spawnSync } from "child_process";
|
|
12
12
|
import { APP_NAME, APP_TITLE, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
|
|
13
13
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
@@ -26,6 +26,7 @@ import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/cha
|
|
|
26
26
|
import { copyToClipboard } from "../../utils/clipboard.js";
|
|
27
27
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
28
28
|
import { parseGitUrl } from "../../utils/git.js";
|
|
29
|
+
import { getCwdRelativePath } from "../../utils/paths.js";
|
|
29
30
|
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
30
31
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
31
32
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
@@ -46,7 +47,7 @@ import { ExtensionEditorComponent } from "./components/extension-editor.js";
|
|
|
46
47
|
import { ExtensionInputComponent } from "./components/extension-input.js";
|
|
47
48
|
import { ExtensionSelectorComponent } from "./components/extension-selector.js";
|
|
48
49
|
import { FooterComponent } from "./components/footer.js";
|
|
49
|
-
import { keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
|
|
50
|
+
import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
|
|
50
51
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
51
52
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
52
53
|
import { OAuthSelectorComponent } from "./components/oauth-selector.js";
|
|
@@ -388,6 +389,19 @@ export class InteractiveMode {
|
|
|
388
389
|
// Both are needed: fd for autocomplete, rg for grep tool and bash commands
|
|
389
390
|
const [fdPath] = await Promise.all([ensureTool("fd"), ensureTool("rg")]);
|
|
390
391
|
this.fdPath = fdPath;
|
|
392
|
+
if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
|
|
393
|
+
const modelList = this.session.scopedModels
|
|
394
|
+
.map((sm) => {
|
|
395
|
+
const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
|
|
396
|
+
return `${sm.model.id}${thinkingStr}`;
|
|
397
|
+
})
|
|
398
|
+
.join(", ");
|
|
399
|
+
const cycleKeys = this.keybindings.getKeys("app.model.cycleForward");
|
|
400
|
+
const cycleHint = cycleKeys.length > 0
|
|
401
|
+
? theme.fg("muted", ` (${formatKeyText(cycleKeys.join("/"), { capitalize: true })} to cycle)`)
|
|
402
|
+
: "";
|
|
403
|
+
console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
|
|
404
|
+
}
|
|
391
405
|
// Add header container as first child
|
|
392
406
|
this.ui.addChild(this.headerContainer);
|
|
393
407
|
// Add header with keybindings from config (unless silenced)
|
|
@@ -676,13 +690,9 @@ export class InteractiveMode {
|
|
|
676
690
|
formatContextPath(p) {
|
|
677
691
|
const cwd = path.resolve(this.sessionManager.getCwd());
|
|
678
692
|
const absolutePath = path.isAbsolute(p) ? path.resolve(p) : path.resolve(cwd, p);
|
|
679
|
-
const relativePath =
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
!relativePath.startsWith(`..${path.sep}`) &&
|
|
683
|
-
!path.isAbsolute(relativePath));
|
|
684
|
-
if (isInsideCwd) {
|
|
685
|
-
return relativePath || ".";
|
|
693
|
+
const relativePath = getCwdRelativePath(absolutePath, cwd);
|
|
694
|
+
if (relativePath !== undefined) {
|
|
695
|
+
return relativePath;
|
|
686
696
|
}
|
|
687
697
|
return this.formatDisplayPath(absolutePath);
|
|
688
698
|
}
|
|
@@ -1591,7 +1601,7 @@ export class InteractiveMode {
|
|
|
1591
1601
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
1592
1602
|
this.hideExtensionSelector();
|
|
1593
1603
|
resolve(undefined);
|
|
1594
|
-
}, { tui: this.ui, timeout: opts?.timeout });
|
|
1604
|
+
}, { tui: this.ui, timeout: opts?.timeout, onToggleToolsExpanded: () => this.toggleToolOutputExpansion() });
|
|
1595
1605
|
this.editorContainer.clear();
|
|
1596
1606
|
this.editorContainer.addChild(this.extensionSelector);
|
|
1597
1607
|
this.ui.setFocus(this.extensionSelector);
|
|
@@ -2646,6 +2656,38 @@ export class InteractiveMode {
|
|
|
2646
2656
|
// extension cleanup can write restore sequences and re-trigger EIO.
|
|
2647
2657
|
process.exit(129);
|
|
2648
2658
|
}
|
|
2659
|
+
/**
|
|
2660
|
+
* Last-resort handler for uncaught exceptions. The TUI puts stdin into raw
|
|
2661
|
+
* mode and hides the cursor; without this handler, an uncaught throw from
|
|
2662
|
+
* anywhere (e.g. an extension's async `ChildProcess.on("exit")` callback)
|
|
2663
|
+
* tears down the process while leaving the terminal in raw mode with no
|
|
2664
|
+
* cursor, requiring `stty sane && reset` to recover.
|
|
2665
|
+
*
|
|
2666
|
+
* Unlike emergencyTerminalExit, the terminal is still alive here, so we
|
|
2667
|
+
* call ui.stop() to restore cooked mode, the cursor, and disable bracketed
|
|
2668
|
+
* paste / Kitty / modifyOtherKeys sequences.
|
|
2669
|
+
*/
|
|
2670
|
+
uncaughtCrash(error) {
|
|
2671
|
+
if (this.isShuttingDown) {
|
|
2672
|
+
process.exit(1);
|
|
2673
|
+
}
|
|
2674
|
+
this.isShuttingDown = true;
|
|
2675
|
+
try {
|
|
2676
|
+
this.unregisterSignalHandlers();
|
|
2677
|
+
}
|
|
2678
|
+
catch { }
|
|
2679
|
+
try {
|
|
2680
|
+
killTrackedDetachedChildren();
|
|
2681
|
+
}
|
|
2682
|
+
catch { }
|
|
2683
|
+
try {
|
|
2684
|
+
this.ui.stop();
|
|
2685
|
+
}
|
|
2686
|
+
catch { }
|
|
2687
|
+
console.error("pi exiting due to uncaughtException:");
|
|
2688
|
+
console.error(error);
|
|
2689
|
+
process.exit(1);
|
|
2690
|
+
}
|
|
2649
2691
|
/**
|
|
2650
2692
|
* Check if shutdown was requested and perform shutdown if so.
|
|
2651
2693
|
*/
|
|
@@ -2681,6 +2723,12 @@ export class InteractiveMode {
|
|
|
2681
2723
|
process.stderr.on("error", terminalErrorHandler);
|
|
2682
2724
|
this.signalCleanupHandlers.push(() => process.stdout.off("error", terminalErrorHandler));
|
|
2683
2725
|
this.signalCleanupHandlers.push(() => process.stderr.off("error", terminalErrorHandler));
|
|
2726
|
+
// Restore the terminal before the process dies on any uncaught throw.
|
|
2727
|
+
// Without this, an unhandled exception from extension code (or anywhere
|
|
2728
|
+
// in pi) leaves the terminal in raw mode with no cursor.
|
|
2729
|
+
const uncaughtExceptionHandler = (error) => this.uncaughtCrash(error);
|
|
2730
|
+
process.prependListener("uncaughtException", uncaughtExceptionHandler);
|
|
2731
|
+
this.signalCleanupHandlers.push(() => process.off("uncaughtException", uncaughtExceptionHandler));
|
|
2684
2732
|
}
|
|
2685
2733
|
unregisterSignalHandlers() {
|
|
2686
2734
|
for (const cleanup of this.signalCleanupHandlers) {
|
|
@@ -2882,6 +2930,7 @@ export class InteractiveMode {
|
|
|
2882
2930
|
showError(errorMessage) {
|
|
2883
2931
|
this.chatContainer.addChild(new Spacer(1));
|
|
2884
2932
|
this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), 1, 0));
|
|
2933
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
2885
2934
|
this.ui.requestRender();
|
|
2886
2935
|
}
|
|
2887
2936
|
showWarning(warningMessage) {
|
|
@@ -2892,8 +2941,11 @@ export class InteractiveMode {
|
|
|
2892
2941
|
showNewVersionNotification(newVersion) {
|
|
2893
2942
|
const action = theme.fg("accent", `${APP_NAME} update`);
|
|
2894
2943
|
const updateInstruction = theme.fg("muted", `New version ${newVersion} is available. Run `) + action;
|
|
2895
|
-
const changelogUrl =
|
|
2896
|
-
const
|
|
2944
|
+
const changelogUrl = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md";
|
|
2945
|
+
const changelogLink = getCapabilities().hyperlinks
|
|
2946
|
+
? hyperlink(theme.fg("accent", "open changelog"), changelogUrl)
|
|
2947
|
+
: theme.fg("accent", changelogUrl);
|
|
2948
|
+
const changelogLine = theme.fg("muted", "Changelog: ") + changelogLink;
|
|
2897
2949
|
this.chatContainer.addChild(new Spacer(1));
|
|
2898
2950
|
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
2899
2951
|
this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction}\n${changelogLine}`, 1, 0));
|
|
@@ -4277,29 +4329,17 @@ export class InteractiveMode {
|
|
|
4277
4329
|
this.chatContainer.addChild(new DynamicBorder());
|
|
4278
4330
|
this.ui.requestRender();
|
|
4279
4331
|
}
|
|
4280
|
-
/**
|
|
4281
|
-
* Capitalize keybinding for display (e.g., "ctrl+c" -> "Ctrl+C").
|
|
4282
|
-
*/
|
|
4283
|
-
capitalizeKey(key) {
|
|
4284
|
-
return key
|
|
4285
|
-
.split("/")
|
|
4286
|
-
.map((k) => k
|
|
4287
|
-
.split("+")
|
|
4288
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
4289
|
-
.join("+"))
|
|
4290
|
-
.join("/");
|
|
4291
|
-
}
|
|
4292
4332
|
/**
|
|
4293
4333
|
* Get capitalized display string for an app keybinding action.
|
|
4294
4334
|
*/
|
|
4295
4335
|
getAppKeyDisplay(action) {
|
|
4296
|
-
return
|
|
4336
|
+
return keyDisplayText(action);
|
|
4297
4337
|
}
|
|
4298
4338
|
/**
|
|
4299
4339
|
* Get capitalized display string for an editor keybinding action.
|
|
4300
4340
|
*/
|
|
4301
4341
|
getEditorKeyDisplay(action) {
|
|
4302
|
-
return
|
|
4342
|
+
return keyDisplayText(action);
|
|
4303
4343
|
}
|
|
4304
4344
|
handleHotkeysCommand() {
|
|
4305
4345
|
// Navigation keybindings
|
|
@@ -4398,7 +4438,7 @@ export class InteractiveMode {
|
|
|
4398
4438
|
`;
|
|
4399
4439
|
for (const [key, shortcut] of shortcuts) {
|
|
4400
4440
|
const description = shortcut.description ?? shortcut.extensionPath;
|
|
4401
|
-
const keyDisplay = key
|
|
4441
|
+
const keyDisplay = formatKeyText(key, { capitalize: true });
|
|
4402
4442
|
hotkeys += `| \`${keyDisplay}\` | ${description} |\n`;
|
|
4403
4443
|
}
|
|
4404
4444
|
}
|