@selesai/code 0.11.0 → 0.13.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 +26 -0
- package/dist/cli/startup-ui.js +2 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.js +77 -9
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/compaction.d.ts +5 -0
- package/dist/core/compaction/compaction.js +19 -4
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.js +48 -1
- package/dist/core/extensions/types.d.ts +18 -1
- package/dist/core/llama/client.d.ts +6 -0
- package/dist/core/llama/client.js +7 -0
- package/dist/core/llama/provider.d.ts +3 -1
- package/dist/core/llama/provider.js +28 -6
- package/dist/core/session-manager.js +4 -2
- package/dist/core/settings-manager.d.ts +8 -1
- package/dist/core/settings-manager.js +17 -0
- package/dist/core/usage-totals.d.ts +2 -0
- package/dist/core/usage-totals.js +10 -0
- package/dist/defaults/models.json +32 -9
- package/dist/extensions/pi-zentui/extensions/zentui/format.ts +2 -1
- package/dist/extensions/pi-zentui/test/format.test.ts +15 -1
- package/dist/extensions/tokenin-onboarding.ts +112 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/main.js +2 -0
- package/dist/modes/interactive/components/footer.js +2 -2
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.js +59 -43
- package/dist/modes/rpc/rpc-client.d.ts +7 -0
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-types.d.ts +12 -0
- package/dist/utils/shell.js +6 -4
- package/docs/settings.md +4 -0
- package/package.json +4 -4
|
@@ -6,7 +6,7 @@ import * as fs from "node:fs";
|
|
|
6
6
|
import * as os from "node:os";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
9
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
9
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Markdown, matchesKey, ProcessTerminal, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import { spawn, spawnSync } from "child_process";
|
|
12
12
|
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getBundledDefaultsDir, getDebugLogPath, getDocsPath, getShareViewerUrl, getUpdateInstruction, PACKAGE_NAME, VERSION, } from "../../config.js";
|
|
@@ -25,7 +25,7 @@ import { buildGitCommandPrompt, GIT_COMMAND_MODES } from "../../core/git-command
|
|
|
25
25
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
26
26
|
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
27
27
|
import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
|
|
28
|
-
import { getUsageCostBreakdown } from "../../core/usage-totals.js";
|
|
28
|
+
import { formatCost, getUsageCostBreakdown } from "../../core/usage-totals.js";
|
|
29
29
|
import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
|
|
30
30
|
import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
|
|
31
31
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
@@ -199,6 +199,7 @@ export function createInteractiveTui(options) {
|
|
|
199
199
|
searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
|
|
200
200
|
openUrl: openBrowser,
|
|
201
201
|
onRightClickPaste: options.onRightClickPaste,
|
|
202
|
+
copyOnSelect: options.fullscreenCopyOnSelect,
|
|
202
203
|
copySelection: async (text) => {
|
|
203
204
|
try {
|
|
204
205
|
await copyToClipboard(text);
|
|
@@ -359,6 +360,7 @@ export class InteractiveMode {
|
|
|
359
360
|
}
|
|
360
361
|
constructor(runtimeHost, options = {}) {
|
|
361
362
|
this.runtimeHost = runtimeHost;
|
|
363
|
+
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
362
364
|
const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
|
|
363
365
|
this.options = { ...options, tuiMode };
|
|
364
366
|
this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
|
|
@@ -374,6 +376,7 @@ export class InteractiveMode {
|
|
|
374
376
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
375
377
|
logDirectory: getAgentDir(),
|
|
376
378
|
onRightClickPaste: this.onRightClickPaste,
|
|
379
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
377
380
|
});
|
|
378
381
|
this.ui = createInteractiveTuiReference(() => this.renderer);
|
|
379
382
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
@@ -610,6 +613,7 @@ export class InteractiveMode {
|
|
|
610
613
|
logDirectory: getAgentDir(),
|
|
611
614
|
terminal,
|
|
612
615
|
onRightClickPaste: this.onRightClickPaste,
|
|
616
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
613
617
|
});
|
|
614
618
|
nextUi.setClearOnShrink(clearOnShrink);
|
|
615
619
|
nextUi.onDebug = onDebug;
|
|
@@ -1424,7 +1428,11 @@ export class InteractiveMode {
|
|
|
1424
1428
|
this.showStartupNoticesIfNeeded();
|
|
1425
1429
|
}
|
|
1426
1430
|
applyRuntimeSettings() {
|
|
1431
|
+
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
1427
1432
|
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
1433
|
+
if (this.renderer instanceof TuiAltScreen) {
|
|
1434
|
+
this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
|
|
1435
|
+
}
|
|
1428
1436
|
this.footer.setSession(this.session);
|
|
1429
1437
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
1430
1438
|
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
@@ -1571,6 +1579,9 @@ export class InteractiveMode {
|
|
|
1571
1579
|
this.statusContainer.addChild(this.idleStatus);
|
|
1572
1580
|
}
|
|
1573
1581
|
}
|
|
1582
|
+
showWorkingStatusIndicator() {
|
|
1583
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
|
|
1584
|
+
}
|
|
1574
1585
|
setWorkingVisible(visible) {
|
|
1575
1586
|
this.workingVisible = visible;
|
|
1576
1587
|
if (!visible) {
|
|
@@ -1579,7 +1590,7 @@ export class InteractiveMode {
|
|
|
1579
1590
|
return;
|
|
1580
1591
|
}
|
|
1581
1592
|
if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
|
|
1582
|
-
this.
|
|
1593
|
+
this.showWorkingStatusIndicator();
|
|
1583
1594
|
}
|
|
1584
1595
|
this.ui.requestRender();
|
|
1585
1596
|
}
|
|
@@ -2191,7 +2202,7 @@ export class InteractiveMode {
|
|
|
2191
2202
|
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
2192
2203
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
2193
2204
|
this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
|
|
2194
|
-
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
|
|
2205
|
+
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
|
|
2195
2206
|
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
2196
2207
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
2197
2208
|
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
@@ -2510,17 +2521,21 @@ export class InteractiveMode {
|
|
|
2510
2521
|
switch (event.type) {
|
|
2511
2522
|
case "agent_start":
|
|
2512
2523
|
this.pendingTools.clear();
|
|
2513
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2514
|
-
this.ui.terminal.setProgress(true);
|
|
2515
|
-
}
|
|
2516
2524
|
// Restore main escape handler if retry handler is still active
|
|
2517
2525
|
// (retry success event fires later, but we need main handler now)
|
|
2518
2526
|
if (this.retryEscapeHandler) {
|
|
2519
2527
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2520
2528
|
this.retryEscapeHandler = undefined;
|
|
2521
2529
|
}
|
|
2530
|
+
break;
|
|
2531
|
+
case "turn_start":
|
|
2532
|
+
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2533
|
+
this.ui.terminal.setProgress(true);
|
|
2534
|
+
}
|
|
2522
2535
|
if (this.workingVisible) {
|
|
2523
|
-
|
|
2536
|
+
if (this.activeStatusIndicator?.kind !== "working") {
|
|
2537
|
+
this.showWorkingStatusIndicator();
|
|
2538
|
+
}
|
|
2524
2539
|
}
|
|
2525
2540
|
else {
|
|
2526
2541
|
this.clearStatusIndicator();
|
|
@@ -3372,18 +3387,19 @@ export class InteractiveMode {
|
|
|
3372
3387
|
}
|
|
3373
3388
|
this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
|
|
3374
3389
|
}
|
|
3390
|
+
/** Update rendered assistant messages without rebuilding live tool components. */
|
|
3391
|
+
updateThinkingBlockVisibility() {
|
|
3392
|
+
for (const child of this.chatContainer.children) {
|
|
3393
|
+
if (child instanceof AssistantMessageComponent) {
|
|
3394
|
+
child.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
this.ui.requestRender();
|
|
3398
|
+
}
|
|
3375
3399
|
toggleThinkingBlockVisibility() {
|
|
3376
3400
|
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
3377
3401
|
this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3378
|
-
|
|
3379
|
-
this.chatContainer.clear();
|
|
3380
|
-
this.rebuildChatFromMessages();
|
|
3381
|
-
// If streaming, re-add the streaming component with updated visibility and re-render
|
|
3382
|
-
if (this.streamingComponent && this.streamingMessage) {
|
|
3383
|
-
this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3384
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
3385
|
-
this.chatContainer.addChild(this.streamingComponent);
|
|
3386
|
-
}
|
|
3402
|
+
this.updateThinkingBlockVisibility();
|
|
3387
3403
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
|
3388
3404
|
}
|
|
3389
3405
|
async handleOpenExternalEditor() {
|
|
@@ -3680,6 +3696,7 @@ export class InteractiveMode {
|
|
|
3680
3696
|
tuiMode: this.settingsManager.getTuiMode(),
|
|
3681
3697
|
fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
|
|
3682
3698
|
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3699
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
3683
3700
|
warnings: this.settingsManager.getWarnings(),
|
|
3684
3701
|
skills: this.buildSkillToggleItems(),
|
|
3685
3702
|
}, {
|
|
@@ -3751,13 +3768,7 @@ export class InteractiveMode {
|
|
|
3751
3768
|
onHideThinkingBlockChange: (hidden) => {
|
|
3752
3769
|
this.hideThinkingBlock = hidden;
|
|
3753
3770
|
this.settingsManager.setHideThinkingBlock(hidden);
|
|
3754
|
-
|
|
3755
|
-
if (child instanceof AssistantMessageComponent) {
|
|
3756
|
-
child.setHideThinkingBlock(hidden);
|
|
3757
|
-
}
|
|
3758
|
-
}
|
|
3759
|
-
this.chatContainer.clear();
|
|
3760
|
-
this.rebuildChatFromMessages();
|
|
3771
|
+
this.updateThinkingBlockVisibility();
|
|
3761
3772
|
},
|
|
3762
3773
|
onShowCacheMissNoticesChange: (shown) => {
|
|
3763
3774
|
this.settingsManager.setShowCacheMissNotices(shown);
|
|
@@ -3847,6 +3858,11 @@ export class InteractiveMode {
|
|
|
3847
3858
|
this.transcriptScrollView?.setScrollbar(mode);
|
|
3848
3859
|
this.ui.requestRender();
|
|
3849
3860
|
},
|
|
3861
|
+
onFullscreenCopyOnSelectChange: (enabled) => {
|
|
3862
|
+
this.settingsManager.setFullscreenCopyOnSelect(enabled);
|
|
3863
|
+
if (this.renderer instanceof TuiAltScreen)
|
|
3864
|
+
this.renderer.setCopyOnSelect(enabled);
|
|
3865
|
+
},
|
|
3850
3866
|
onWarningsChange: (warnings) => {
|
|
3851
3867
|
this.settingsManager.setWarnings(warnings);
|
|
3852
3868
|
},
|
|
@@ -4057,6 +4073,7 @@ export class InteractiveMode {
|
|
|
4057
4073
|
return;
|
|
4058
4074
|
try {
|
|
4059
4075
|
await this.session.setModel(model);
|
|
4076
|
+
this.updateAvailableProviderCount();
|
|
4060
4077
|
this.footer.invalidate();
|
|
4061
4078
|
this.updateEditorBorderColor();
|
|
4062
4079
|
done();
|
|
@@ -4870,21 +4887,8 @@ export class InteractiveMode {
|
|
|
4870
4887
|
activeHeader.setExpanded(this.toolOutputExpanded);
|
|
4871
4888
|
}
|
|
4872
4889
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
4890
|
+
this.applyRuntimeSettings();
|
|
4873
4891
|
await this.themeController.applyFromSettings();
|
|
4874
|
-
const editorPaddingX = this.settingsManager.getEditorPaddingX();
|
|
4875
|
-
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
|
4876
|
-
this.defaultEditor.setPaddingX(editorPaddingX);
|
|
4877
|
-
this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
|
|
4878
|
-
if (this.editor !== this.defaultEditor) {
|
|
4879
|
-
this.editor.setPaddingX?.(editorPaddingX);
|
|
4880
|
-
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
|
4881
|
-
}
|
|
4882
|
-
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
4883
|
-
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
|
4884
|
-
this.ui.setClearOnShrink(clearOnShrink);
|
|
4885
|
-
if (!clearOnShrink && !this.activeStatusIndicator) {
|
|
4886
|
-
this.statusContainer.clear();
|
|
4887
|
-
}
|
|
4888
4892
|
this.setupAutocompleteProvider();
|
|
4889
4893
|
const runner = this.session.extensionRunner;
|
|
4890
4894
|
this.setupExtensionShortcuts(runner);
|
|
@@ -5082,7 +5086,14 @@ export class InteractiveMode {
|
|
|
5082
5086
|
}
|
|
5083
5087
|
}
|
|
5084
5088
|
}
|
|
5085
|
-
async handleCopyCommand() {
|
|
5089
|
+
async handleCopyCommand(options = {}) {
|
|
5090
|
+
if (options.preferSelection &&
|
|
5091
|
+
this.ui instanceof TuiAltScreen &&
|
|
5092
|
+
!this.ui.getCopyOnSelect() &&
|
|
5093
|
+
this.ui.hasActiveSelection()) {
|
|
5094
|
+
await this.ui.copyActiveSelectionToClipboard();
|
|
5095
|
+
return;
|
|
5096
|
+
}
|
|
5086
5097
|
const text = this.session.getLastAssistantText();
|
|
5087
5098
|
if (!text) {
|
|
5088
5099
|
this.showError("No agent messages to copy yet.");
|
|
@@ -5090,7 +5101,12 @@ export class InteractiveMode {
|
|
|
5090
5101
|
}
|
|
5091
5102
|
try {
|
|
5092
5103
|
await copyToClipboard(text);
|
|
5093
|
-
|
|
5104
|
+
if (options.flashConfirmation && this.ui instanceof TuiAltScreen) {
|
|
5105
|
+
this.ui.flash("Copied!");
|
|
5106
|
+
}
|
|
5107
|
+
else {
|
|
5108
|
+
this.showStatus("Copied last agent message to clipboard");
|
|
5109
|
+
}
|
|
5094
5110
|
}
|
|
5095
5111
|
catch (error) {
|
|
5096
5112
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
@@ -5157,10 +5173,10 @@ export class InteractiveMode {
|
|
|
5157
5173
|
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5158
5174
|
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
5159
5175
|
info += `\n${theme.bold("Cost")}\n`;
|
|
5160
|
-
info += `${theme.fg("dim", "Total:")}
|
|
5176
|
+
info += `${theme.fg("dim", "Total:")} ${formatCost(stats.cost)}`;
|
|
5161
5177
|
if (usageBreakdown.length > 1) {
|
|
5162
5178
|
for (const entry of usageBreakdown) {
|
|
5163
|
-
info += `\n ${theme.fg("dim", `${entry.key}:`)}
|
|
5179
|
+
info += `\n ${theme.fg("dim", `${entry.key}:`)} ${formatCost(entry.cost)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
|
|
5164
5180
|
}
|
|
5165
5181
|
}
|
|
5166
5182
|
if (cacheWaste.missedTokens > 0) {
|
|
@@ -5168,7 +5184,7 @@ export class InteractiveMode {
|
|
|
5168
5184
|
const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
|
|
5169
5185
|
info +=
|
|
5170
5186
|
cacheWaste.missedCost >= 0.0001
|
|
5171
|
-
? `\n${theme.fg("dim", "Cache Re-billed:")}
|
|
5187
|
+
? `\n${theme.fg("dim", "Cache Re-billed:")} ${formatCost(cacheWaste.missedCost)} ${theme.fg("dim", `(${detail})`)}`
|
|
5172
5188
|
: `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
|
|
5173
5189
|
}
|
|
5174
5190
|
}
|
|
@@ -75,6 +75,13 @@ export declare class RpcClient {
|
|
|
75
75
|
* Abort current operation.
|
|
76
76
|
*/
|
|
77
77
|
abort(): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Clear queued steering and follow-up messages, returning their text.
|
|
80
|
+
*/
|
|
81
|
+
clearQueue(): Promise<{
|
|
82
|
+
steering: string[];
|
|
83
|
+
followUp: string[];
|
|
84
|
+
}>;
|
|
78
85
|
/**
|
|
79
86
|
* Start a new session, optionally with parent tracking.
|
|
80
87
|
* @param parentSession - Optional parent session path for lineage tracking
|
|
@@ -153,6 +153,13 @@ export class RpcClient {
|
|
|
153
153
|
async abort() {
|
|
154
154
|
await this.send({ type: "abort" });
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Clear queued steering and follow-up messages, returning their text.
|
|
158
|
+
*/
|
|
159
|
+
async clearQueue() {
|
|
160
|
+
const response = await this.send({ type: "clear_queue" });
|
|
161
|
+
return this.getData(response);
|
|
162
|
+
}
|
|
156
163
|
/**
|
|
157
164
|
* Start a new session, optionally with parent tracking.
|
|
158
165
|
* @param parentSession - Optional parent session path for lineage tracking
|
|
@@ -331,6 +331,9 @@ export async function runRpcMode(runtimeHost) {
|
|
|
331
331
|
await session.abort();
|
|
332
332
|
return success(id, "abort");
|
|
333
333
|
}
|
|
334
|
+
case "clear_queue": {
|
|
335
|
+
return success(id, "clear_queue", session.clearQueue());
|
|
336
|
+
}
|
|
334
337
|
case "new_session": {
|
|
335
338
|
const options = command.parentSession ? { parentSession: command.parentSession } : undefined;
|
|
336
339
|
const result = await runtimeHost.newSession(options);
|
|
@@ -30,6 +30,9 @@ export type RpcCommand = {
|
|
|
30
30
|
} | {
|
|
31
31
|
id?: string;
|
|
32
32
|
type: "abort";
|
|
33
|
+
} | {
|
|
34
|
+
id?: string;
|
|
35
|
+
type: "clear_queue";
|
|
33
36
|
} | {
|
|
34
37
|
id?: string;
|
|
35
38
|
type: "new_session";
|
|
@@ -206,6 +209,15 @@ export type RpcResponse = {
|
|
|
206
209
|
type: "response";
|
|
207
210
|
command: "abort";
|
|
208
211
|
success: true;
|
|
212
|
+
} | {
|
|
213
|
+
id?: string;
|
|
214
|
+
type: "response";
|
|
215
|
+
command: "clear_queue";
|
|
216
|
+
success: true;
|
|
217
|
+
data: {
|
|
218
|
+
steering: string[];
|
|
219
|
+
followUp: string[];
|
|
220
|
+
};
|
|
209
221
|
} | {
|
|
210
222
|
id?: string;
|
|
211
223
|
type: "response";
|
package/dist/utils/shell.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { delimiter } from "node:path";
|
|
2
|
+
import { delimiter, join } from "node:path";
|
|
3
3
|
import { spawn, spawnSync } from "child_process";
|
|
4
4
|
import { getBinDir } from "../config.js";
|
|
5
5
|
/**
|
|
@@ -183,16 +183,18 @@ export function killTrackedDetachedChildren() {
|
|
|
183
183
|
*/
|
|
184
184
|
export function killProcessTree(pid) {
|
|
185
185
|
if (process.platform === "win32") {
|
|
186
|
-
// Use
|
|
186
|
+
// Use the trusted System32 executable so cleanup does not depend on PATH.
|
|
187
187
|
try {
|
|
188
|
-
spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
|
|
188
|
+
const child = spawn(join(process.env.SystemRoot ?? "C:\\Windows", "System32", "taskkill.exe"), ["/F", "/T", "/PID", String(pid)], {
|
|
189
189
|
stdio: "ignore",
|
|
190
190
|
detached: true,
|
|
191
191
|
windowsHide: true,
|
|
192
192
|
});
|
|
193
|
+
// A failed spawn emits "error" asynchronously; consume it to avoid crashing Node.
|
|
194
|
+
child.once("error", () => { });
|
|
193
195
|
}
|
|
194
196
|
catch {
|
|
195
|
-
// Ignore errors if taskkill fails
|
|
197
|
+
// Ignore errors if taskkill fails.
|
|
196
198
|
}
|
|
197
199
|
}
|
|
198
200
|
else {
|
package/docs/settings.md
CHANGED
|
@@ -64,6 +64,7 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
|
|
|
64
64
|
| `showHardwareCursor` | boolean | `false` | Show the terminal cursor while TUI positions it for IME support |
|
|
65
65
|
| `tuiMode` | string | `"fullscreen"` | TUI layout: `"fullscreen"` (default) or `"regular"`. `fullscreen` uses Pi's native alternate-screen viewport with a fixed dock for the input editor, status, and widgets; set `"regular"` to opt out |
|
|
66
66
|
| `fullscreenScrollbar` | string | `"auto"` | Fullscreen transcript scrollbar: `"auto"`, `"always"`, or `"hidden"`; configurable in `/settings`. No effect in regular TUI mode |
|
|
67
|
+
| `fullscreenCopyOnSelect` | boolean | `true` | Automatically copy selected text in fullscreen mode; disable to copy selections with Ctrl+X. Configurable in `/settings`. No effect in regular TUI mode |
|
|
67
68
|
|
|
68
69
|
### Telemetry and update checks
|
|
69
70
|
|
|
@@ -169,6 +170,9 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
|
|
|
169
170
|
| `terminal.showImages` | boolean | `true` | Show images in terminal (if supported) |
|
|
170
171
|
| `terminal.imageWidthCells` | number | `60` | Preferred inline image width in terminal cells |
|
|
171
172
|
| `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) |
|
|
173
|
+
| `terminal.images` | string | `"auto"` | Terminal image protocol: `"kitty"`, `"iterm2"`, `"auto"`, or `false` to disable inline images |
|
|
174
|
+
| `terminal.trueColor` | boolean/string | `"auto"` | Pin true-color support (`true`/`false`) or keep `"auto"` detection |
|
|
175
|
+
| `terminal.hyperlinks` | boolean/string | `"auto"` | Pin hyperlink support (`true`/`false`) or keep `"auto"` detection |
|
|
172
176
|
| `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max |
|
|
173
177
|
| `images.blockImages` | boolean | `false` | Block all images from being sent to LLM |
|
|
174
178
|
| `images.imageCaptionModel` | string | unset | Vision model (`provider/model`) to describe images when the active model cannot accept images; the caption text is used in place of the image (e.g. `tokenin/gemma-4`, `tokenin/kimi-k3`) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selesai/code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Maintained, extension-first Pi coding agent with built-in workflows, subagents, web research, questions, skills, and an enhanced terminal UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"acorn": "8.18.0",
|
|
63
63
|
"@ast-grep/cli": "0.45.0",
|
|
64
|
-
"@earendil-works/pi-agent-core": "0.84.
|
|
65
|
-
"@earendil-works/pi-ai": "0.84.
|
|
66
|
-
"@earendil-works/pi-tui": "0.84.
|
|
64
|
+
"@earendil-works/pi-agent-core": "0.84.4",
|
|
65
|
+
"@earendil-works/pi-ai": "0.84.4",
|
|
66
|
+
"@earendil-works/pi-tui": "0.84.4",
|
|
67
67
|
"@mozilla/readability": "^0.6.0",
|
|
68
68
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
69
69
|
"chalk": "5.6.2",
|