@code-yeongyu/senpi 2026.5.15-2 → 2026.5.15-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 +10 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.d.ts +97 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.js +420 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +11 -2
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +26 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +0 -3
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +64 -23
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/working-status.d.ts +15 -0
- package/dist/modes/interactive/working-status.d.ts.map +1 -0
- package/dist/modes/interactive/working-status.js +60 -0
- package/dist/modes/interactive/working-status.js.map +1 -0
- package/package.json +4 -4
|
@@ -60,6 +60,7 @@ import { UserMessageComponent } from "./components/user-message.js";
|
|
|
60
60
|
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
|
61
61
|
import { resolveStartupToolPaths } from "./startup-tools.js";
|
|
62
62
|
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";
|
|
63
64
|
function isExpandable(obj) {
|
|
64
65
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
65
66
|
}
|
|
@@ -77,6 +78,58 @@ class ExpandableText extends Text {
|
|
|
77
78
|
}
|
|
78
79
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
79
80
|
const DEFAULT_WORKING_STATUS_REFRESH_INTERVAL_MS = 600;
|
|
81
|
+
const DEFAULT_WORKING_STATUS_MESSAGE_ANIMATION_INTERVAL_MS = 32;
|
|
82
|
+
const RGB_FOREGROUND_PATTERN = /\x1b\[38;2;(\d+);(\d+);(\d+)m/;
|
|
83
|
+
const DARK_DEFAULT_WORKING_TEXT_RGB = { r: 229, g: 229, b: 231 };
|
|
84
|
+
const LIGHT_DEFAULT_WORKING_TEXT_RGB = { r: 17, g: 17, b: 17 };
|
|
85
|
+
const DARK_DEFAULT_WORKING_BASE_RGB = { r: 102, g: 102, b: 102 };
|
|
86
|
+
const LIGHT_DEFAULT_WORKING_BASE_RGB = { r: 118, g: 118, b: 118 };
|
|
87
|
+
function parseAnsiRgbForeground(ansi) {
|
|
88
|
+
const match = RGB_FOREGROUND_PATTERN.exec(ansi);
|
|
89
|
+
const red = match?.[1];
|
|
90
|
+
const green = match?.[2];
|
|
91
|
+
const blue = match?.[3];
|
|
92
|
+
if (red === undefined || green === undefined || blue === undefined) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
r: Number.parseInt(red, 10),
|
|
97
|
+
g: Number.parseInt(green, 10),
|
|
98
|
+
b: Number.parseInt(blue, 10),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function isWorkingLightTheme() {
|
|
102
|
+
return theme.name?.toLowerCase().includes("light") ?? false;
|
|
103
|
+
}
|
|
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
|
+
function formatWorkingStatusShimmerText(text, intensity) {
|
|
116
|
+
if (theme.getColorMode() !== "truecolor") {
|
|
117
|
+
if (intensity < 0.2) {
|
|
118
|
+
return theme.fg("dim", text);
|
|
119
|
+
}
|
|
120
|
+
if (intensity < 0.6) {
|
|
121
|
+
return theme.fg("text", text);
|
|
122
|
+
}
|
|
123
|
+
return theme.bold(theme.fg("text", text));
|
|
124
|
+
}
|
|
125
|
+
const lightTheme = isWorkingLightTheme();
|
|
126
|
+
const base = parseAnsiRgbForeground(theme.getFgAnsi("dim")) ??
|
|
127
|
+
(lightTheme ? LIGHT_DEFAULT_WORKING_BASE_RGB : DARK_DEFAULT_WORKING_BASE_RGB);
|
|
128
|
+
const highlight = parseAnsiRgbForeground(theme.getFgAnsi("text")) ??
|
|
129
|
+
(lightTheme ? LIGHT_DEFAULT_WORKING_TEXT_RGB : DARK_DEFAULT_WORKING_TEXT_RGB);
|
|
130
|
+
const color = mixRgbColor(base, highlight, intensity * 0.9);
|
|
131
|
+
return `\x1b[1m\x1b[38;2;${color.r};${color.g};${color.b}m${text}\x1b[39m\x1b[22m`;
|
|
132
|
+
}
|
|
80
133
|
function isDeadTerminalError(error) {
|
|
81
134
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
82
135
|
return false;
|
|
@@ -84,23 +137,6 @@ function isDeadTerminalError(error) {
|
|
|
84
137
|
const code = error.code;
|
|
85
138
|
return code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);
|
|
86
139
|
}
|
|
87
|
-
export function formatWorkingElapsedSeconds(elapsedSeconds) {
|
|
88
|
-
const totalSeconds = Math.max(0, Math.floor(elapsedSeconds));
|
|
89
|
-
const seconds = totalSeconds % 60;
|
|
90
|
-
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
91
|
-
if (totalSeconds < 60) {
|
|
92
|
-
return `${totalSeconds}s`;
|
|
93
|
-
}
|
|
94
|
-
if (totalSeconds < 3600) {
|
|
95
|
-
return `${totalMinutes}m ${seconds.toString().padStart(2, "0")}s`;
|
|
96
|
-
}
|
|
97
|
-
const hours = Math.floor(totalMinutes / 60);
|
|
98
|
-
const minutes = totalMinutes % 60;
|
|
99
|
-
return `${hours}h ${minutes.toString().padStart(2, "0")}m ${seconds.toString().padStart(2, "0")}s`;
|
|
100
|
-
}
|
|
101
|
-
export function formatWorkingStatusMessage(message, elapsedSeconds, interruptKey) {
|
|
102
|
-
return `${message} (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;
|
|
103
|
-
}
|
|
104
140
|
const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage.";
|
|
105
141
|
function isAnthropicSubscriptionAuthKey(apiKey) {
|
|
106
142
|
return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");
|
|
@@ -1308,11 +1344,8 @@ export class InteractiveMode {
|
|
|
1308
1344
|
}
|
|
1309
1345
|
return Math.max(0, Math.floor((Date.now() - this.workingStartedAt) / 1000));
|
|
1310
1346
|
}
|
|
1311
|
-
getWorkingStatusMessage() {
|
|
1312
|
-
return formatWorkingStatusMessage(this.getWorkingLoaderMessage(), this.getWorkingElapsedSeconds(), keyText("app.interrupt"));
|
|
1313
|
-
}
|
|
1314
1347
|
refreshWorkingLoaderMessage() {
|
|
1315
|
-
this.loadingAnimation?.setMessage(this.
|
|
1348
|
+
this.loadingAnimation?.setMessage(this.getWorkingLoaderMessage());
|
|
1316
1349
|
}
|
|
1317
1350
|
startWorkingElapsedTimer() {
|
|
1318
1351
|
this.stopWorkingElapsedTimer();
|
|
@@ -1329,12 +1362,20 @@ export class InteractiveMode {
|
|
|
1329
1362
|
}
|
|
1330
1363
|
getWorkingIndicatorOptions() {
|
|
1331
1364
|
return (this.workingIndicatorOptions ?? {
|
|
1332
|
-
frames: [theme.fg("accent", "•")
|
|
1365
|
+
frames: [theme.fg("accent", "•")],
|
|
1333
1366
|
intervalMs: DEFAULT_WORKING_STATUS_REFRESH_INTERVAL_MS,
|
|
1367
|
+
messageFormatter: (message, animationElapsedMs) => formatWorkingStatusMessageFrame(message, this.getWorkingElapsedSeconds(), keyText("app.interrupt"), animationElapsedMs, {
|
|
1368
|
+
base: (text) => theme.fg("dim", text),
|
|
1369
|
+
glow: (text) => theme.fg("text", text),
|
|
1370
|
+
highlight: (text) => theme.bold(theme.fg("text", text)),
|
|
1371
|
+
shimmer: formatWorkingStatusShimmerText,
|
|
1372
|
+
suffix: (text) => theme.fg("dim", text),
|
|
1373
|
+
}),
|
|
1374
|
+
messageIntervalMs: DEFAULT_WORKING_STATUS_MESSAGE_ANIMATION_INTERVAL_MS,
|
|
1334
1375
|
});
|
|
1335
1376
|
}
|
|
1336
1377
|
createWorkingLoader() {
|
|
1337
|
-
return new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), this.
|
|
1378
|
+
return new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), this.getWorkingLoaderMessage(), this.getWorkingIndicatorOptions());
|
|
1338
1379
|
}
|
|
1339
1380
|
stopWorkingLoader() {
|
|
1340
1381
|
this.stopWorkingElapsedTimer();
|