@code-yeongyu/senpi 2026.5.16 → 2026.5.18-2
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 +75 -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.d.ts.map +1 -1
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +47 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +22 -14
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/preview-format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/preview-format.js +5 -128
- package/dist/core/extensions/builtin/gpt-apply-patch/preview-format.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +64 -9
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +5 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +72 -31
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +6 -4
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +38 -8
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +2 -5
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/diff-render.d.ts +13 -0
- package/dist/core/tools/diff-render.d.ts.map +1 -0
- package/dist/core/tools/diff-render.js +130 -0
- package/dist/core/tools/diff-render.js.map +1 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +8 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +28 -7
- package/dist/core/tools/write.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +2 -2
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +7 -4
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +0 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +42 -44
- package/dist/modes/interactive/components/footer.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 +55 -48
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-info-format.d.ts +3 -0
- package/dist/modes/interactive/session-info-format.d.ts.map +1 -0
- package/dist/modes/interactive/session-info-format.js +44 -0
- package/dist/modes/interactive/session-info-format.js.map +1 -0
- package/dist/modes/interactive/working-status.d.ts +6 -0
- package/dist/modes/interactive/working-status.d.ts.map +1 -1
- package/dist/modes/interactive/working-status.js +11 -0
- package/dist/modes/interactive/working-status.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +3 -4
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/senpi +5 -1
- package/dist/utils/child-process.d.ts +7 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +60 -7
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +4 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/custom-provider.md +55 -0
- package/docs/extensions.md +1 -1
- package/docs/settings.md +1 -3
- package/docs/skills.md +3 -4
- 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/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +6 -6
|
@@ -58,9 +58,10 @@ import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
|
58
58
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
59
59
|
import { UserMessageComponent } from "./components/user-message.js";
|
|
60
60
|
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
|
61
|
+
import { formatSessionInfo } from "./session-info-format.js";
|
|
61
62
|
import { resolveStartupToolPaths } from "./startup-tools.js";
|
|
62
63
|
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
|
|
63
|
-
import { formatWorkingStatusMessageFrame } from "./working-status.js";
|
|
64
|
+
import { blendWorkingStatusShimmerRgbColor, formatWorkingStatusMessageFrame, } from "./working-status.js";
|
|
64
65
|
function isExpandable(obj) {
|
|
65
66
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
66
67
|
}
|
|
@@ -101,17 +102,6 @@ function parseAnsiRgbForeground(ansi) {
|
|
|
101
102
|
function isWorkingLightTheme() {
|
|
102
103
|
return theme.name?.toLowerCase().includes("light") ?? false;
|
|
103
104
|
}
|
|
104
|
-
function clampColorChannel(value) {
|
|
105
|
-
return Math.max(0, Math.min(255, Math.round(value)));
|
|
106
|
-
}
|
|
107
|
-
function mixRgbColor(base, highlight, amount) {
|
|
108
|
-
const clampedAmount = Math.max(0, Math.min(1, amount));
|
|
109
|
-
return {
|
|
110
|
-
r: clampColorChannel(base.r + (highlight.r - base.r) * clampedAmount),
|
|
111
|
-
g: clampColorChannel(base.g + (highlight.g - base.g) * clampedAmount),
|
|
112
|
-
b: clampColorChannel(base.b + (highlight.b - base.b) * clampedAmount),
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
105
|
function formatWorkingStatusShimmerText(text, intensity) {
|
|
116
106
|
if (theme.getColorMode() !== "truecolor") {
|
|
117
107
|
if (intensity < 0.2) {
|
|
@@ -123,11 +113,11 @@ function formatWorkingStatusShimmerText(text, intensity) {
|
|
|
123
113
|
return theme.bold(theme.fg("text", text));
|
|
124
114
|
}
|
|
125
115
|
const lightTheme = isWorkingLightTheme();
|
|
126
|
-
const
|
|
116
|
+
const highlight = parseAnsiRgbForeground(theme.getFgAnsi("dim")) ??
|
|
127
117
|
(lightTheme ? LIGHT_DEFAULT_WORKING_BASE_RGB : DARK_DEFAULT_WORKING_BASE_RGB);
|
|
128
|
-
const
|
|
118
|
+
const base = parseAnsiRgbForeground(theme.getFgAnsi("text")) ??
|
|
129
119
|
(lightTheme ? LIGHT_DEFAULT_WORKING_TEXT_RGB : DARK_DEFAULT_WORKING_TEXT_RGB);
|
|
130
|
-
const color =
|
|
120
|
+
const color = blendWorkingStatusShimmerRgbColor(highlight, base, intensity * 0.9);
|
|
131
121
|
return `\x1b[1m\x1b[38;2;${color.r};${color.g};${color.b}m${text}\x1b[39m\x1b[22m`;
|
|
132
122
|
}
|
|
133
123
|
function isDeadTerminalError(error) {
|
|
@@ -448,6 +438,19 @@ export class InteractiveMode {
|
|
|
448
438
|
// Startup should never wait for tool downloads. Missing tools are resolved
|
|
449
439
|
// lazily by the tools that need them.
|
|
450
440
|
this.fdPath = resolveStartupToolPaths().fdPath;
|
|
441
|
+
if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
|
|
442
|
+
const modelList = this.session.scopedModels
|
|
443
|
+
.map((sm) => {
|
|
444
|
+
const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
|
|
445
|
+
return `${sm.model.id}${thinkingStr}`;
|
|
446
|
+
})
|
|
447
|
+
.join(", ");
|
|
448
|
+
const cycleKeys = this.keybindings.getKeys("app.model.cycleForward");
|
|
449
|
+
const cycleHint = cycleKeys.length > 0
|
|
450
|
+
? theme.fg("muted", ` (${formatKeyText(cycleKeys.join("/"), { capitalize: true })} to cycle)`)
|
|
451
|
+
: "";
|
|
452
|
+
console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
|
|
453
|
+
}
|
|
451
454
|
// Add header container as first child
|
|
452
455
|
this.ui.addChild(this.headerContainer);
|
|
453
456
|
// Add header with keybindings from config (unless silenced)
|
|
@@ -1947,8 +1950,8 @@ export class InteractiveMode {
|
|
|
1947
1950
|
// Set up handlers on defaultEditor - they use this.editor for text access
|
|
1948
1951
|
// so they work correctly regardless of which editor is active
|
|
1949
1952
|
this.defaultEditor.onEscape = () => {
|
|
1950
|
-
if (this.session.isStreaming) {
|
|
1951
|
-
this.
|
|
1953
|
+
if (this.session.isStreaming || this.session.retryAttempt > 0) {
|
|
1954
|
+
void this.abortAndFireQueuedMessages();
|
|
1952
1955
|
}
|
|
1953
1956
|
else if (this.session.isBashRunning) {
|
|
1954
1957
|
this.session.abortBash();
|
|
@@ -2470,11 +2473,11 @@ export class InteractiveMode {
|
|
|
2470
2473
|
break;
|
|
2471
2474
|
}
|
|
2472
2475
|
case "auto_retry_start": {
|
|
2473
|
-
//
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2476
|
+
// During retry waits, isStreaming flips false between attempts. The main Esc handler
|
|
2477
|
+
// keys off both isStreaming and retryAttempt so we keep the same close-out path here;
|
|
2478
|
+
// no separate retry-only handler is installed (the prior one only called
|
|
2479
|
+
// session.abortRetry() and left queued steering messages stranded).
|
|
2480
|
+
this.retryEscapeHandler = undefined;
|
|
2478
2481
|
// Show retry indicator
|
|
2479
2482
|
this.statusContainer.clear();
|
|
2480
2483
|
this.retryCountdown?.dispose();
|
|
@@ -3142,6 +3145,35 @@ export class InteractiveMode {
|
|
|
3142
3145
|
}
|
|
3143
3146
|
return allQueued.length;
|
|
3144
3147
|
}
|
|
3148
|
+
/**
|
|
3149
|
+
* User-abort path that drains the queue, aborts the active run (and any in-flight retry),
|
|
3150
|
+
* waits for settle, then re-fires queued messages as a single fresh prompt.
|
|
3151
|
+
*
|
|
3152
|
+
* Behavior contract:
|
|
3153
|
+
* - clearAllQueues() is called synchronously so the pending-messages display empties immediately.
|
|
3154
|
+
* - `await session.abort()` ensures the previous run is fully idle before the fresh prompt fires,
|
|
3155
|
+
* so it starts a new turn instead of being re-queued as steering behind the dying run.
|
|
3156
|
+
* - When no messages were queued, the helper is just a sync clear + abort (no fresh prompt).
|
|
3157
|
+
* - Failures from the fresh prompt are surfaced via showError but do not throw.
|
|
3158
|
+
*/
|
|
3159
|
+
async abortAndFireQueuedMessages() {
|
|
3160
|
+
const { steering, followUp } = this.clearAllQueues();
|
|
3161
|
+
const allQueued = [...steering, ...followUp];
|
|
3162
|
+
this.updatePendingMessagesDisplay();
|
|
3163
|
+
await this.session.abort();
|
|
3164
|
+
if (allQueued.length === 0) {
|
|
3165
|
+
return 0;
|
|
3166
|
+
}
|
|
3167
|
+
const queuedText = allQueued.join("\n\n");
|
|
3168
|
+
try {
|
|
3169
|
+
await this.session.prompt(queuedText);
|
|
3170
|
+
}
|
|
3171
|
+
catch (error) {
|
|
3172
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
3173
|
+
this.showError(`Failed to fire queued message: ${errorMessage}`);
|
|
3174
|
+
}
|
|
3175
|
+
return allQueued.length;
|
|
3176
|
+
}
|
|
3145
3177
|
queueCompactionMessage(text, mode) {
|
|
3146
3178
|
this.compactionQueuedMessages.push({ text, mode });
|
|
3147
3179
|
this.editor.addToHistory?.(text);
|
|
@@ -4398,32 +4430,7 @@ export class InteractiveMode {
|
|
|
4398
4430
|
handleSessionCommand() {
|
|
4399
4431
|
const stats = this.session.getSessionStats();
|
|
4400
4432
|
const sessionName = this.sessionManager.getSessionName();
|
|
4401
|
-
|
|
4402
|
-
if (sessionName) {
|
|
4403
|
-
info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
|
|
4404
|
-
}
|
|
4405
|
-
info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
|
|
4406
|
-
info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
|
|
4407
|
-
info += `${theme.bold("Messages")}\n`;
|
|
4408
|
-
info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
|
|
4409
|
-
info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
|
|
4410
|
-
info += `${theme.fg("dim", "Tool Calls:")} ${stats.toolCalls}\n`;
|
|
4411
|
-
info += `${theme.fg("dim", "Tool Results:")} ${stats.toolResults}\n`;
|
|
4412
|
-
info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n\n`;
|
|
4413
|
-
info += `${theme.bold("Tokens")}\n`;
|
|
4414
|
-
info += `${theme.fg("dim", "Input:")} ${stats.tokens.input.toLocaleString()}\n`;
|
|
4415
|
-
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
4416
|
-
if (stats.tokens.cacheRead > 0) {
|
|
4417
|
-
info += `${theme.fg("dim", "Cache Read:")} ${stats.tokens.cacheRead.toLocaleString()}\n`;
|
|
4418
|
-
}
|
|
4419
|
-
if (stats.tokens.cacheWrite > 0) {
|
|
4420
|
-
info += `${theme.fg("dim", "Cache Write:")} ${stats.tokens.cacheWrite.toLocaleString()}\n`;
|
|
4421
|
-
}
|
|
4422
|
-
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
4423
|
-
if (stats.cost > 0) {
|
|
4424
|
-
info += `\n${theme.bold("Cost")}\n`;
|
|
4425
|
-
info += `${theme.fg("dim", "Total:")} ${stats.cost.toFixed(4)}`;
|
|
4426
|
-
}
|
|
4433
|
+
const info = formatSessionInfo(stats, sessionName);
|
|
4427
4434
|
this.chatContainer.addChild(new Spacer(1));
|
|
4428
4435
|
this.chatContainer.addChild(new Text(info, 1, 0));
|
|
4429
4436
|
this.ui.requestRender();
|