@mariozechner/pi-coding-agent 0.25.1 → 0.25.3
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 +20 -0
- package/README.md +4 -1
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +5 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts +4 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/settings-manager.d.ts +9 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +13 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +2 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +41 -14
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts +2 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +5 -5
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +9 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +2 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +13 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +8 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +76 -12
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/skills.md +53 -0
- package/package.json +4 -4
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Handles TUI rendering and user interaction, delegating business logic to AgentSession.
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
|
+
import * as os from "node:os";
|
|
6
7
|
import * as path from "node:path";
|
|
7
8
|
import { CombinedAutocompleteProvider, Container, getCapabilities, Input, Loader, Markdown, ProcessTerminal, Spacer, Text, TruncatedText, TUI, visibleWidth, } from "@mariozechner/pi-tui";
|
|
8
|
-
import { exec } from "child_process";
|
|
9
|
+
import { exec, spawnSync } from "child_process";
|
|
9
10
|
import { APP_NAME, getDebugLogPath, getOAuthPath } from "../../config.js";
|
|
10
11
|
import { isBashExecutionMessage } from "../../core/messages.js";
|
|
11
12
|
import { invalidateOAuthCache } from "../../core/model-config.js";
|
|
@@ -157,6 +158,9 @@ export class InteractiveMode {
|
|
|
157
158
|
theme.fg("dim", "ctrl+d") +
|
|
158
159
|
theme.fg("muted", " to exit (empty)") +
|
|
159
160
|
"\n" +
|
|
161
|
+
theme.fg("dim", "ctrl+z") +
|
|
162
|
+
theme.fg("muted", " to suspend") +
|
|
163
|
+
"\n" +
|
|
160
164
|
theme.fg("dim", "ctrl+k") +
|
|
161
165
|
theme.fg("muted", " to delete line") +
|
|
162
166
|
"\n" +
|
|
@@ -244,17 +248,22 @@ export class InteractiveMode {
|
|
|
244
248
|
this.chatContainer.addChild(new Spacer(1));
|
|
245
249
|
}
|
|
246
250
|
// Show loaded skills
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
const skillsSettings = this.session.skillsSettings;
|
|
252
|
+
if (skillsSettings?.enabled !== false) {
|
|
253
|
+
const { skills, warnings: skillWarnings } = loadSkills(skillsSettings ?? {});
|
|
254
|
+
if (skills.length > 0) {
|
|
255
|
+
const skillList = skills.map((s) => theme.fg("dim", ` ${s.filePath}`)).join("\n");
|
|
256
|
+
this.chatContainer.addChild(new Text(theme.fg("muted", "Loaded skills:\n") + skillList, 0, 0));
|
|
257
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
258
|
+
}
|
|
259
|
+
// Show skill warnings if any
|
|
260
|
+
if (skillWarnings.length > 0) {
|
|
261
|
+
const warningList = skillWarnings
|
|
262
|
+
.map((w) => theme.fg("warning", ` ${w.skillPath}: ${w.message}`))
|
|
263
|
+
.join("\n");
|
|
264
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", "Skill warnings:\n") + warningList, 0, 0));
|
|
265
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
266
|
+
}
|
|
258
267
|
}
|
|
259
268
|
// Show loaded custom tools
|
|
260
269
|
if (this.customTools.size > 0) {
|
|
@@ -480,10 +489,12 @@ export class InteractiveMode {
|
|
|
480
489
|
};
|
|
481
490
|
this.editor.onCtrlC = () => this.handleCtrlC();
|
|
482
491
|
this.editor.onCtrlD = () => this.handleCtrlD();
|
|
492
|
+
this.editor.onCtrlZ = () => this.handleCtrlZ();
|
|
483
493
|
this.editor.onShiftTab = () => this.cycleThinkingLevel();
|
|
484
494
|
this.editor.onCtrlP = () => this.cycleModel();
|
|
485
495
|
this.editor.onCtrlO = () => this.toggleToolOutputExpansion();
|
|
486
496
|
this.editor.onCtrlT = () => this.toggleThinkingBlockVisibility();
|
|
497
|
+
this.editor.onCtrlG = () => this.openExternalEditor();
|
|
487
498
|
this.editor.onChange = (text) => {
|
|
488
499
|
const wasBashMode = this.isBashMode;
|
|
489
500
|
this.isBashMode = text.trimStart().startsWith("!");
|
|
@@ -990,6 +1001,17 @@ export class InteractiveMode {
|
|
|
990
1001
|
this.stop();
|
|
991
1002
|
process.exit(0);
|
|
992
1003
|
}
|
|
1004
|
+
handleCtrlZ() {
|
|
1005
|
+
// Set up handler to restore TUI when resumed
|
|
1006
|
+
process.once("SIGCONT", () => {
|
|
1007
|
+
this.ui.start();
|
|
1008
|
+
this.ui.requestRender(true);
|
|
1009
|
+
});
|
|
1010
|
+
// Stop the TUI (restore terminal to normal mode)
|
|
1011
|
+
this.ui.stop();
|
|
1012
|
+
// Send SIGTSTP to process group (pid=0 means all processes in group)
|
|
1013
|
+
process.kill(0, "SIGTSTP");
|
|
1014
|
+
}
|
|
993
1015
|
updateEditorBorderColor() {
|
|
994
1016
|
if (this.isBashMode) {
|
|
995
1017
|
this.editor.borderColor = theme.getBashModeBorderColor();
|
|
@@ -1056,6 +1078,46 @@ export class InteractiveMode {
|
|
|
1056
1078
|
this.rebuildChatFromMessages();
|
|
1057
1079
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
|
1058
1080
|
}
|
|
1081
|
+
openExternalEditor() {
|
|
1082
|
+
// Determine editor (respect $VISUAL, then $EDITOR)
|
|
1083
|
+
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
|
1084
|
+
if (!editorCmd) {
|
|
1085
|
+
this.showWarning("No editor configured. Set $VISUAL or $EDITOR environment variable.");
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
const currentText = this.editor.getText();
|
|
1089
|
+
const tmpFile = path.join(os.tmpdir(), `pi-editor-${Date.now()}.pi.md`);
|
|
1090
|
+
try {
|
|
1091
|
+
// Write current content to temp file
|
|
1092
|
+
fs.writeFileSync(tmpFile, currentText, "utf-8");
|
|
1093
|
+
// Stop TUI to release terminal
|
|
1094
|
+
this.ui.stop();
|
|
1095
|
+
// Split by space to support editor arguments (e.g., "code --wait")
|
|
1096
|
+
const [editor, ...editorArgs] = editorCmd.split(" ");
|
|
1097
|
+
// Spawn editor synchronously with inherited stdio for interactive editing
|
|
1098
|
+
const result = spawnSync(editor, [...editorArgs, tmpFile], {
|
|
1099
|
+
stdio: "inherit",
|
|
1100
|
+
});
|
|
1101
|
+
// On successful exit (status 0), replace editor content
|
|
1102
|
+
if (result.status === 0) {
|
|
1103
|
+
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
|
1104
|
+
this.editor.setText(newContent);
|
|
1105
|
+
}
|
|
1106
|
+
// On non-zero exit, keep original text (no action needed)
|
|
1107
|
+
}
|
|
1108
|
+
finally {
|
|
1109
|
+
// Clean up temp file
|
|
1110
|
+
try {
|
|
1111
|
+
fs.unlinkSync(tmpFile);
|
|
1112
|
+
}
|
|
1113
|
+
catch {
|
|
1114
|
+
// Ignore cleanup errors
|
|
1115
|
+
}
|
|
1116
|
+
// Restart TUI
|
|
1117
|
+
this.ui.start();
|
|
1118
|
+
this.ui.requestRender();
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1059
1121
|
// =========================================================================
|
|
1060
1122
|
// UI helpers
|
|
1061
1123
|
// =========================================================================
|
|
@@ -1443,10 +1505,12 @@ export class InteractiveMode {
|
|
|
1443
1505
|
| \`Escape\` | Cancel autocomplete / abort streaming |
|
|
1444
1506
|
| \`Ctrl+C\` | Clear editor (first) / exit (second) |
|
|
1445
1507
|
| \`Ctrl+D\` | Exit (when editor is empty) |
|
|
1508
|
+
| \`Ctrl+Z\` | Suspend to background |
|
|
1446
1509
|
| \`Shift+Tab\` | Cycle thinking level |
|
|
1447
1510
|
| \`Ctrl+P\` | Cycle models |
|
|
1448
1511
|
| \`Ctrl+O\` | Toggle tool output expansion |
|
|
1449
1512
|
| \`Ctrl+T\` | Toggle thinking block visibility |
|
|
1513
|
+
| \`Ctrl+G\` | Edit message in external editor |
|
|
1450
1514
|
| \`/\` | Slash commands |
|
|
1451
1515
|
| \`!\` | Run bash command |
|
|
1452
1516
|
`;
|