@code-yeongyu/senpi 2026.8.27 → 2026.8.28-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 +83 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +5 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +1 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -0
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/credential-accounts.d.ts +31 -0
- package/dist/core/credential-accounts.d.ts.map +1 -0
- package/dist/core/credential-accounts.js +135 -0
- package/dist/core/credential-accounts.js.map +1 -0
- package/dist/core/credential-pool/classify.d.ts +6 -1
- package/dist/core/credential-pool/classify.d.ts.map +1 -1
- package/dist/core/credential-pool/classify.js +22 -5
- package/dist/core/credential-pool/classify.js.map +1 -1
- package/dist/core/credential-pool/failover.d.ts +8 -0
- package/dist/core/credential-pool/failover.d.ts.map +1 -1
- package/dist/core/credential-pool/failover.js +24 -6
- package/dist/core/credential-pool/failover.js.map +1 -1
- package/dist/core/credential-pool/rotation-stream.d.ts +13 -2
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-stream.js +97 -10
- package/dist/core/credential-pool/rotation-stream.js.map +1 -1
- package/dist/core/extensions/builtin/account/index.d.ts +9 -0
- package/dist/core/extensions/builtin/account/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/account/index.js +69 -0
- package/dist/core/extensions/builtin/account/index.js.map +1 -0
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +7 -0
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.js +10 -3
- package/dist/core/extensions/builtin/imagegen/index.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +4 -0
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
- package/dist/core/extensions/builtin/service-tier.js +13 -0
- package/dist/core/extensions/builtin/service-tier.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +4 -2
- package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
- package/dist/core/model-config-schema.d.ts +4 -4
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +74 -37
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/retry-fallback/chains.d.ts +23 -1
- package/dist/core/retry-fallback/chains.d.ts.map +1 -1
- package/dist/core/retry-fallback/chains.js +59 -3
- package/dist/core/retry-fallback/chains.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +9 -2
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +9 -0
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/retry-fallback/validate.js +1 -1
- package/dist/core/retry-fallback/validate.js.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +9 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +31 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/main.d.ts +7 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +22 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/app-server/server/account.d.ts.map +1 -1
- package/dist/modes/app-server/server/account.js +5 -5
- package/dist/modes/app-server/server/account.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +11 -3
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +31 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/grok/chrome.d.ts +4 -4
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
- package/dist/modes/interactive/grok/chrome.js.map +1 -1
- package/dist/modes/interactive/grok/footer.d.ts +3 -3
- package/dist/modes/interactive/grok/footer.d.ts.map +1 -1
- package/dist/modes/interactive/grok/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +16 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +321 -36
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +295 -250
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +144 -29
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +14 -4
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +90 -8
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +118 -23
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +3 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +164 -2
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +22 -0
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +153 -14
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +4 -0
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +16 -0
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +40 -3
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/docs/providers.md +48 -0
- package/docs/rpc.md +43 -4
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +26 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +13 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/inline-worker.ts +15 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +14 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js +20 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts +21 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js +27 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts +24 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js +7 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -224,6 +224,19 @@ function isDeadTerminalError(error) {
|
|
|
224
224
|
}
|
|
225
225
|
return false;
|
|
226
226
|
}
|
|
227
|
+
function storageWriteCrashMessage(error) {
|
|
228
|
+
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
const code = error.code;
|
|
232
|
+
if (code === "EDQUOT") {
|
|
233
|
+
return "Disk quota exceeded (EDQUOT). Free space or quota on the filesystem, then retry.";
|
|
234
|
+
}
|
|
235
|
+
if (code === "ENOSPC") {
|
|
236
|
+
return "Disk full (ENOSPC). Free space on the filesystem, then retry.";
|
|
237
|
+
}
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
227
240
|
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. Disable this warning in /settings.";
|
|
228
241
|
function isAnthropicSubscriptionAuthKey(apiKey) {
|
|
229
242
|
return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");
|
|
@@ -490,6 +503,8 @@ export class InteractiveMode {
|
|
|
490
503
|
this.ui.setMaxRenderFps(fps);
|
|
491
504
|
}
|
|
492
505
|
// Convenience accessors
|
|
506
|
+
// The session may be the local AgentSession or the shared-host RPC proxy; the
|
|
507
|
+
// four reads widened on InteractiveSession must be awaited at every call site.
|
|
493
508
|
get session() {
|
|
494
509
|
return this.runtimeHost.session;
|
|
495
510
|
}
|
|
@@ -2985,7 +3000,7 @@ export class InteractiveMode {
|
|
|
2985
3000
|
this.showTreeSelector();
|
|
2986
3001
|
}
|
|
2987
3002
|
else {
|
|
2988
|
-
this.showUserMessageSelector();
|
|
3003
|
+
void this.showUserMessageSelector().catch((error) => this.showError(error instanceof Error ? error.message : String(error)));
|
|
2989
3004
|
}
|
|
2990
3005
|
this.lastEscapeTime = 0;
|
|
2991
3006
|
}
|
|
@@ -2999,7 +3014,9 @@ export class InteractiveMode {
|
|
|
2999
3014
|
this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
|
|
3000
3015
|
this.defaultEditor.onCtrlD = () => this.handleCtrlD();
|
|
3001
3016
|
this.defaultEditor.onAction("app.suspend", () => this.handleCtrlZ());
|
|
3002
|
-
this.defaultEditor.onAction("app.thinking.cycle", () =>
|
|
3017
|
+
this.defaultEditor.onAction("app.thinking.cycle", () => {
|
|
3018
|
+
void this.cycleThinkingLevel().catch((error) => this.showError(error instanceof Error ? error.message : String(error)));
|
|
3019
|
+
});
|
|
3003
3020
|
this.defaultEditor.onAction("app.model.cycleForward", () => this.cycleModel("forward"));
|
|
3004
3021
|
this.defaultEditor.onAction("app.model.cycleBackward", () => this.cycleModel("backward"));
|
|
3005
3022
|
// Global debug handler on TUI (works regardless of focus)
|
|
@@ -3021,7 +3038,7 @@ export class InteractiveMode {
|
|
|
3021
3038
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
3022
3039
|
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
3023
3040
|
this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
|
|
3024
|
-
this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
|
|
3041
|
+
this.defaultEditor.onAction("app.session.fork", () => void this.showUserMessageSelector().catch((error) => this.showError(error instanceof Error ? error.message : String(error))));
|
|
3025
3042
|
this.defaultEditor.onAction("app.session.resume", () => this.showSessionSelector());
|
|
3026
3043
|
this.defaultEditor.onChange = (text) => {
|
|
3027
3044
|
const wasBashMode = this.isBashMode;
|
|
@@ -3177,197 +3194,158 @@ export class InteractiveMode {
|
|
|
3177
3194
|
}
|
|
3178
3195
|
setupEditorSubmitHandler() {
|
|
3179
3196
|
this.defaultEditor.onSubmit = async (text) => {
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
if (text === "/favorite-models") {
|
|
3199
|
-
this.editor.setText("");
|
|
3200
|
-
await this.showFavoriteModelsSelector();
|
|
3201
|
-
return;
|
|
3202
|
-
}
|
|
3203
|
-
if (text === "/scoped-models") {
|
|
3204
|
-
this.editor.setText("");
|
|
3205
|
-
this.showScopedModelsSelector();
|
|
3206
|
-
return;
|
|
3207
|
-
}
|
|
3208
|
-
if (text === "/model" || text.startsWith("/model ")) {
|
|
3209
|
-
const searchTerm = text.startsWith("/model ") ? text.slice(7).trim() : undefined;
|
|
3210
|
-
this.editor.setText("");
|
|
3211
|
-
await this.handleModelCommand(searchTerm);
|
|
3212
|
-
return;
|
|
3213
|
-
}
|
|
3214
|
-
if (text === "/export" || text.startsWith("/export ")) {
|
|
3215
|
-
await this.handleExportCommand(text);
|
|
3216
|
-
this.editor.setText("");
|
|
3217
|
-
return;
|
|
3218
|
-
}
|
|
3219
|
-
if (text === "/import" || text.startsWith("/import ")) {
|
|
3220
|
-
await this.handleImportCommand(text);
|
|
3221
|
-
this.editor.setText("");
|
|
3222
|
-
return;
|
|
3223
|
-
}
|
|
3224
|
-
if (text === "/share") {
|
|
3225
|
-
await this.handleShareCommand();
|
|
3226
|
-
this.editor.setText("");
|
|
3227
|
-
return;
|
|
3228
|
-
}
|
|
3229
|
-
if (text === "/copy") {
|
|
3230
|
-
await this.handleCopyCommand();
|
|
3231
|
-
this.editor.setText("");
|
|
3232
|
-
return;
|
|
3233
|
-
}
|
|
3234
|
-
if (text === "/name" || text.startsWith("/name ")) {
|
|
3235
|
-
this.handleNameCommand(text);
|
|
3236
|
-
this.editor.setText("");
|
|
3237
|
-
return;
|
|
3238
|
-
}
|
|
3239
|
-
if (text === "/session") {
|
|
3240
|
-
this.handleSessionCommand();
|
|
3241
|
-
this.editor.setText("");
|
|
3242
|
-
return;
|
|
3243
|
-
}
|
|
3244
|
-
if (text === "/changelog") {
|
|
3245
|
-
this.handleChangelogCommand();
|
|
3246
|
-
this.editor.setText("");
|
|
3247
|
-
return;
|
|
3248
|
-
}
|
|
3249
|
-
if (text === "/keybindings") {
|
|
3250
|
-
this.editor.setText("");
|
|
3251
|
-
await this.handleKeybindingsCommand();
|
|
3252
|
-
return;
|
|
3253
|
-
}
|
|
3254
|
-
if (text === "/hotkeys") {
|
|
3255
|
-
this.handleHotkeysCommand();
|
|
3256
|
-
this.editor.setText("");
|
|
3257
|
-
return;
|
|
3258
|
-
}
|
|
3259
|
-
if (text === "/fork") {
|
|
3260
|
-
this.showUserMessageSelector();
|
|
3261
|
-
this.editor.setText("");
|
|
3262
|
-
return;
|
|
3263
|
-
}
|
|
3264
|
-
if (text === "/clone") {
|
|
3265
|
-
this.editor.setText("");
|
|
3266
|
-
await this.handleCloneCommand();
|
|
3267
|
-
return;
|
|
3268
|
-
}
|
|
3269
|
-
if (text === "/tree") {
|
|
3270
|
-
this.showTreeSelector();
|
|
3271
|
-
this.editor.setText("");
|
|
3272
|
-
return;
|
|
3273
|
-
}
|
|
3274
|
-
if (text === "/trust") {
|
|
3275
|
-
this.showTrustSelector();
|
|
3276
|
-
this.editor.setText("");
|
|
3277
|
-
return;
|
|
3278
|
-
}
|
|
3279
|
-
if (text === "/login" || text.startsWith("/login ")) {
|
|
3280
|
-
const providerRef = text.startsWith("/login ") ? text.slice(7).trim() : undefined;
|
|
3281
|
-
this.editor.setText("");
|
|
3282
|
-
await this.handleLoginCommand(providerRef);
|
|
3283
|
-
return;
|
|
3284
|
-
}
|
|
3285
|
-
if (text === "/logout") {
|
|
3286
|
-
this.showOAuthSelector("logout");
|
|
3287
|
-
this.editor.setText("");
|
|
3288
|
-
return;
|
|
3289
|
-
}
|
|
3290
|
-
if (text === "/new") {
|
|
3291
|
-
this.editor.setText("");
|
|
3292
|
-
await this.handleClearCommand();
|
|
3293
|
-
return;
|
|
3294
|
-
}
|
|
3295
|
-
if (text === "/compact" || text.startsWith("/compact ")) {
|
|
3296
|
-
const customInstructions = text.startsWith("/compact ") ? text.slice(9).trim() : undefined;
|
|
3297
|
-
this.editor.setText("");
|
|
3298
|
-
await this.handleCompactCommand(customInstructions);
|
|
3299
|
-
return;
|
|
3300
|
-
}
|
|
3301
|
-
if (text === "/reload") {
|
|
3302
|
-
this.editor.setText("");
|
|
3303
|
-
await this.handleReloadCommand();
|
|
3304
|
-
return;
|
|
3305
|
-
}
|
|
3306
|
-
if (text === "/debug") {
|
|
3307
|
-
this.handleDebugCommand();
|
|
3308
|
-
this.editor.setText("");
|
|
3309
|
-
return;
|
|
3310
|
-
}
|
|
3311
|
-
if (text === "/arminsayshi") {
|
|
3312
|
-
this.handleArminSaysHi();
|
|
3313
|
-
this.editor.setText("");
|
|
3314
|
-
return;
|
|
3315
|
-
}
|
|
3316
|
-
if (text === "/dementedelves") {
|
|
3317
|
-
this.handleDementedDelves();
|
|
3318
|
-
this.editor.setText("");
|
|
3319
|
-
return;
|
|
3320
|
-
}
|
|
3321
|
-
if (text === "/resume") {
|
|
3322
|
-
this.showSessionSelector();
|
|
3323
|
-
this.editor.setText("");
|
|
3324
|
-
return;
|
|
3325
|
-
}
|
|
3326
|
-
if (text === "/quit" || text === "/exit") {
|
|
3327
|
-
this.editor.setText("");
|
|
3328
|
-
await this.shutdown();
|
|
3329
|
-
return;
|
|
3330
|
-
}
|
|
3331
|
-
if (this.isExtensionCommand(text)) {
|
|
3332
|
-
this.editor.addToHistory?.(text);
|
|
3333
|
-
this.editor.setText("");
|
|
3334
|
-
const pendingEchoId = this.optimisticUserEchoes.begin(text);
|
|
3335
|
-
try {
|
|
3336
|
-
await this.session.prompt(text, this.optimisticUserEchoes.promptOptions(pendingEchoId));
|
|
3197
|
+
try {
|
|
3198
|
+
// Capture-then-clear BEFORE any branch: handleFollowUp's non-streaming
|
|
3199
|
+
// path pre-resolves images and hands off here, but slash / extension /
|
|
3200
|
+
// bash submissions return before the consuming branches below. Clearing
|
|
3201
|
+
// only after use would leak a stale array into a later ordinary
|
|
3202
|
+
// submission whose text never references it.
|
|
3203
|
+
const preResolvedImages = this.preResolvedSubmissionImages;
|
|
3204
|
+
this.preResolvedSubmissionImages = undefined;
|
|
3205
|
+
this.hideShortcutOverlay();
|
|
3206
|
+
this.lastEditorText = "";
|
|
3207
|
+
text = text.trim();
|
|
3208
|
+
if (!text)
|
|
3209
|
+
return;
|
|
3210
|
+
// Handle commands
|
|
3211
|
+
if (text === "/settings") {
|
|
3212
|
+
await this.showSettingsSelector();
|
|
3213
|
+
this.editor.setText("");
|
|
3214
|
+
return;
|
|
3337
3215
|
}
|
|
3338
|
-
|
|
3339
|
-
this.
|
|
3340
|
-
|
|
3216
|
+
if (text === "/favorite-models") {
|
|
3217
|
+
this.editor.setText("");
|
|
3218
|
+
await this.showFavoriteModelsSelector();
|
|
3219
|
+
return;
|
|
3341
3220
|
}
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
this.
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3221
|
+
if (text === "/scoped-models") {
|
|
3222
|
+
this.editor.setText("");
|
|
3223
|
+
this.showScopedModelsSelector();
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3226
|
+
if (text === "/model" || text.startsWith("/model ")) {
|
|
3227
|
+
const searchTerm = text.startsWith("/model ") ? text.slice(7).trim() : undefined;
|
|
3228
|
+
this.editor.setText("");
|
|
3229
|
+
await this.handleModelCommand(searchTerm);
|
|
3230
|
+
return;
|
|
3231
|
+
}
|
|
3232
|
+
if (text === "/export" || text.startsWith("/export ")) {
|
|
3233
|
+
await this.handleExportCommand(text);
|
|
3234
|
+
this.editor.setText("");
|
|
3235
|
+
return;
|
|
3236
|
+
}
|
|
3237
|
+
if (text === "/import" || text.startsWith("/import ")) {
|
|
3238
|
+
await this.handleImportCommand(text);
|
|
3239
|
+
this.editor.setText("");
|
|
3240
|
+
return;
|
|
3241
|
+
}
|
|
3242
|
+
if (text === "/share") {
|
|
3243
|
+
await this.handleShareCommand();
|
|
3244
|
+
this.editor.setText("");
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
if (text === "/copy") {
|
|
3248
|
+
await this.handleCopyCommand();
|
|
3249
|
+
this.editor.setText("");
|
|
3250
|
+
return;
|
|
3251
|
+
}
|
|
3252
|
+
if (text === "/name" || text.startsWith("/name ")) {
|
|
3253
|
+
await this.handleNameCommand(text);
|
|
3254
|
+
this.editor.setText("");
|
|
3255
|
+
return;
|
|
3256
|
+
}
|
|
3257
|
+
if (text === "/session") {
|
|
3258
|
+
await this.handleSessionCommand();
|
|
3259
|
+
this.editor.setText("");
|
|
3260
|
+
return;
|
|
3261
|
+
}
|
|
3262
|
+
if (text === "/changelog") {
|
|
3263
|
+
this.handleChangelogCommand();
|
|
3264
|
+
this.editor.setText("");
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3267
|
+
if (text === "/keybindings") {
|
|
3268
|
+
this.editor.setText("");
|
|
3269
|
+
await this.handleKeybindingsCommand();
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
if (text === "/hotkeys") {
|
|
3273
|
+
this.handleHotkeysCommand();
|
|
3274
|
+
this.editor.setText("");
|
|
3275
|
+
return;
|
|
3276
|
+
}
|
|
3277
|
+
if (text === "/fork") {
|
|
3278
|
+
await this.showUserMessageSelector();
|
|
3279
|
+
this.editor.setText("");
|
|
3280
|
+
return;
|
|
3281
|
+
}
|
|
3282
|
+
if (text === "/clone") {
|
|
3283
|
+
this.editor.setText("");
|
|
3284
|
+
await this.handleCloneCommand();
|
|
3285
|
+
return;
|
|
3286
|
+
}
|
|
3287
|
+
if (text === "/tree") {
|
|
3288
|
+
this.showTreeSelector();
|
|
3289
|
+
this.editor.setText("");
|
|
3290
|
+
return;
|
|
3291
|
+
}
|
|
3292
|
+
if (text === "/trust") {
|
|
3293
|
+
this.showTrustSelector();
|
|
3294
|
+
this.editor.setText("");
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
if (text === "/login" || text.startsWith("/login ")) {
|
|
3298
|
+
const providerRef = text.startsWith("/login ") ? text.slice(7).trim() : undefined;
|
|
3299
|
+
this.editor.setText("");
|
|
3300
|
+
await this.handleLoginCommand(providerRef);
|
|
3301
|
+
return;
|
|
3302
|
+
}
|
|
3303
|
+
if (text === "/logout") {
|
|
3304
|
+
this.showOAuthSelector("logout");
|
|
3305
|
+
this.editor.setText("");
|
|
3306
|
+
return;
|
|
3307
|
+
}
|
|
3308
|
+
if (text === "/new") {
|
|
3309
|
+
this.editor.setText("");
|
|
3310
|
+
await this.handleClearCommand();
|
|
3311
|
+
return;
|
|
3312
|
+
}
|
|
3313
|
+
if (text === "/compact" || text.startsWith("/compact ")) {
|
|
3314
|
+
const customInstructions = text.startsWith("/compact ") ? text.slice(9).trim() : undefined;
|
|
3315
|
+
this.editor.setText("");
|
|
3316
|
+
await this.handleCompactCommand(customInstructions);
|
|
3317
|
+
return;
|
|
3318
|
+
}
|
|
3319
|
+
if (text === "/reload") {
|
|
3320
|
+
this.editor.setText("");
|
|
3321
|
+
await this.handleReloadCommand();
|
|
3322
|
+
return;
|
|
3323
|
+
}
|
|
3324
|
+
if (text === "/debug") {
|
|
3325
|
+
this.handleDebugCommand();
|
|
3326
|
+
this.editor.setText("");
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
if (text === "/arminsayshi") {
|
|
3330
|
+
this.handleArminSaysHi();
|
|
3331
|
+
this.editor.setText("");
|
|
3332
|
+
return;
|
|
3333
|
+
}
|
|
3334
|
+
if (text === "/dementedelves") {
|
|
3335
|
+
this.handleDementedDelves();
|
|
3336
|
+
this.editor.setText("");
|
|
3337
|
+
return;
|
|
3338
|
+
}
|
|
3339
|
+
if (text === "/resume") {
|
|
3340
|
+
this.showSessionSelector();
|
|
3341
|
+
this.editor.setText("");
|
|
3342
|
+
return;
|
|
3343
|
+
}
|
|
3344
|
+
if (text === "/quit" || text === "/exit") {
|
|
3345
|
+
this.editor.setText("");
|
|
3346
|
+
await this.shutdown();
|
|
3358
3347
|
return;
|
|
3359
3348
|
}
|
|
3360
|
-
}
|
|
3361
|
-
// Queue non-command input during compaction.
|
|
3362
|
-
// Extension commands short-circuit at the isExtensionCommand branch above and
|
|
3363
|
-
// dispatch immediately inside AgentSession.prompt(), so the only text that
|
|
3364
|
-
// reaches this compaction branch is non-command user input, which is queued
|
|
3365
|
-
// for delivery after compaction settles.
|
|
3366
|
-
//
|
|
3367
|
-
// Note: the isExtensionCommand re-check below is already unreachable today
|
|
3368
|
-
// (the branch above returns first) and stays harmless after the
|
|
3369
|
-
// immediate-dispatch hoist in prompt().
|
|
3370
|
-
if (this.session.isCompacting) {
|
|
3371
3349
|
if (this.isExtensionCommand(text)) {
|
|
3372
3350
|
this.editor.addToHistory?.(text);
|
|
3373
3351
|
this.editor.setText("");
|
|
@@ -3379,52 +3357,96 @@ export class InteractiveMode {
|
|
|
3379
3357
|
this.optimisticUserEchoes.reject(pendingEchoId);
|
|
3380
3358
|
throw error;
|
|
3381
3359
|
}
|
|
3360
|
+
return;
|
|
3382
3361
|
}
|
|
3383
|
-
|
|
3384
|
-
|
|
3362
|
+
// Handle bash command (! for normal, !! for excluded from context)
|
|
3363
|
+
if (text.startsWith("!")) {
|
|
3364
|
+
const isExcluded = text.startsWith("!!");
|
|
3365
|
+
const command = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
|
|
3366
|
+
if (command) {
|
|
3367
|
+
if (this.session.isBashRunning) {
|
|
3368
|
+
this.showWarning("A bash command is already running. Press Esc to cancel it first.");
|
|
3369
|
+
this.editor.setText(text);
|
|
3370
|
+
return;
|
|
3371
|
+
}
|
|
3372
|
+
this.editor.addToHistory?.(text);
|
|
3373
|
+
await this.handleBashCommand(command, isExcluded);
|
|
3374
|
+
this.isBashMode = false;
|
|
3375
|
+
this.updateEditorBorderColor();
|
|
3376
|
+
return;
|
|
3377
|
+
}
|
|
3385
3378
|
}
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
//
|
|
3395
|
-
|
|
3379
|
+
// Queue non-command input during compaction.
|
|
3380
|
+
// Extension commands short-circuit at the isExtensionCommand branch above and
|
|
3381
|
+
// dispatch immediately inside AgentSession.prompt(), so the only text that
|
|
3382
|
+
// reaches this compaction branch is non-command user input, which is queued
|
|
3383
|
+
// for delivery after compaction settles.
|
|
3384
|
+
//
|
|
3385
|
+
// Note: the isExtensionCommand re-check below is already unreachable today
|
|
3386
|
+
// (the branch above returns first) and stays harmless after the
|
|
3387
|
+
// immediate-dispatch hoist in prompt().
|
|
3388
|
+
if (this.session.isCompacting) {
|
|
3389
|
+
if (this.isExtensionCommand(text)) {
|
|
3390
|
+
this.editor.addToHistory?.(text);
|
|
3391
|
+
this.editor.setText("");
|
|
3392
|
+
const pendingEchoId = this.optimisticUserEchoes.begin(text);
|
|
3393
|
+
try {
|
|
3394
|
+
await this.session.prompt(text, this.optimisticUserEchoes.promptOptions(pendingEchoId));
|
|
3395
|
+
}
|
|
3396
|
+
catch (error) {
|
|
3397
|
+
this.optimisticUserEchoes.reject(pendingEchoId);
|
|
3398
|
+
throw error;
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
else {
|
|
3402
|
+
this.queueCompactionSubmission(text, "steer");
|
|
3403
|
+
}
|
|
3404
|
+
return;
|
|
3405
|
+
}
|
|
3406
|
+
// If streaming, use prompt() with steer behavior.
|
|
3407
|
+
// Extension commands are dispatched immediately by AgentSession.prompt()
|
|
3408
|
+
// (short-circuited at the isExtensionCommand branch above); the steer
|
|
3409
|
+
// behavior here applies only to ordinary text, prompt template expansion,
|
|
3410
|
+
// and queueing.
|
|
3411
|
+
if (this.session.isStreaming) {
|
|
3412
|
+
// Resolve BEFORE setText(""): the editor's prune chain fires
|
|
3413
|
+
// onImageMarkersChanged([]) and destroys pendingImages.
|
|
3414
|
+
const images = preResolvedImages ?? this.takeSubmissionImages(text);
|
|
3415
|
+
this.editor.addToHistory?.(text);
|
|
3416
|
+
this.editor.setText("");
|
|
3417
|
+
const pendingEchoId = this.optimisticUserEchoes.begin(text);
|
|
3418
|
+
try {
|
|
3419
|
+
await this.session.prompt(text, {
|
|
3420
|
+
streamingBehavior: "steer",
|
|
3421
|
+
...(images.length > 0 ? { images } : {}),
|
|
3422
|
+
...this.optimisticUserEchoes.promptOptions(pendingEchoId),
|
|
3423
|
+
});
|
|
3424
|
+
}
|
|
3425
|
+
catch (error) {
|
|
3426
|
+
this.optimisticUserEchoes.reject(pendingEchoId);
|
|
3427
|
+
throw error;
|
|
3428
|
+
}
|
|
3429
|
+
this.updatePendingMessagesDisplay();
|
|
3430
|
+
this.ui.requestRender();
|
|
3431
|
+
return;
|
|
3432
|
+
}
|
|
3433
|
+
// Normal message submission
|
|
3434
|
+
// First, move any pending bash components to chat
|
|
3435
|
+
this.flushPendingBashComponents();
|
|
3396
3436
|
const images = preResolvedImages ?? this.takeSubmissionImages(text);
|
|
3397
|
-
this.editor.addToHistory?.(text);
|
|
3398
|
-
this.editor.setText("");
|
|
3399
3437
|
const pendingEchoId = this.optimisticUserEchoes.begin(text);
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
...(images.length > 0 ? { images } : {}),
|
|
3404
|
-
...this.optimisticUserEchoes.promptOptions(pendingEchoId),
|
|
3405
|
-
});
|
|
3438
|
+
const submission = images.length > 0 ? { text, images, pendingEchoId } : { text, pendingEchoId };
|
|
3439
|
+
if (this.onInputCallback) {
|
|
3440
|
+
this.onInputCallback(submission);
|
|
3406
3441
|
}
|
|
3407
|
-
|
|
3408
|
-
this.
|
|
3409
|
-
throw error;
|
|
3442
|
+
else {
|
|
3443
|
+
this.pendingUserInputs.push(submission);
|
|
3410
3444
|
}
|
|
3411
|
-
this.
|
|
3412
|
-
this.ui.requestRender();
|
|
3413
|
-
return;
|
|
3414
|
-
}
|
|
3415
|
-
// Normal message submission
|
|
3416
|
-
// First, move any pending bash components to chat
|
|
3417
|
-
this.flushPendingBashComponents();
|
|
3418
|
-
const images = preResolvedImages ?? this.takeSubmissionImages(text);
|
|
3419
|
-
const pendingEchoId = this.optimisticUserEchoes.begin(text);
|
|
3420
|
-
const submission = images.length > 0 ? { text, images, pendingEchoId } : { text, pendingEchoId };
|
|
3421
|
-
if (this.onInputCallback) {
|
|
3422
|
-
this.onInputCallback(submission);
|
|
3445
|
+
this.editor.addToHistory?.(text);
|
|
3423
3446
|
}
|
|
3424
|
-
|
|
3425
|
-
this.
|
|
3447
|
+
catch (error) {
|
|
3448
|
+
this.showError(error instanceof Error ? error.message : String(error));
|
|
3426
3449
|
}
|
|
3427
|
-
this.editor.addToHistory?.(text);
|
|
3428
3450
|
};
|
|
3429
3451
|
}
|
|
3430
3452
|
subscribeToAgent() {
|
|
@@ -3485,6 +3507,7 @@ export class InteractiveMode {
|
|
|
3485
3507
|
case "thinking_level_changed":
|
|
3486
3508
|
this.footer.invalidate();
|
|
3487
3509
|
this.updateEditorBorderColor();
|
|
3510
|
+
this.showStatus(`Thinking level: ${event.level}`);
|
|
3488
3511
|
break;
|
|
3489
3512
|
case "high_reasoning_warning":
|
|
3490
3513
|
this.showHighReasoningWarning(event);
|
|
@@ -3735,15 +3758,24 @@ export class InteractiveMode {
|
|
|
3735
3758
|
// Keep the structural fallback for focused handler consumers while using
|
|
3736
3759
|
// the session-owned manager on the real TUI path.
|
|
3737
3760
|
const sessionManager = this.session.sessionManager ?? this.sessionManager;
|
|
3738
|
-
|
|
3761
|
+
let entries = sessionManager?.buildContextEntries?.() ?? [];
|
|
3739
3762
|
if (entries[0]?.type !== "compaction") {
|
|
3740
|
-
|
|
3763
|
+
try {
|
|
3764
|
+
sessionManager?.reloadFromDisk?.();
|
|
3765
|
+
entries = sessionManager?.buildContextEntries?.() ?? entries;
|
|
3766
|
+
}
|
|
3767
|
+
catch {
|
|
3768
|
+
// Retain existing entries on reload error
|
|
3769
|
+
}
|
|
3741
3770
|
}
|
|
3742
3771
|
this.chatContainer.clear();
|
|
3743
3772
|
const summaryMessage = createCompactionSummaryMessage(sanitizeTerminalLabel(event.result.summary), event.result.tokensBefore, new Date().toISOString(), event.result.details);
|
|
3744
3773
|
if (typeof this.renderSessionEntries === "function") {
|
|
3745
3774
|
// The latest compaction is prepended for model context; append it below at its chronological position.
|
|
3746
|
-
|
|
3775
|
+
const entriesToRender = entries[0]?.type === "compaction"
|
|
3776
|
+
? entries.slice(1)
|
|
3777
|
+
: entries.filter((e) => e.type !== "compaction");
|
|
3778
|
+
this.renderSessionEntries(entriesToRender);
|
|
3747
3779
|
this.addMessageToChat(summaryMessage);
|
|
3748
3780
|
if (event.result.usage) {
|
|
3749
3781
|
this.addCompactionCostNotice({
|
|
@@ -4438,6 +4470,12 @@ export class InteractiveMode {
|
|
|
4438
4470
|
};
|
|
4439
4471
|
}
|
|
4440
4472
|
rebuildChatFromMessages() {
|
|
4473
|
+
try {
|
|
4474
|
+
this.sessionManager?.reloadFromDisk?.();
|
|
4475
|
+
}
|
|
4476
|
+
catch {
|
|
4477
|
+
// Keep in-memory entries if file reload is unavailable
|
|
4478
|
+
}
|
|
4441
4479
|
this.chatContainer.clear();
|
|
4442
4480
|
this.renderSessionEntries(this.sessionManager.buildContextEntries());
|
|
4443
4481
|
}
|
|
@@ -4558,6 +4596,10 @@ export class InteractiveMode {
|
|
|
4558
4596
|
}
|
|
4559
4597
|
catch { }
|
|
4560
4598
|
restoreInteractiveStderr();
|
|
4599
|
+
const storageMessage = storageWriteCrashMessage(error);
|
|
4600
|
+
if (storageMessage !== undefined) {
|
|
4601
|
+
console.error(storageMessage);
|
|
4602
|
+
}
|
|
4561
4603
|
console.error(`${APP_NAME} exiting due to uncaughtException:`);
|
|
4562
4604
|
console.error(error);
|
|
4563
4605
|
process.exit(1);
|
|
@@ -4738,16 +4780,15 @@ export class InteractiveMode {
|
|
|
4738
4780
|
}
|
|
4739
4781
|
this.ui.requestRender();
|
|
4740
4782
|
}
|
|
4741
|
-
cycleThinkingLevel() {
|
|
4742
|
-
|
|
4783
|
+
async cycleThinkingLevel() {
|
|
4784
|
+
// The shared-host proxy answers this over RPC. The level itself is rendered
|
|
4785
|
+
// from the thinking_level_changed event (single path for local and remote,
|
|
4786
|
+
// and for changes made by OTHER attached clients); the awaited value only
|
|
4787
|
+
// distinguishes "model does not support thinking".
|
|
4788
|
+
const newLevel = await this.session.cycleThinkingLevel();
|
|
4743
4789
|
if (newLevel === undefined) {
|
|
4744
4790
|
this.showStatus("Current model does not support thinking");
|
|
4745
4791
|
}
|
|
4746
|
-
else {
|
|
4747
|
-
this.footer.invalidate();
|
|
4748
|
-
this.updateEditorBorderColor();
|
|
4749
|
-
this.showStatus(`Thinking level: ${newLevel}`);
|
|
4750
|
-
}
|
|
4751
4792
|
}
|
|
4752
4793
|
async cycleModel(direction) {
|
|
4753
4794
|
try {
|
|
@@ -5229,7 +5270,9 @@ export class InteractiveMode {
|
|
|
5229
5270
|
this.ui.setFocus(created.focus);
|
|
5230
5271
|
this.ui.requestRender();
|
|
5231
5272
|
}
|
|
5232
|
-
showSettingsSelector() {
|
|
5273
|
+
async showSettingsSelector() {
|
|
5274
|
+
// Awaited at the boundary: the shared-host proxy answers this over RPC.
|
|
5275
|
+
const availableThinkingLevels = await this.session.getAvailableThinkingLevels();
|
|
5233
5276
|
this.showSelector((done) => {
|
|
5234
5277
|
let selector;
|
|
5235
5278
|
selector = new SettingsSelectorComponent({
|
|
@@ -5244,7 +5287,7 @@ export class InteractiveMode {
|
|
|
5244
5287
|
transport: this.settingsManager.getTransport(),
|
|
5245
5288
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
5246
5289
|
thinkingLevel: this.session.thinkingLevel,
|
|
5247
|
-
availableThinkingLevels
|
|
5290
|
+
availableThinkingLevels,
|
|
5248
5291
|
currentTheme: this.themeController.getThemeSelection() || "dark",
|
|
5249
5292
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
5250
5293
|
availableThemes: getAvailableThemes(),
|
|
@@ -5832,8 +5875,9 @@ export class InteractiveMode {
|
|
|
5832
5875
|
};
|
|
5833
5876
|
});
|
|
5834
5877
|
}
|
|
5835
|
-
showUserMessageSelector() {
|
|
5836
|
-
|
|
5878
|
+
async showUserMessageSelector() {
|
|
5879
|
+
// Awaited at the boundary: the shared-host proxy answers this over RPC.
|
|
5880
|
+
const userMessages = await this.session.getUserMessagesForForking();
|
|
5837
5881
|
if (userMessages.length === 0) {
|
|
5838
5882
|
this.showStatus("No messages to fork from");
|
|
5839
5883
|
return;
|
|
@@ -6612,7 +6656,7 @@ export class InteractiveMode {
|
|
|
6612
6656
|
const outputPath = this.getPathCommandArgument(text, "/export");
|
|
6613
6657
|
try {
|
|
6614
6658
|
if (outputPath?.endsWith(".jsonl")) {
|
|
6615
|
-
const filePath = this.session.exportToJsonl(outputPath);
|
|
6659
|
+
const filePath = await this.session.exportToJsonl(outputPath);
|
|
6616
6660
|
this.showStatus(`Session exported to: ${filePath}`);
|
|
6617
6661
|
}
|
|
6618
6662
|
else {
|
|
@@ -6801,7 +6845,7 @@ export class InteractiveMode {
|
|
|
6801
6845
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
6802
6846
|
}
|
|
6803
6847
|
}
|
|
6804
|
-
handleNameCommand(text) {
|
|
6848
|
+
async handleNameCommand(text) {
|
|
6805
6849
|
const name = text.replace(/^\/name\s*/, "").trim();
|
|
6806
6850
|
if (!name) {
|
|
6807
6851
|
const currentName = this.sessionManager.getSessionName();
|
|
@@ -6815,8 +6859,8 @@ export class InteractiveMode {
|
|
|
6815
6859
|
this.ui.requestRender();
|
|
6816
6860
|
return;
|
|
6817
6861
|
}
|
|
6818
|
-
this.session.setSessionName(name);
|
|
6819
|
-
const sessionName = this.
|
|
6862
|
+
await this.session.setSessionName(name);
|
|
6863
|
+
const sessionName = this.session.sessionName;
|
|
6820
6864
|
if (sessionName !== name) {
|
|
6821
6865
|
this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`);
|
|
6822
6866
|
}
|
|
@@ -6824,9 +6868,10 @@ export class InteractiveMode {
|
|
|
6824
6868
|
this.chatContainer.addChild(new Text(theme.fg("dim", `Session name set: ${sessionName ?? name}`), 1, 0));
|
|
6825
6869
|
this.ui.requestRender();
|
|
6826
6870
|
}
|
|
6827
|
-
handleSessionCommand() {
|
|
6828
|
-
|
|
6829
|
-
const
|
|
6871
|
+
async handleSessionCommand() {
|
|
6872
|
+
// Awaited at the boundary: the shared-host proxy answers this over RPC.
|
|
6873
|
+
const stats = await this.session.getSessionStats();
|
|
6874
|
+
const sessionName = this.session.sessionName;
|
|
6830
6875
|
const entries = this.sessionManager.getEntries();
|
|
6831
6876
|
const cacheWaste = computeCacheWaste(entries, this.session.modelRuntime);
|
|
6832
6877
|
// Cost/token totals per provider/model actually used (e.g. OpenRouter `auto`
|
|
@@ -7108,7 +7153,7 @@ export class InteractiveMode {
|
|
|
7108
7153
|
}
|
|
7109
7154
|
this.bashComponent.setComplete(result.exitCode, result.cancelled, result.truncated ? { truncated: true, content: result.output } : undefined, result.fullOutputPath);
|
|
7110
7155
|
// Record the result in session
|
|
7111
|
-
this.session.recordBashResult(command, result, { excludeFromContext });
|
|
7156
|
+
void this.session.recordBashResult(command, result, { excludeFromContext });
|
|
7112
7157
|
this.bashComponent = undefined;
|
|
7113
7158
|
this.ui.requestRender();
|
|
7114
7159
|
return;
|