@earendil-works/pi-coding-agent 0.74.0 → 0.74.2
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 +48 -0
- package/README.md +8 -6
- 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/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -20
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- 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.map +1 -1
- package/dist/core/compaction/compaction.js +2 -2
- 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 +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +45 -7
- 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/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 +74 -30
- 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/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +6 -1
- package/dist/package-manager-cli.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/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +14 -0
- package/dist/utils/version-check.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/providers.md +2 -0
- package/docs/sdk.md +24 -44
- 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 +6 -11
|
@@ -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,10 +26,11 @@ 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";
|
|
32
|
-
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
33
|
+
import { checkForNewPiVersion, getLatestPiNodeRequirementMessage, isCurrentNodeVersionSupportedByLatestPi, } from "../../utils/version-check.js";
|
|
33
34
|
import { ArminComponent } from "./components/armin.js";
|
|
34
35
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
35
36
|
import { BashExecutionComponent } from "./components/bash-execution.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) {
|
|
@@ -2890,13 +2939,20 @@ export class InteractiveMode {
|
|
|
2890
2939
|
this.ui.requestRender();
|
|
2891
2940
|
}
|
|
2892
2941
|
showNewVersionNotification(newVersion) {
|
|
2942
|
+
const nodeVersionSupported = isCurrentNodeVersionSupportedByLatestPi();
|
|
2893
2943
|
const action = theme.fg("accent", `${APP_NAME} update`);
|
|
2894
|
-
const updateInstruction =
|
|
2895
|
-
|
|
2896
|
-
|
|
2944
|
+
const updateInstruction = nodeVersionSupported
|
|
2945
|
+
? theme.fg("muted", `New version ${newVersion} is available. Run `) + action
|
|
2946
|
+
: theme.fg("muted", `New version ${newVersion} is available. ${getLatestPiNodeRequirementMessage(`${APP_NAME} update`)}`);
|
|
2947
|
+
const changelogUrl = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md";
|
|
2948
|
+
const changelogLink = getCapabilities().hyperlinks
|
|
2949
|
+
? hyperlink(theme.fg("accent", "open changelog"), changelogUrl)
|
|
2950
|
+
: theme.fg("accent", changelogUrl);
|
|
2951
|
+
const changelogLine = theme.fg("muted", "Changelog: ") + changelogLink;
|
|
2897
2952
|
this.chatContainer.addChild(new Spacer(1));
|
|
2898
2953
|
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
2899
|
-
|
|
2954
|
+
const title = nodeVersionSupported ? "Update Available" : "Update Requires Newer Node";
|
|
2955
|
+
this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", title))}\n${updateInstruction}\n${changelogLine}`, 1, 0));
|
|
2900
2956
|
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
2901
2957
|
this.ui.requestRender();
|
|
2902
2958
|
}
|
|
@@ -4277,29 +4333,17 @@ export class InteractiveMode {
|
|
|
4277
4333
|
this.chatContainer.addChild(new DynamicBorder());
|
|
4278
4334
|
this.ui.requestRender();
|
|
4279
4335
|
}
|
|
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
4336
|
/**
|
|
4293
4337
|
* Get capitalized display string for an app keybinding action.
|
|
4294
4338
|
*/
|
|
4295
4339
|
getAppKeyDisplay(action) {
|
|
4296
|
-
return
|
|
4340
|
+
return keyDisplayText(action);
|
|
4297
4341
|
}
|
|
4298
4342
|
/**
|
|
4299
4343
|
* Get capitalized display string for an editor keybinding action.
|
|
4300
4344
|
*/
|
|
4301
4345
|
getEditorKeyDisplay(action) {
|
|
4302
|
-
return
|
|
4346
|
+
return keyDisplayText(action);
|
|
4303
4347
|
}
|
|
4304
4348
|
handleHotkeysCommand() {
|
|
4305
4349
|
// Navigation keybindings
|
|
@@ -4398,7 +4442,7 @@ export class InteractiveMode {
|
|
|
4398
4442
|
`;
|
|
4399
4443
|
for (const [key, shortcut] of shortcuts) {
|
|
4400
4444
|
const description = shortcut.description ?? shortcut.extensionPath;
|
|
4401
|
-
const keyDisplay = key
|
|
4445
|
+
const keyDisplay = formatKeyText(key, { capitalize: true });
|
|
4402
4446
|
hotkeys += `| \`${keyDisplay}\` | ${description} |\n`;
|
|
4403
4447
|
}
|
|
4404
4448
|
}
|