@mariozechner/pi-coding-agent 0.31.1 → 0.32.1
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 +54 -0
- package/README.md +56 -5
- package/dist/cli/file-processor.d.ts +5 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +28 -8
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/core/agent-session.d.ts +45 -17
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +93 -42
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +6 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +16 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/custom-tools/types.d.ts +1 -1
- package/dist/core/custom-tools/types.d.ts.map +1 -1
- package/dist/core/custom-tools/types.js.map +1 -1
- package/dist/core/hooks/loader.d.ts +4 -1
- package/dist/core/hooks/loader.d.ts.map +1 -1
- package/dist/core/hooks/loader.js +2 -2
- package/dist/core/hooks/loader.js.map +1 -1
- package/dist/core/hooks/runner.d.ts +2 -2
- package/dist/core/hooks/runner.d.ts.map +1 -1
- package/dist/core/hooks/runner.js +3 -3
- package/dist/core/hooks/runner.js.map +1 -1
- package/dist/core/hooks/types.d.ts +10 -4
- package/dist/core/hooks/types.d.ts.map +1 -1
- package/dist/core/hooks/types.js.map +1 -1
- package/dist/core/messages.d.ts +2 -0
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +4 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -2
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +85 -49
- 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/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +9 -6
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +17 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +41 -6
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/index.d.ts +9 -4
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +6 -6
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/read.d.ts +5 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +22 -5
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -5
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +6 -4
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +7 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/hook-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/hook-editor.js +3 -3
- package/dist/modes/interactive/components/hook-editor.js.map +1 -1
- package/dist/modes/interactive/components/hook-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/hook-input.js +3 -3
- package/dist/modes/interactive/components/hook-input.js.map +1 -1
- package/dist/modes/interactive/components/hook-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/hook-selector.js +3 -3
- package/dist/modes/interactive/components/hook-selector.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +3 -3
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -3
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +37 -6
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +7 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +74 -26
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -3
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +12 -4
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +18 -6
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +21 -12
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +25 -6
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/image-resize.d.ts +29 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +111 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/docs/hooks.md +16 -9
- package/examples/README.md +6 -0
- package/examples/custom-tools/README.md +2 -0
- package/examples/hooks/README.md +1 -0
- package/examples/hooks/file-trigger.ts +1 -1
- package/examples/hooks/todo/index.ts +134 -0
- package/package.json +6 -5
- package/dist/modes/interactive/components/queue-mode-selector.d.ts +0 -10
- package/dist/modes/interactive/components/queue-mode-selector.d.ts.map +0 -1
- package/dist/modes/interactive/components/queue-mode-selector.js +0 -42
- package/dist/modes/interactive/components/queue-mode-selector.js.map +0 -1
|
@@ -194,6 +194,9 @@ export class InteractiveMode {
|
|
|
194
194
|
theme.fg("dim", "!") +
|
|
195
195
|
theme.fg("muted", " to run bash") +
|
|
196
196
|
"\n" +
|
|
197
|
+
theme.fg("dim", "alt+enter") +
|
|
198
|
+
theme.fg("muted", " to queue follow-up") +
|
|
199
|
+
"\n" +
|
|
197
200
|
theme.fg("dim", "drop files") +
|
|
198
201
|
theme.fg("muted", " to attach");
|
|
199
202
|
const header = new Text(`${logo}\n${instructions}`, 1, 0);
|
|
@@ -230,6 +233,9 @@ export class InteractiveMode {
|
|
|
230
233
|
// Start the UI
|
|
231
234
|
this.ui.start();
|
|
232
235
|
this.isInitialized = true;
|
|
236
|
+
// Set terminal title
|
|
237
|
+
const cwdBasename = path.basename(process.cwd());
|
|
238
|
+
this.ui.terminal.setTitle(`pi - ${cwdBasename}`);
|
|
233
239
|
// Initialize hooks with TUI-based UI context
|
|
234
240
|
await this.initHooksAndCustomTools();
|
|
235
241
|
// Subscribe to agent events
|
|
@@ -312,10 +318,10 @@ export class InteractiveMode {
|
|
|
312
318
|
}
|
|
313
319
|
hookRunner.initialize({
|
|
314
320
|
getModel: () => this.session.model,
|
|
315
|
-
sendMessageHandler: (message,
|
|
321
|
+
sendMessageHandler: (message, options) => {
|
|
316
322
|
const wasStreaming = this.session.isStreaming;
|
|
317
323
|
this.session
|
|
318
|
-
.sendHookMessage(message,
|
|
324
|
+
.sendHookMessage(message, options)
|
|
319
325
|
.then(() => {
|
|
320
326
|
// For non-streaming cases with display=true, update UI
|
|
321
327
|
// (streaming cases update via message_end event)
|
|
@@ -388,7 +394,7 @@ export class InteractiveMode {
|
|
|
388
394
|
abort: () => {
|
|
389
395
|
this.session.abort();
|
|
390
396
|
},
|
|
391
|
-
|
|
397
|
+
hasPendingMessages: () => this.session.pendingMessageCount > 0,
|
|
392
398
|
uiContext,
|
|
393
399
|
hasUI: true,
|
|
394
400
|
});
|
|
@@ -420,7 +426,7 @@ export class InteractiveMode {
|
|
|
420
426
|
modelRegistry: this.session.modelRegistry,
|
|
421
427
|
model: this.session.model,
|
|
422
428
|
isIdle: () => !this.session.isStreaming,
|
|
423
|
-
|
|
429
|
+
hasPendingMessages: () => this.session.pendingMessageCount > 0,
|
|
424
430
|
abort: () => {
|
|
425
431
|
this.session.abort();
|
|
426
432
|
},
|
|
@@ -596,8 +602,9 @@ export class InteractiveMode {
|
|
|
596
602
|
this.editor.onEscape = () => {
|
|
597
603
|
if (this.loadingAnimation) {
|
|
598
604
|
// Abort and restore queued messages to editor
|
|
599
|
-
const
|
|
600
|
-
const
|
|
605
|
+
const { steering, followUp } = this.session.clearQueue();
|
|
606
|
+
const allQueued = [...steering, ...followUp];
|
|
607
|
+
const queuedText = allQueued.join("\n\n");
|
|
601
608
|
const currentText = this.editor.getText();
|
|
602
609
|
const combinedText = [queuedText, currentText].filter((t) => t.trim()).join("\n\n");
|
|
603
610
|
this.editor.setText(combinedText);
|
|
@@ -613,10 +620,15 @@ export class InteractiveMode {
|
|
|
613
620
|
this.updateEditorBorderColor();
|
|
614
621
|
}
|
|
615
622
|
else if (!this.editor.getText().trim()) {
|
|
616
|
-
// Double-escape with empty editor triggers /branch
|
|
623
|
+
// Double-escape with empty editor triggers /tree or /branch based on setting
|
|
617
624
|
const now = Date.now();
|
|
618
625
|
if (now - this.lastEscapeTime < 500) {
|
|
619
|
-
this.
|
|
626
|
+
if (this.settingsManager.getDoubleEscapeAction() === "tree") {
|
|
627
|
+
this.showTreeSelector();
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
this.showUserMessageSelector();
|
|
631
|
+
}
|
|
620
632
|
this.lastEscapeTime = 0;
|
|
621
633
|
}
|
|
622
634
|
else {
|
|
@@ -636,6 +648,7 @@ export class InteractiveMode {
|
|
|
636
648
|
this.editor.onCtrlO = () => this.toggleToolOutputExpansion();
|
|
637
649
|
this.editor.onCtrlT = () => this.toggleThinkingBlockVisibility();
|
|
638
650
|
this.editor.onCtrlG = () => this.openExternalEditor();
|
|
651
|
+
this.editor.onAltEnter = () => this.handleAltEnter();
|
|
639
652
|
this.editor.onChange = (text) => {
|
|
640
653
|
const wasBashMode = this.isBashMode;
|
|
641
654
|
this.isBashMode = text.trimStart().startsWith("!");
|
|
@@ -742,9 +755,10 @@ export class InteractiveMode {
|
|
|
742
755
|
this.editor.setText("");
|
|
743
756
|
return;
|
|
744
757
|
}
|
|
745
|
-
// Handle bash command
|
|
758
|
+
// Handle bash command (! for normal, !! for excluded from context)
|
|
746
759
|
if (text.startsWith("!")) {
|
|
747
|
-
const
|
|
760
|
+
const isExcluded = text.startsWith("!!");
|
|
761
|
+
const command = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
|
|
748
762
|
if (command) {
|
|
749
763
|
if (this.session.isBashRunning) {
|
|
750
764
|
this.showWarning("A bash command is already running. Press Esc to cancel it first.");
|
|
@@ -752,7 +766,7 @@ export class InteractiveMode {
|
|
|
752
766
|
return;
|
|
753
767
|
}
|
|
754
768
|
this.editor.addToHistory(text);
|
|
755
|
-
await this.handleBashCommand(command);
|
|
769
|
+
await this.handleBashCommand(command, isExcluded);
|
|
756
770
|
this.isBashMode = false;
|
|
757
771
|
this.updateEditorBorderColor();
|
|
758
772
|
return;
|
|
@@ -775,9 +789,9 @@ export class InteractiveMode {
|
|
|
775
789
|
return;
|
|
776
790
|
}
|
|
777
791
|
}
|
|
778
|
-
// Queue
|
|
792
|
+
// Queue steering message if agent is streaming (interrupts current work)
|
|
779
793
|
if (this.session.isStreaming) {
|
|
780
|
-
await this.session.
|
|
794
|
+
await this.session.steer(text);
|
|
781
795
|
this.updatePendingMessagesDisplay();
|
|
782
796
|
this.editor.addToHistory(text);
|
|
783
797
|
this.editor.setText("");
|
|
@@ -1051,7 +1065,7 @@ export class InteractiveMode {
|
|
|
1051
1065
|
addMessageToChat(message, options) {
|
|
1052
1066
|
switch (message.role) {
|
|
1053
1067
|
case "bashExecution": {
|
|
1054
|
-
const component = new BashExecutionComponent(message.command, this.ui);
|
|
1068
|
+
const component = new BashExecutionComponent(message.command, this.ui, message.excludeFromContext);
|
|
1055
1069
|
if (message.output) {
|
|
1056
1070
|
component.appendOutput(message.output);
|
|
1057
1071
|
}
|
|
@@ -1226,6 +1240,23 @@ export class InteractiveMode {
|
|
|
1226
1240
|
// Send SIGTSTP to process group (pid=0 means all processes in group)
|
|
1227
1241
|
process.kill(0, "SIGTSTP");
|
|
1228
1242
|
}
|
|
1243
|
+
async handleAltEnter() {
|
|
1244
|
+
const text = this.editor.getText().trim();
|
|
1245
|
+
if (!text)
|
|
1246
|
+
return;
|
|
1247
|
+
// Alt+Enter queues a follow-up message (waits until agent finishes)
|
|
1248
|
+
if (this.session.isStreaming) {
|
|
1249
|
+
await this.session.followUp(text);
|
|
1250
|
+
this.updatePendingMessagesDisplay();
|
|
1251
|
+
this.editor.addToHistory(text);
|
|
1252
|
+
this.editor.setText("");
|
|
1253
|
+
this.ui.requestRender();
|
|
1254
|
+
}
|
|
1255
|
+
// If not streaming, Alt+Enter acts like regular Enter (trigger onSubmit)
|
|
1256
|
+
else if (this.editor.onSubmit) {
|
|
1257
|
+
this.editor.onSubmit(text);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1229
1260
|
updateEditorBorderColor() {
|
|
1230
1261
|
if (this.isBashMode) {
|
|
1231
1262
|
this.editor.borderColor = theme.getBashModeBorderColor();
|
|
@@ -1357,12 +1388,17 @@ export class InteractiveMode {
|
|
|
1357
1388
|
}
|
|
1358
1389
|
updatePendingMessagesDisplay() {
|
|
1359
1390
|
this.pendingMessagesContainer.clear();
|
|
1360
|
-
const
|
|
1361
|
-
|
|
1391
|
+
const steeringMessages = this.session.getSteeringMessages();
|
|
1392
|
+
const followUpMessages = this.session.getFollowUpMessages();
|
|
1393
|
+
if (steeringMessages.length > 0 || followUpMessages.length > 0) {
|
|
1362
1394
|
this.pendingMessagesContainer.addChild(new Spacer(1));
|
|
1363
|
-
for (const message of
|
|
1364
|
-
const
|
|
1365
|
-
this.pendingMessagesContainer.addChild(new TruncatedText(
|
|
1395
|
+
for (const message of steeringMessages) {
|
|
1396
|
+
const text = theme.fg("dim", `Steering: ${message}`);
|
|
1397
|
+
this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
|
|
1398
|
+
}
|
|
1399
|
+
for (const message of followUpMessages) {
|
|
1400
|
+
const text = theme.fg("dim", `Follow-up: ${message}`);
|
|
1401
|
+
this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
|
|
1366
1402
|
}
|
|
1367
1403
|
}
|
|
1368
1404
|
}
|
|
@@ -1398,13 +1434,16 @@ export class InteractiveMode {
|
|
|
1398
1434
|
const selector = new SettingsSelectorComponent({
|
|
1399
1435
|
autoCompact: this.session.autoCompactionEnabled,
|
|
1400
1436
|
showImages: this.settingsManager.getShowImages(),
|
|
1401
|
-
|
|
1437
|
+
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
|
1438
|
+
steeringMode: this.session.steeringMode,
|
|
1439
|
+
followUpMode: this.session.followUpMode,
|
|
1402
1440
|
thinkingLevel: this.session.thinkingLevel,
|
|
1403
1441
|
availableThinkingLevels: this.session.getAvailableThinkingLevels(),
|
|
1404
1442
|
currentTheme: this.settingsManager.getTheme() || "dark",
|
|
1405
1443
|
availableThemes: getAvailableThemes(),
|
|
1406
1444
|
hideThinkingBlock: this.hideThinkingBlock,
|
|
1407
1445
|
collapseChangelog: this.settingsManager.getCollapseChangelog(),
|
|
1446
|
+
doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
|
|
1408
1447
|
}, {
|
|
1409
1448
|
onAutoCompactChange: (enabled) => {
|
|
1410
1449
|
this.session.setAutoCompactionEnabled(enabled);
|
|
@@ -1418,8 +1457,14 @@ export class InteractiveMode {
|
|
|
1418
1457
|
}
|
|
1419
1458
|
}
|
|
1420
1459
|
},
|
|
1421
|
-
|
|
1422
|
-
this.
|
|
1460
|
+
onAutoResizeImagesChange: (enabled) => {
|
|
1461
|
+
this.settingsManager.setImageAutoResize(enabled);
|
|
1462
|
+
},
|
|
1463
|
+
onSteeringModeChange: (mode) => {
|
|
1464
|
+
this.session.setSteeringMode(mode);
|
|
1465
|
+
},
|
|
1466
|
+
onFollowUpModeChange: (mode) => {
|
|
1467
|
+
this.session.setFollowUpMode(mode);
|
|
1423
1468
|
},
|
|
1424
1469
|
onThinkingLevelChange: (level) => {
|
|
1425
1470
|
this.session.setThinkingLevel(level);
|
|
@@ -1455,6 +1500,9 @@ export class InteractiveMode {
|
|
|
1455
1500
|
onCollapseChangelogChange: (collapsed) => {
|
|
1456
1501
|
this.settingsManager.setCollapseChangelog(collapsed);
|
|
1457
1502
|
},
|
|
1503
|
+
onDoubleEscapeActionChange: (action) => {
|
|
1504
|
+
this.settingsManager.setDoubleEscapeAction(action);
|
|
1505
|
+
},
|
|
1458
1506
|
onCancel: () => {
|
|
1459
1507
|
done();
|
|
1460
1508
|
this.ui.requestRender();
|
|
@@ -1835,7 +1883,7 @@ export class InteractiveMode {
|
|
|
1835
1883
|
handleSessionCommand() {
|
|
1836
1884
|
const stats = this.session.getSessionStats();
|
|
1837
1885
|
let info = `${theme.bold("Session Info")}\n\n`;
|
|
1838
|
-
info += `${theme.fg("dim", "File:")} ${stats.sessionFile}\n`;
|
|
1886
|
+
info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
|
|
1839
1887
|
info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
|
|
1840
1888
|
info += `${theme.bold("Messages")}\n`;
|
|
1841
1889
|
info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
|
|
@@ -1971,9 +2019,9 @@ export class InteractiveMode {
|
|
|
1971
2019
|
this.chatContainer.addChild(new ArminComponent(this.ui));
|
|
1972
2020
|
this.ui.requestRender();
|
|
1973
2021
|
}
|
|
1974
|
-
async handleBashCommand(command) {
|
|
2022
|
+
async handleBashCommand(command, excludeFromContext = false) {
|
|
1975
2023
|
const isDeferred = this.session.isStreaming;
|
|
1976
|
-
this.bashComponent = new BashExecutionComponent(command, this.ui);
|
|
2024
|
+
this.bashComponent = new BashExecutionComponent(command, this.ui, excludeFromContext);
|
|
1977
2025
|
if (isDeferred) {
|
|
1978
2026
|
// Show in pending area when agent is streaming
|
|
1979
2027
|
this.pendingMessagesContainer.addChild(this.bashComponent);
|
|
@@ -1990,7 +2038,7 @@ export class InteractiveMode {
|
|
|
1990
2038
|
this.bashComponent.appendOutput(chunk);
|
|
1991
2039
|
this.ui.requestRender();
|
|
1992
2040
|
}
|
|
1993
|
-
});
|
|
2041
|
+
}, { excludeFromContext });
|
|
1994
2042
|
if (this.bashComponent) {
|
|
1995
2043
|
this.bashComponent.setComplete(result.exitCode, result.cancelled, result.truncated ? { truncated: true, content: result.output } : undefined, result.fullOutputPath);
|
|
1996
2044
|
}
|