@mariozechner/pi-coding-agent 0.12.10 → 0.12.12
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 +138 -268
- package/README.md +50 -0
- package/dist/fuzzy.d.ts +7 -0
- package/dist/fuzzy.d.ts.map +1 -0
- package/dist/fuzzy.js +64 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/fuzzy.test.d.ts +2 -0
- package/dist/fuzzy.test.d.ts.map +1 -0
- package/dist/fuzzy.test.js +76 -0
- package/dist/fuzzy.test.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +61 -49
- package/dist/main.js.map +1 -1
- package/dist/model-config.d.ts.map +1 -1
- package/dist/model-config.js +9 -1
- package/dist/model-config.js.map +1 -1
- package/dist/settings-manager.d.ts +3 -0
- package/dist/settings-manager.d.ts.map +1 -1
- package/dist/settings-manager.js +7 -0
- package/dist/settings-manager.js.map +1 -1
- package/dist/tui/assistant-message.d.ts +3 -1
- package/dist/tui/assistant-message.d.ts.map +1 -1
- package/dist/tui/assistant-message.js +26 -9
- package/dist/tui/assistant-message.js.map +1 -1
- package/dist/tui/compaction.d.ts.map +1 -1
- package/dist/tui/compaction.js +5 -4
- package/dist/tui/compaction.js.map +1 -1
- package/dist/tui/custom-editor.d.ts +1 -0
- package/dist/tui/custom-editor.d.ts.map +1 -1
- package/dist/tui/custom-editor.js +6 -0
- package/dist/tui/custom-editor.js.map +1 -1
- package/dist/tui/footer.d.ts.map +1 -1
- package/dist/tui/footer.js +18 -6
- package/dist/tui/footer.js.map +1 -1
- package/dist/tui/model-selector.d.ts.map +1 -1
- package/dist/tui/model-selector.js +2 -13
- package/dist/tui/model-selector.js.map +1 -1
- package/dist/tui/session-selector.d.ts.map +1 -1
- package/dist/tui/session-selector.js +2 -14
- package/dist/tui/session-selector.js.map +1 -1
- package/dist/tui/tool-execution.d.ts.map +1 -1
- package/dist/tui/tool-execution.js +11 -1
- package/dist/tui/tool-execution.js.map +1 -1
- package/dist/tui/tui-renderer.d.ts +6 -1
- package/dist/tui/tui-renderer.d.ts.map +1 -1
- package/dist/tui/tui-renderer.js +133 -15
- package/dist/tui/tui-renderer.js.map +1 -1
- package/dist/tui/user-message-selector.d.ts.map +1 -1
- package/dist/tui/user-message-selector.js +3 -3
- package/dist/tui/user-message-selector.js.map +1 -1
- package/package.json +4 -4
package/dist/tui/tui-renderer.js
CHANGED
|
@@ -20,6 +20,7 @@ import { FooterComponent } from "./footer.js";
|
|
|
20
20
|
import { ModelSelectorComponent } from "./model-selector.js";
|
|
21
21
|
import { OAuthSelectorComponent } from "./oauth-selector.js";
|
|
22
22
|
import { QueueModeSelectorComponent } from "./queue-mode-selector.js";
|
|
23
|
+
import { SessionSelectorComponent } from "./session-selector.js";
|
|
23
24
|
import { ThemeSelectorComponent } from "./theme-selector.js";
|
|
24
25
|
import { ThinkingSelectorComponent } from "./thinking-selector.js";
|
|
25
26
|
import { ToolExecutionComponent } from "./tool-execution.js";
|
|
@@ -62,6 +63,8 @@ export class TuiRenderer {
|
|
|
62
63
|
modelSelector = null;
|
|
63
64
|
// User message selector (for branching)
|
|
64
65
|
userMessageSelector = null;
|
|
66
|
+
// Session selector (for resume)
|
|
67
|
+
sessionSelector = null;
|
|
65
68
|
// OAuth selector
|
|
66
69
|
oauthSelector = null;
|
|
67
70
|
// Track if this is the first user message (to skip spacer)
|
|
@@ -70,6 +73,8 @@ export class TuiRenderer {
|
|
|
70
73
|
scopedModels = [];
|
|
71
74
|
// Tool output expansion state
|
|
72
75
|
toolOutputExpanded = false;
|
|
76
|
+
// Thinking block visibility state
|
|
77
|
+
hideThinkingBlock = false;
|
|
73
78
|
// Agent subscription unsubscribe function
|
|
74
79
|
unsubscribe;
|
|
75
80
|
// File-based slash commands
|
|
@@ -148,6 +153,12 @@ export class TuiRenderer {
|
|
|
148
153
|
name: "autocompact",
|
|
149
154
|
description: "Toggle automatic context compaction",
|
|
150
155
|
};
|
|
156
|
+
const resumeCommand = {
|
|
157
|
+
name: "resume",
|
|
158
|
+
description: "Resume a different session",
|
|
159
|
+
};
|
|
160
|
+
// Load hide thinking block setting
|
|
161
|
+
this.hideThinkingBlock = settingsManager.getHideThinkingBlock();
|
|
151
162
|
// Load file-based slash commands
|
|
152
163
|
this.fileCommands = loadSlashCommands();
|
|
153
164
|
// Convert file commands to SlashCommand format
|
|
@@ -171,6 +182,7 @@ export class TuiRenderer {
|
|
|
171
182
|
clearCommand,
|
|
172
183
|
compactCommand,
|
|
173
184
|
autocompactCommand,
|
|
185
|
+
resumeCommand,
|
|
174
186
|
...fileSlashCommands,
|
|
175
187
|
], process.cwd(), fdPath);
|
|
176
188
|
this.editor.setAutocompleteProvider(autocompleteProvider);
|
|
@@ -201,6 +213,9 @@ export class TuiRenderer {
|
|
|
201
213
|
theme.fg("dim", "ctrl+o") +
|
|
202
214
|
theme.fg("muted", " to expand tools") +
|
|
203
215
|
"\n" +
|
|
216
|
+
theme.fg("dim", "ctrl+t") +
|
|
217
|
+
theme.fg("muted", " to toggle thinking") +
|
|
218
|
+
"\n" +
|
|
204
219
|
theme.fg("dim", "/") +
|
|
205
220
|
theme.fg("muted", " for commands") +
|
|
206
221
|
"\n" +
|
|
@@ -269,6 +284,9 @@ export class TuiRenderer {
|
|
|
269
284
|
this.editor.onCtrlO = () => {
|
|
270
285
|
this.toggleToolOutputExpansion();
|
|
271
286
|
};
|
|
287
|
+
this.editor.onCtrlT = () => {
|
|
288
|
+
this.toggleThinkingBlockVisibility();
|
|
289
|
+
};
|
|
272
290
|
// Handle editor submission
|
|
273
291
|
this.editor.onSubmit = async (text) => {
|
|
274
292
|
text = text.trim();
|
|
@@ -367,6 +385,12 @@ export class TuiRenderer {
|
|
|
367
385
|
this.editor.setText("");
|
|
368
386
|
return;
|
|
369
387
|
}
|
|
388
|
+
// Check for /resume command
|
|
389
|
+
if (text === "/resume") {
|
|
390
|
+
this.showSessionSelector();
|
|
391
|
+
this.editor.setText("");
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
370
394
|
// Check for file-based slash commands
|
|
371
395
|
text = expandSlashCommand(text, this.fileCommands);
|
|
372
396
|
// Normal message submission - validate model and API key first
|
|
@@ -398,6 +422,8 @@ export class TuiRenderer {
|
|
|
398
422
|
});
|
|
399
423
|
// Update pending messages display
|
|
400
424
|
this.updatePendingMessagesDisplay();
|
|
425
|
+
// Add to history for up/down arrow navigation
|
|
426
|
+
this.editor.addToHistory(text);
|
|
401
427
|
// Clear editor
|
|
402
428
|
this.editor.setText("");
|
|
403
429
|
this.ui.requestRender();
|
|
@@ -407,6 +433,8 @@ export class TuiRenderer {
|
|
|
407
433
|
if (this.onInputCallback) {
|
|
408
434
|
this.onInputCallback(text);
|
|
409
435
|
}
|
|
436
|
+
// Add to history for up/down arrow navigation
|
|
437
|
+
this.editor.addToHistory(text);
|
|
410
438
|
};
|
|
411
439
|
// Start the UI
|
|
412
440
|
this.ui.start();
|
|
@@ -508,7 +536,7 @@ export class TuiRenderer {
|
|
|
508
536
|
}
|
|
509
537
|
else if (event.message.role === "assistant") {
|
|
510
538
|
// Create assistant component for streaming
|
|
511
|
-
this.streamingComponent = new AssistantMessageComponent();
|
|
539
|
+
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock);
|
|
512
540
|
this.chatContainer.addChild(this.streamingComponent);
|
|
513
541
|
this.streamingComponent.updateContent(event.message);
|
|
514
542
|
this.ui.requestRender();
|
|
@@ -634,7 +662,7 @@ export class TuiRenderer {
|
|
|
634
662
|
else if (message.role === "assistant") {
|
|
635
663
|
const assistantMsg = message;
|
|
636
664
|
// Add assistant message component
|
|
637
|
-
const assistantComponent = new AssistantMessageComponent(assistantMsg);
|
|
665
|
+
const assistantComponent = new AssistantMessageComponent(assistantMsg, this.hideThinkingBlock);
|
|
638
666
|
this.chatContainer.addChild(assistantComponent);
|
|
639
667
|
}
|
|
640
668
|
// Note: tool calls and results are now handled via tool_execution_start/end events
|
|
@@ -675,7 +703,7 @@ export class TuiRenderer {
|
|
|
675
703
|
}
|
|
676
704
|
else if (message.role === "assistant") {
|
|
677
705
|
const assistantMsg = message;
|
|
678
|
-
const assistantComponent = new AssistantMessageComponent(assistantMsg);
|
|
706
|
+
const assistantComponent = new AssistantMessageComponent(assistantMsg, this.hideThinkingBlock);
|
|
679
707
|
this.chatContainer.addChild(assistantComponent);
|
|
680
708
|
// Create tool execution components for any tool calls
|
|
681
709
|
for (const content of assistantMsg.content) {
|
|
@@ -715,6 +743,19 @@ export class TuiRenderer {
|
|
|
715
743
|
}
|
|
716
744
|
// Clear pending tools after rendering initial messages
|
|
717
745
|
this.pendingTools.clear();
|
|
746
|
+
// Populate editor history with user messages from the session (oldest first so newest is at index 0)
|
|
747
|
+
for (const message of state.messages) {
|
|
748
|
+
if (message.role === "user") {
|
|
749
|
+
const textBlocks = typeof message.content === "string"
|
|
750
|
+
? [{ type: "text", text: message.content }]
|
|
751
|
+
: message.content.filter((c) => c.type === "text");
|
|
752
|
+
const textContent = textBlocks.map((c) => c.text).join("");
|
|
753
|
+
// Skip compaction summary messages
|
|
754
|
+
if (textContent && !textContent.startsWith(SUMMARY_PREFIX)) {
|
|
755
|
+
this.editor.addToHistory(textContent);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
718
759
|
this.ui.requestRender();
|
|
719
760
|
}
|
|
720
761
|
async getUserInput() {
|
|
@@ -755,7 +796,7 @@ export class TuiRenderer {
|
|
|
755
796
|
}
|
|
756
797
|
else if (message.role === "assistant") {
|
|
757
798
|
const assistantMsg = message;
|
|
758
|
-
const assistantComponent = new AssistantMessageComponent(assistantMsg);
|
|
799
|
+
const assistantComponent = new AssistantMessageComponent(assistantMsg, this.hideThinkingBlock);
|
|
759
800
|
this.chatContainer.addChild(assistantComponent);
|
|
760
801
|
for (const content of assistantMsg.content) {
|
|
761
802
|
if (content.type === "toolCall") {
|
|
@@ -923,6 +964,24 @@ export class TuiRenderer {
|
|
|
923
964
|
}
|
|
924
965
|
this.ui.requestRender();
|
|
925
966
|
}
|
|
967
|
+
toggleThinkingBlockVisibility() {
|
|
968
|
+
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
969
|
+
this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
|
|
970
|
+
// Update all assistant message components and rebuild their content
|
|
971
|
+
for (const child of this.chatContainer.children) {
|
|
972
|
+
if (child instanceof AssistantMessageComponent) {
|
|
973
|
+
child.setHideThinkingBlock(this.hideThinkingBlock);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
// Rebuild chat to apply visibility change
|
|
977
|
+
this.chatContainer.clear();
|
|
978
|
+
this.rebuildChatFromMessages();
|
|
979
|
+
// Show brief notification
|
|
980
|
+
const status = this.hideThinkingBlock ? "hidden" : "visible";
|
|
981
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
982
|
+
this.chatContainer.addChild(new Text(theme.fg("dim", `Thinking blocks: ${status}`), 1, 0));
|
|
983
|
+
this.ui.requestRender();
|
|
984
|
+
}
|
|
926
985
|
clearEditor() {
|
|
927
986
|
this.editor.setText("");
|
|
928
987
|
this.ui.requestRender();
|
|
@@ -939,14 +998,6 @@ export class TuiRenderer {
|
|
|
939
998
|
this.chatContainer.addChild(new Text(theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
|
|
940
999
|
this.ui.requestRender();
|
|
941
1000
|
}
|
|
942
|
-
showSuccess(message, detail) {
|
|
943
|
-
this.chatContainer.addChild(new Spacer(1));
|
|
944
|
-
const text = detail
|
|
945
|
-
? `${theme.fg("success", message)}\n${theme.fg("muted", detail)}`
|
|
946
|
-
: theme.fg("success", message);
|
|
947
|
-
this.chatContainer.addChild(new Text(text, 1, 1));
|
|
948
|
-
this.ui.requestRender();
|
|
949
|
-
}
|
|
950
1001
|
showThinkingSelector() {
|
|
951
1002
|
// Create thinking selector with current level
|
|
952
1003
|
this.thinkingSelector = new ThinkingSelectorComponent(this.agent.state.thinkingLevel, (level) => {
|
|
@@ -1176,6 +1227,76 @@ export class TuiRenderer {
|
|
|
1176
1227
|
this.userMessageSelector = null;
|
|
1177
1228
|
this.ui.setFocus(this.editor);
|
|
1178
1229
|
}
|
|
1230
|
+
showSessionSelector() {
|
|
1231
|
+
// Create session selector
|
|
1232
|
+
this.sessionSelector = new SessionSelectorComponent(this.sessionManager, async (sessionPath) => {
|
|
1233
|
+
this.hideSessionSelector();
|
|
1234
|
+
await this.handleResumeSession(sessionPath);
|
|
1235
|
+
}, () => {
|
|
1236
|
+
// Just hide the selector
|
|
1237
|
+
this.hideSessionSelector();
|
|
1238
|
+
this.ui.requestRender();
|
|
1239
|
+
});
|
|
1240
|
+
// Replace editor with selector
|
|
1241
|
+
this.editorContainer.clear();
|
|
1242
|
+
this.editorContainer.addChild(this.sessionSelector);
|
|
1243
|
+
this.ui.setFocus(this.sessionSelector.getSessionList());
|
|
1244
|
+
this.ui.requestRender();
|
|
1245
|
+
}
|
|
1246
|
+
async handleResumeSession(sessionPath) {
|
|
1247
|
+
// Unsubscribe first to prevent processing events during transition
|
|
1248
|
+
this.unsubscribe?.();
|
|
1249
|
+
// Abort and wait for completion
|
|
1250
|
+
this.agent.abort();
|
|
1251
|
+
await this.agent.waitForIdle();
|
|
1252
|
+
// Stop loading animation
|
|
1253
|
+
if (this.loadingAnimation) {
|
|
1254
|
+
this.loadingAnimation.stop();
|
|
1255
|
+
this.loadingAnimation = null;
|
|
1256
|
+
}
|
|
1257
|
+
this.statusContainer.clear();
|
|
1258
|
+
// Clear UI state
|
|
1259
|
+
this.queuedMessages = [];
|
|
1260
|
+
this.pendingMessagesContainer.clear();
|
|
1261
|
+
this.streamingComponent = null;
|
|
1262
|
+
this.pendingTools.clear();
|
|
1263
|
+
// Set the selected session as active
|
|
1264
|
+
this.sessionManager.setSessionFile(sessionPath);
|
|
1265
|
+
// Reload the session
|
|
1266
|
+
const loaded = loadSessionFromEntries(this.sessionManager.loadEntries());
|
|
1267
|
+
this.agent.replaceMessages(loaded.messages);
|
|
1268
|
+
// Restore model if saved in session
|
|
1269
|
+
const savedModel = this.sessionManager.loadModel();
|
|
1270
|
+
if (savedModel) {
|
|
1271
|
+
const availableModels = (await getAvailableModels()).models;
|
|
1272
|
+
const match = availableModels.find((m) => m.provider === savedModel.provider && m.id === savedModel.modelId);
|
|
1273
|
+
if (match) {
|
|
1274
|
+
this.agent.setModel(match);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
// Restore thinking level if saved in session
|
|
1278
|
+
const savedThinking = this.sessionManager.loadThinkingLevel();
|
|
1279
|
+
if (savedThinking) {
|
|
1280
|
+
this.agent.setThinkingLevel(savedThinking);
|
|
1281
|
+
}
|
|
1282
|
+
// Resubscribe to agent
|
|
1283
|
+
this.subscribeToAgent();
|
|
1284
|
+
// Clear and re-render the chat
|
|
1285
|
+
this.chatContainer.clear();
|
|
1286
|
+
this.isFirstUserMessage = true;
|
|
1287
|
+
this.renderInitialMessages(this.agent.state);
|
|
1288
|
+
// Show confirmation message
|
|
1289
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
1290
|
+
this.chatContainer.addChild(new Text(theme.fg("dim", "Resumed session"), 1, 0));
|
|
1291
|
+
this.ui.requestRender();
|
|
1292
|
+
}
|
|
1293
|
+
hideSessionSelector() {
|
|
1294
|
+
// Replace selector with editor in the container
|
|
1295
|
+
this.editorContainer.clear();
|
|
1296
|
+
this.editorContainer.addChild(this.editor);
|
|
1297
|
+
this.sessionSelector = null;
|
|
1298
|
+
this.ui.setFocus(this.editor);
|
|
1299
|
+
}
|
|
1179
1300
|
async showOAuthSelector(mode) {
|
|
1180
1301
|
// For logout mode, filter to only show logged-in providers
|
|
1181
1302
|
let providersToShow = [];
|
|
@@ -1521,9 +1642,6 @@ export class TuiRenderer {
|
|
|
1521
1642
|
this.chatContainer.addChild(compactionComponent);
|
|
1522
1643
|
// Update footer with new state (fixes context % display)
|
|
1523
1644
|
this.footer.updateState(this.agent.state);
|
|
1524
|
-
// Show success message
|
|
1525
|
-
const successTitle = isAuto ? "✓ Context auto-compacted" : "✓ Context compacted";
|
|
1526
|
-
this.showSuccess(successTitle, `Reduced from ${compactionEntry.tokensBefore.toLocaleString()} tokens`);
|
|
1527
1645
|
}
|
|
1528
1646
|
catch (error) {
|
|
1529
1647
|
const message = error instanceof Error ? error.message : String(error);
|