@earendil-works/pi-coding-agent 0.81.0 → 0.82.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 +59 -0
- package/README.md +13 -0
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session.d.ts +33 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +37 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +5 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +5 -7
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +13 -4
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +29 -17
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +4 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +5 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-config.d.ts +30 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +6 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -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 +7 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +0 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +3 -5
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +5 -10
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -3
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +1 -2
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -46
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +2 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +58 -46
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +3 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +5 -2
- package/docs/environment-variables.md +88 -0
- package/docs/extensions.md +11 -3
- package/docs/index.md +1 -0
- package/docs/json.md +5 -1
- package/docs/models.md +6 -2
- package/docs/providers.md +8 -1
- package/docs/rpc.md +56 -6
- package/docs/sdk.md +3 -0
- package/docs/settings.md +1 -1
- package/docs/usage.md +0 -13
- package/examples/extensions/custom-compaction.ts +3 -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/handoff.ts +9 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +3 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +16 -15
- package/package.json +5 -4
|
@@ -64,6 +64,7 @@ import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
|
64
64
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
65
65
|
import { UserMessageComponent } from "./components/user-message.js";
|
|
66
66
|
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
|
67
|
+
import { editInExternalEditor } from "./external-editor.js";
|
|
67
68
|
import { getModelSearchText } from "./model-search.js";
|
|
68
69
|
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
|
|
69
70
|
import { InteractiveThemeController } from "./theme/theme-controller.js";
|
|
@@ -272,7 +273,7 @@ export class InteractiveMode {
|
|
|
272
273
|
await this.rebindCurrentSession({ renderBeforeBind: true });
|
|
273
274
|
});
|
|
274
275
|
this.version = VERSION;
|
|
275
|
-
this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor());
|
|
276
|
+
this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor(), getAgentDir());
|
|
276
277
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
277
278
|
this.headerContainer = new Container();
|
|
278
279
|
this.loadedResourcesContainer = new Container();
|
|
@@ -580,6 +581,12 @@ export class InteractiveMode {
|
|
|
580
581
|
*/
|
|
581
582
|
async run() {
|
|
582
583
|
await this.init();
|
|
584
|
+
if (!process.env.PI_OFFLINE) {
|
|
585
|
+
void this.session.modelRuntime
|
|
586
|
+
.refresh()
|
|
587
|
+
.then(() => this.updateAvailableProviderCount())
|
|
588
|
+
.catch(() => { });
|
|
589
|
+
}
|
|
583
590
|
// Start version check asynchronously
|
|
584
591
|
checkForNewPiVersion(this.version).then((newRelease) => {
|
|
585
592
|
if (newRelease) {
|
|
@@ -791,8 +798,15 @@ export class InteractiveMode {
|
|
|
791
798
|
* Get a short path relative to the package root for display.
|
|
792
799
|
*/
|
|
793
800
|
getShortPath(fullPath, sourceInfo) {
|
|
801
|
+
const normalizedFullPath = fullPath.replace(/\\/g, "/");
|
|
794
802
|
const baseDir = sourceInfo?.baseDir;
|
|
795
803
|
if (baseDir && this.isPackageSource(sourceInfo)) {
|
|
804
|
+
const normalizedBaseDir = baseDir.replace(/\\/g, "/");
|
|
805
|
+
const npmRootMatch = normalizedBaseDir.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);
|
|
806
|
+
// If fullPath is under the same node_modules root as baseDir, preserve that relative topology.
|
|
807
|
+
if (npmRootMatch?.[1] && normalizedFullPath.startsWith(`${npmRootMatch[1]}/`)) {
|
|
808
|
+
return path.posix.relative(normalizedBaseDir, normalizedFullPath);
|
|
809
|
+
}
|
|
796
810
|
const relativePath = path.relative(path.resolve(baseDir), path.resolve(fullPath));
|
|
797
811
|
if (relativePath &&
|
|
798
812
|
relativePath !== "." &&
|
|
@@ -803,11 +817,11 @@ export class InteractiveMode {
|
|
|
803
817
|
}
|
|
804
818
|
}
|
|
805
819
|
const source = sourceInfo?.source ?? "";
|
|
806
|
-
const npmMatch =
|
|
820
|
+
const npmMatch = normalizedFullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
|
|
807
821
|
if (npmMatch && source.startsWith("npm:")) {
|
|
808
822
|
return npmMatch[2];
|
|
809
823
|
}
|
|
810
|
-
const gitMatch =
|
|
824
|
+
const gitMatch = normalizedFullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
|
|
811
825
|
if (gitMatch && source.startsWith("git:")) {
|
|
812
826
|
return gitMatch[1];
|
|
813
827
|
}
|
|
@@ -1347,6 +1361,7 @@ export class InteractiveMode {
|
|
|
1347
1361
|
sessionManager: this.sessionManager,
|
|
1348
1362
|
modelRegistry: extensionRunner.getModelRegistry(),
|
|
1349
1363
|
model: this.session.model,
|
|
1364
|
+
thinkingLevel: this.session.thinkingLevel,
|
|
1350
1365
|
isIdle: () => this.session.isIdle,
|
|
1351
1366
|
isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
|
|
1352
1367
|
signal: this.session.agent.signal,
|
|
@@ -2032,7 +2047,7 @@ export class InteractiveMode {
|
|
|
2032
2047
|
this.defaultEditor.onAction("app.model.select", () => this.showModelSelector());
|
|
2033
2048
|
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
2034
2049
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
2035
|
-
this.defaultEditor.onAction("app.editor.external", () => this.
|
|
2050
|
+
this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
|
|
2036
2051
|
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
|
|
2037
2052
|
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
2038
2053
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
@@ -2394,6 +2409,9 @@ export class InteractiveMode {
|
|
|
2394
2409
|
}
|
|
2395
2410
|
this.ui.requestRender();
|
|
2396
2411
|
break;
|
|
2412
|
+
case "bash_execution_update":
|
|
2413
|
+
// The bash execution callback handles TUI output rendering.
|
|
2414
|
+
break;
|
|
2397
2415
|
case "tool_execution_start": {
|
|
2398
2416
|
let component = this.pendingTools.get(event.toolCallId);
|
|
2399
2417
|
if (!component) {
|
|
@@ -2515,6 +2533,28 @@ export class InteractiveMode {
|
|
|
2515
2533
|
this.ui.requestRender();
|
|
2516
2534
|
break;
|
|
2517
2535
|
}
|
|
2536
|
+
case "summarization_retry_scheduled": {
|
|
2537
|
+
this.showError(event.errorMessage);
|
|
2538
|
+
this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
|
|
2539
|
+
this.ui.requestRender();
|
|
2540
|
+
break;
|
|
2541
|
+
}
|
|
2542
|
+
case "summarization_retry_attempt_start": {
|
|
2543
|
+
this.clearStatusIndicator("retry");
|
|
2544
|
+
if (event.source === "branchSummary") {
|
|
2545
|
+
this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
|
|
2546
|
+
}
|
|
2547
|
+
else {
|
|
2548
|
+
this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
|
|
2549
|
+
}
|
|
2550
|
+
this.ui.requestRender();
|
|
2551
|
+
break;
|
|
2552
|
+
}
|
|
2553
|
+
case "summarization_retry_finished": {
|
|
2554
|
+
this.clearStatusIndicator("retry");
|
|
2555
|
+
this.ui.requestRender();
|
|
2556
|
+
break;
|
|
2557
|
+
}
|
|
2518
2558
|
}
|
|
2519
2559
|
}
|
|
2520
2560
|
/** Extract text content from a user message */
|
|
@@ -3094,51 +3134,21 @@ export class InteractiveMode {
|
|
|
3094
3134
|
}
|
|
3095
3135
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
|
3096
3136
|
}
|
|
3097
|
-
async
|
|
3137
|
+
async handleOpenExternalEditor() {
|
|
3098
3138
|
const editorCmd = this.settingsManager.getExternalEditorCommand();
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
return;
|
|
3102
|
-
}
|
|
3103
|
-
const currentText = this.editor.getExpandedText?.() ?? this.editor.getText();
|
|
3104
|
-
const tmpFile = path.join(os.tmpdir(), `pi-editor-${Date.now()}.pi.md`);
|
|
3139
|
+
const content = this.editor.getExpandedText?.() ?? this.editor.getText();
|
|
3140
|
+
this.ui.stop();
|
|
3105
3141
|
try {
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
this.ui.stop();
|
|
3110
|
-
// Split by space to support editor arguments (e.g., "code --wait")
|
|
3111
|
-
const [editor, ...editorArgs] = editorCmd.split(" ");
|
|
3112
|
-
process.stdout.write(`Launching external editor: ${editorCmd}\nPi will resume when the editor exits.\n`);
|
|
3113
|
-
// Do not use spawnSync here. On Windows, synchronous child_process calls can keep
|
|
3114
|
-
// Node/libuv's console input read active after ui.stop() pauses stdin, racing
|
|
3115
|
-
// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.
|
|
3116
|
-
const status = await new Promise((resolve) => {
|
|
3117
|
-
const child = spawn(editor, [...editorArgs, tmpFile], {
|
|
3118
|
-
stdio: "inherit",
|
|
3119
|
-
shell: process.platform === "win32",
|
|
3120
|
-
});
|
|
3121
|
-
child.on("error", () => resolve(null));
|
|
3122
|
-
child.on("close", (code) => resolve(code));
|
|
3142
|
+
const result = await editInExternalEditor({
|
|
3143
|
+
command: editorCmd,
|
|
3144
|
+
content,
|
|
3123
3145
|
});
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
|
3127
|
-
this.editor.setText(newContent);
|
|
3146
|
+
if (result.status === "complete") {
|
|
3147
|
+
this.editor.setText(result.content);
|
|
3128
3148
|
}
|
|
3129
|
-
// On non-zero exit, keep original text (no action needed)
|
|
3130
3149
|
}
|
|
3131
3150
|
finally {
|
|
3132
|
-
// Clean up temp file
|
|
3133
|
-
try {
|
|
3134
|
-
fs.unlinkSync(tmpFile);
|
|
3135
|
-
}
|
|
3136
|
-
catch {
|
|
3137
|
-
// Ignore cleanup errors
|
|
3138
|
-
}
|
|
3139
|
-
// Restart TUI
|
|
3140
3151
|
this.ui.start();
|
|
3141
|
-
// Force full re-render since external editor uses alternate screen
|
|
3142
3152
|
this.ui.requestRender(true);
|
|
3143
3153
|
}
|
|
3144
3154
|
}
|
|
@@ -3593,10 +3603,12 @@ export class InteractiveMode {
|
|
|
3593
3603
|
return [];
|
|
3594
3604
|
}
|
|
3595
3605
|
}
|
|
3596
|
-
/** Update the footer's available provider count from current
|
|
3597
|
-
|
|
3598
|
-
const models =
|
|
3599
|
-
|
|
3606
|
+
/** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
|
|
3607
|
+
updateAvailableProviderCount() {
|
|
3608
|
+
const models = this.session.scopedModels.length > 0
|
|
3609
|
+
? this.session.scopedModels.map((scoped) => scoped.model)
|
|
3610
|
+
: this.session.modelRuntime.getAvailableSnapshot();
|
|
3611
|
+
const uniqueProviders = new Set(models.map((model) => model.provider));
|
|
3600
3612
|
this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size);
|
|
3601
3613
|
}
|
|
3602
3614
|
async maybeWarnAboutAnthropicSubscriptionAuth(model = this.session.model) {
|