mixdog 0.9.151 → 0.9.152
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/README.md +110 -68
- package/package.json +3 -2
- package/scripts/tool-stress.mjs +0 -2
- package/src/defaults/skills/setup/SKILL.md +18 -27
- package/src/headless-exec.mjs +3 -10
- package/src/headless-exec.test.mjs +2 -7
- package/src/runtime/agent/orchestrator/config.mjs +6 -66
- package/src/runtime/agent/orchestrator/context/collect-skills.test.mjs +153 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +49 -45
- package/src/runtime/agent/orchestrator/mcp/client.mjs +242 -15
- package/src/runtime/agent/orchestrator/mcp/features.test.mjs +66 -0
- package/src/runtime/agent/orchestrator/mcp/security.test.mjs +36 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +54 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +3 -8
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +10 -2
- package/src/runtime/agent/orchestrator/providers/lib/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/lib/sse-framing.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +35 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +22 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +0 -2
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +4 -7
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/provider-replay.test.mjs +235 -0
- package/src/runtime/agent/orchestrator/providers/sse-framing.test.mjs +719 -0
- package/src/runtime/agent/orchestrator/providers/stream-json-pool.mjs +399 -39
- package/src/runtime/agent/orchestrator/providers/stream-json-worker.mjs +26 -0
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +24 -1
- package/src/runtime/agent/orchestrator/session/compaction-read-reset.test.mjs +161 -0
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +31 -18
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/message-sanitize.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +556 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.test.mjs +457 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +105 -186
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +115 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool-cwd-env.test.mjs +14 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -10
- package/src/runtime/agent/orchestrator/tools/builtin/find-search-budget.test.mjs +30 -14
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +15 -4
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +73 -15
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.test.mjs +76 -2
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +24 -683
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +64 -72
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-runner.mjs +2 -5
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-transport.mjs +75 -0
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-transport.test.mjs +24 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +24 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.test.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +12 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +35 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +28 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.test.mjs +54 -0
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +11 -11
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +11 -11
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +11 -11
- package/src/runtime/browser-bridge/client.mjs +103 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +42 -0
- package/src/runtime/computer-bridge/client.mjs +101 -0
- package/src/runtime/computer-bridge/tool-defs.mjs +53 -0
- package/src/runtime/media/store.mjs +18 -8
- package/src/runtime/media/store.test.mjs +14 -0
- package/src/runtime/memory/index.mjs +1 -1
- package/src/runtime/memory/lib/transcript-ingest.mjs +8 -6
- package/src/runtime/memory/lib/transcript-ingest.test.mjs +52 -0
- package/src/runtime/shared/child-spawn-gate.mjs +17 -0
- package/src/runtime/shared/child-spawn-remote.mjs +69 -7
- package/src/runtime/shared/child-spawn-remote.test.mjs +124 -0
- package/src/runtime/shared/pristine-execution-contract.json +2 -1
- package/src/runtime/shared/provider-api-key.mjs +1 -0
- package/src/runtime/shared/session-runtime-health.mjs +91 -0
- package/src/runtime/shared/session-runtime-health.test.mjs +53 -0
- package/src/runtime/shared/skill-document.mjs +86 -0
- package/src/runtime/shared/skill-document.test.mjs +81 -0
- package/src/runtime/shared/tool-surface.mjs +18 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +1 -0
- package/src/runtime/shared/turn-snapshot.mjs +32 -9
- package/src/runtime/shared/user-cwd.mjs +33 -14
- package/src/runtime/shared/user-cwd.test.mjs +43 -0
- package/src/session-runtime/cwd-plugins.mjs +26 -26
- package/src/session-runtime/cwd-plugins.test.mjs +75 -0
- package/src/session-runtime/cwd-tool-routing.test.mjs +5 -0
- package/src/session-runtime/global-extensions.mjs +26 -0
- package/src/session-runtime/global-extensions.test.mjs +28 -0
- package/src/session-runtime/goal-runtime.mjs +721 -0
- package/src/session-runtime/goal-runtime.test.mjs +108 -0
- package/src/session-runtime/lifecycle-api.mjs +18 -4
- package/src/session-runtime/lifecycle-api.test.mjs +21 -0
- package/src/session-runtime/mcp-glue.mjs +49 -47
- package/src/session-runtime/plugin-mcp-standard.test.mjs +177 -0
- package/src/session-runtime/plugin-mcp.mjs +96 -22
- package/src/session-runtime/prewarm.mjs +1 -10
- package/src/session-runtime/resource-api-global.test.mjs +69 -0
- package/src/session-runtime/resource-api.mjs +173 -58
- package/src/session-runtime/runtime-core.mjs +148 -20
- package/src/session-runtime/runtime-tunables.mjs +6 -8
- package/src/session-runtime/session-turn-api.mjs +22 -11
- package/src/session-runtime/skills-api.mjs +79 -25
- package/src/session-runtime/skills-api.test.mjs +99 -0
- package/src/session-runtime/tool-catalog-schema.mjs +0 -5
- package/src/session-runtime/tool-catalog.mjs +4 -13
- package/src/session-runtime/tool-policy-surface.test.mjs +33 -11
- package/src/session-runtime/tool-surface.mjs +12 -0
- package/src/standalone/agent-dispatch-broker.mjs +5 -9
- package/src/standalone/agent-tool/notify.mjs +6 -8
- package/src/standalone/agent-tool/notify.test.mjs +37 -0
- package/src/standalone/daemon.mjs +31 -15
- package/src/standalone/hook-bus/config.mjs +1 -0
- package/src/standalone/plugin-admin.mjs +17 -0
- package/src/standalone/plugin-admin.test.mjs +7 -0
- package/src/standalone/provider-admin.mjs +1 -0
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-runtime-agent-control-client.mjs +133 -0
- package/src/standalone/session-runtime-agent-control-client.test.mjs +71 -0
- package/src/standalone/session-runtime-dispatch-cancel.test.mjs +139 -0
- package/src/standalone/session-runtime-host-factory.mjs +17 -0
- package/src/standalone/session-runtime-host-factory.test.mjs +31 -0
- package/src/standalone/session-runtime-host-health.test.mjs +5 -0
- package/src/standalone/session-runtime-host.mjs +696 -58
- package/src/standalone/session-runtime-inline-host.mjs +351 -0
- package/src/standalone/session-runtime-inline-host.test.mjs +83 -0
- package/src/standalone/session-runtime-provider-cooldown.mjs +78 -0
- package/src/standalone/session-runtime-provider-cooldown.test.mjs +80 -0
- package/src/standalone/session-runtime-shard-host.test.mjs +569 -0
- package/src/standalone/session-runtime-shard-router.mjs +149 -0
- package/src/standalone/session-runtime-shard-router.test.mjs +101 -0
- package/src/standalone/session-runtime-worker.mjs +476 -18
- package/src/standalone/session-service.mjs +81 -6
- package/src/tui/app/app-view.jsx +1 -0
- package/src/tui/app/core-memory-picker.mjs +2 -0
- package/src/tui/app/extension-pickers.mjs +1 -1
- package/src/tui/app/maintenance-pickers.mjs +3 -3
- package/src/tui/app/model-options.mjs +2 -0
- package/src/tui/app/model-picker.mjs +14 -4
- package/src/tui/app/panel-handoff.test.mjs +311 -0
- package/src/tui/app/project-picker.mjs +1 -0
- package/src/tui/app/route-pickers.mjs +21 -6
- package/src/tui/app/settings-picker.mjs +26 -3
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch.mjs +73 -22
- package/src/tui/app/theme-effort-pickers.mjs +7 -2
- package/src/tui/components/Picker.jsx +10 -1
- package/src/tui/dist/index.mjs +163 -44
- package/src/tui/session/context-state.mjs +1 -0
- package/src/tui/session/goal-continuation.mjs +110 -0
- package/src/tui/session/goal-continuation.test.mjs +84 -0
- package/src/tui/session/queue-helpers.mjs +5 -2
- package/src/tui/session/session-action-surface.test.mjs +108 -0
- package/src/tui/session/session-api-ext.mjs +39 -8
- package/src/tui/session/session-api.mjs +58 -0
- package/src/tui/session/session-flow.mjs +6 -0
- package/src/tui/session/turn.mjs +1 -0
- package/src/tui/session-local.mjs +15 -1
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +0 -301
package/src/tui/dist/index.mjs
CHANGED
|
@@ -669,7 +669,8 @@ var init_provider_api_key = __esm({
|
|
|
669
669
|
gemini: "GEMINI_API_KEY",
|
|
670
670
|
deepseek: "DEEPSEEK_API_KEY",
|
|
671
671
|
xai: "XAI_API_KEY",
|
|
672
|
-
"opencode-go": "OPENCODE_API_KEY"
|
|
672
|
+
"opencode-go": "OPENCODE_API_KEY",
|
|
673
|
+
openrouter: "OPENROUTER_API_KEY"
|
|
673
674
|
});
|
|
674
675
|
AGENT_PROVIDER_ENV_ALIASES = Object.freeze({
|
|
675
676
|
xai: ["GROK_API_KEY"]
|
|
@@ -3873,6 +3874,10 @@ function displayToolName(name, args = {}) {
|
|
|
3873
3874
|
case "web_fetch":
|
|
3874
3875
|
case "fetch":
|
|
3875
3876
|
return "Fetch";
|
|
3877
|
+
case "browser":
|
|
3878
|
+
return "Browser";
|
|
3879
|
+
case "computer":
|
|
3880
|
+
return "Computer";
|
|
3876
3881
|
case "list_mcp_resources":
|
|
3877
3882
|
case "list_mcp_resource_templates":
|
|
3878
3883
|
case "cwd":
|
|
@@ -3993,6 +3998,16 @@ function summarizeToolArgs(name, args, { max = DEFAULT_SUMMARY_MAX } = {}) {
|
|
|
3993
3998
|
return formatCountedUnit(collectionCount(a.url, a.uri), "URL", "URLs");
|
|
3994
3999
|
}
|
|
3995
4000
|
return truncateToolText(a.url || a.uri || "", max);
|
|
4001
|
+
case "browser":
|
|
4002
|
+
return compactParts([
|
|
4003
|
+
String(a.action || ""),
|
|
4004
|
+
a.url ? truncateToolText(a.url, max) : a.ref ? String(a.ref) : ""
|
|
4005
|
+
]);
|
|
4006
|
+
case "computer":
|
|
4007
|
+
return compactParts([
|
|
4008
|
+
String(a.action || ""),
|
|
4009
|
+
a.window ? truncateToolText(a.window, max) : a.ref ? String(a.ref) : a.app ? truncateToolText(a.app, max) : ""
|
|
4010
|
+
]);
|
|
3996
4011
|
case "read_mcp_resource":
|
|
3997
4012
|
return truncateToolText(a.uri || "", max);
|
|
3998
4013
|
case "list_mcp_resources":
|
|
@@ -4257,6 +4272,10 @@ function toolWorkUnit(name, args = {}, category = "") {
|
|
|
4257
4272
|
return unitDescriptor("Web Research", { count: queryCount(a, "query", "queries", "keywords") || 1, noun: "query", pluralNoun: "queries" });
|
|
4258
4273
|
case "web_fetch":
|
|
4259
4274
|
return unitDescriptor("Web Research", { count: queryCount(a, "url", "urls", "uri", "uris") || 1, active: "Fetching", done: "Fetched", noun: "URL", pluralNoun: "URLs" });
|
|
4275
|
+
case "browser":
|
|
4276
|
+
return unitDescriptor("Browser", { count: 1, active: "Browsing", done: "Browsed", noun: "action" });
|
|
4277
|
+
case "computer":
|
|
4278
|
+
return unitDescriptor("Computer", { count: 1, active: "Operating", done: "Operated", noun: "action" });
|
|
4260
4279
|
case "fetch": {
|
|
4261
4280
|
const fetchLimit = Number(a.limit ?? a.messages);
|
|
4262
4281
|
const fetchCount = Number.isFinite(fetchLimit) && fetchLimit > 0 ? Math.floor(fetchLimit) : queryCount(a, "messages") || 1;
|
|
@@ -7464,6 +7483,10 @@ function Picker({
|
|
|
7464
7483
|
indexMode = "auto",
|
|
7465
7484
|
fillHeight = false,
|
|
7466
7485
|
visibleCount = MAX_VISIBLE,
|
|
7486
|
+
// Loading panels reserve the same content-row geometry as the real list.
|
|
7487
|
+
// This prevents an `(empty)` row from being replaced by a multi-row menu in
|
|
7488
|
+
// one commit, which reads as the option items jumping into place.
|
|
7489
|
+
loading = false,
|
|
7467
7490
|
// Onboarding confirm bar: { buttons:[{value,label}], onConfirm(button,index) }.
|
|
7468
7491
|
// When present, ←/→ and Tab drive button focus (mutually exclusive with
|
|
7469
7492
|
// onLeft/onRight), and Enter fires onConfirm while a button is focused.
|
|
@@ -7644,6 +7667,7 @@ function Picker({
|
|
|
7644
7667
|
);
|
|
7645
7668
|
if (items.length === 0) {
|
|
7646
7669
|
const emptyLine = truncateText(String(description || "").replace(/\s+/g, " ").trim(), Math.max(0, columns - 4));
|
|
7670
|
+
const loadingRows = loading ? Array.from({ length: visibleLimit }, (_, index) => /* @__PURE__ */ jsx6(Text6, { color: theme.inactive, children: " " }, `loading-${index}`)) : null;
|
|
7647
7671
|
return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", flexShrink: 0, height: fillHeight ? "100%" : void 0, children: /* @__PURE__ */ jsxs4(
|
|
7648
7672
|
Box6,
|
|
7649
7673
|
{
|
|
@@ -7661,7 +7685,7 @@ function Picker({
|
|
|
7661
7685
|
/* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
7662
7686
|
/* @__PURE__ */ jsx6(Text6, { color: theme.text, children: emptyLine || " " }),
|
|
7663
7687
|
/* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
7664
|
-
/* @__PURE__ */ jsx6(Text6, { color: theme.inactive, children: "(empty)" }),
|
|
7688
|
+
loading ? loadingRows : /* @__PURE__ */ jsx6(Text6, { color: theme.inactive, children: "(empty)" }),
|
|
7665
7689
|
hasConfirm ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
7666
7690
|
/* @__PURE__ */ jsx6(Box6, { flexGrow: 1 }),
|
|
7667
7691
|
/* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
@@ -9372,6 +9396,7 @@ var SLASH_COMMANDS = [
|
|
|
9372
9396
|
{ name: "clear", usage: "/clear", aliases: ["new"], aliasUsage: ["new"], description: "Start a fresh chat" },
|
|
9373
9397
|
{ name: "project", usage: "/project", aliases: ["projects"], aliasUsage: ["projects"], showAliasUsage: false, params: "[path]", description: "Switch working directory (project)" },
|
|
9374
9398
|
{ name: "compact", usage: "/compact", description: "Compact older conversation context" },
|
|
9399
|
+
{ name: "goal", usage: "/goal", params: "[objective --time 1h|status|pause|resume|edit|complete|clear]", description: "Run and manage a durable session Goal" },
|
|
9375
9400
|
{ name: "autoclear", usage: "/autoclear", params: "[on|off|duration]", description: "Reduce cache-miss cost after long idle gaps" },
|
|
9376
9401
|
{ name: "resume", usage: "/resume", params: "[id]", description: "Resume a saved chat" },
|
|
9377
9402
|
{ name: "context", usage: "/context", description: "Show current context surface" },
|
|
@@ -17166,6 +17191,7 @@ function renderAppView(ctx) {
|
|
|
17166
17191
|
indexMode: picker.indexMode,
|
|
17167
17192
|
visibleCount: pickerVisibleRows,
|
|
17168
17193
|
fillHeight: expandedOptionPanel,
|
|
17194
|
+
loading: picker.loading === true,
|
|
17169
17195
|
themeEpoch: state.themeEpoch || 0,
|
|
17170
17196
|
confirmBar: picker.confirmBar
|
|
17171
17197
|
},
|
|
@@ -17543,6 +17569,7 @@ function createThemeEffortPickers({
|
|
|
17543
17569
|
const openThemePicker = (options = {}) => {
|
|
17544
17570
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
|
|
17545
17571
|
const onboarding = options.onboarding || null;
|
|
17572
|
+
const handoffPanel = options.handoffPanel && typeof options.handoffPanel === "object" ? options.handoffPanel : null;
|
|
17546
17573
|
const own = surface.claim();
|
|
17547
17574
|
let themes = [];
|
|
17548
17575
|
try {
|
|
@@ -17577,7 +17604,8 @@ function createThemeEffortPickers({
|
|
|
17577
17604
|
}
|
|
17578
17605
|
};
|
|
17579
17606
|
const saveTheme = (id, { advance = false } = {}) => {
|
|
17580
|
-
own.
|
|
17607
|
+
if (handoffPanel) own.paint(handoffPanel);
|
|
17608
|
+
else own.close();
|
|
17581
17609
|
const applied = applyTheme(id, { persist: true });
|
|
17582
17610
|
store.pushNotice(themeNotice(applied || { id }), "info");
|
|
17583
17611
|
if (advance && onboarding) onboarding.onAdvance?.();
|
|
@@ -17618,7 +17646,8 @@ function createThemeEffortPickers({
|
|
|
17618
17646
|
saveTheme(entry.id, { advance: Boolean(onboarding) });
|
|
17619
17647
|
},
|
|
17620
17648
|
onCancel: () => {
|
|
17621
|
-
own.
|
|
17649
|
+
if (handoffPanel) own.paint(handoffPanel);
|
|
17650
|
+
else own.close();
|
|
17622
17651
|
if (currentId) applyTheme(currentId, { persist: false });
|
|
17623
17652
|
if (onboarding) onboarding.onCancel?.();
|
|
17624
17653
|
else if (returnTo) returnTo();
|
|
@@ -17730,6 +17759,7 @@ function createCoreMemoryPicker({
|
|
|
17730
17759
|
// Loading state lives in the header description row, not as a fake
|
|
17731
17760
|
// selectable menu item.
|
|
17732
17761
|
description: "Loading memories\u2026",
|
|
17762
|
+
loading: true,
|
|
17733
17763
|
items: [],
|
|
17734
17764
|
onSelect: () => {
|
|
17735
17765
|
},
|
|
@@ -17793,6 +17823,7 @@ function createCoreMemoryPicker({
|
|
|
17793
17823
|
paintPanel({
|
|
17794
17824
|
title: "Memory \xB7 List",
|
|
17795
17825
|
description: "Loading memories\u2026",
|
|
17826
|
+
loading: true,
|
|
17796
17827
|
items: [],
|
|
17797
17828
|
onSelect: () => {
|
|
17798
17829
|
},
|
|
@@ -17956,7 +17987,7 @@ function createExtensionPickers({
|
|
|
17956
17987
|
mcpActive = true;
|
|
17957
17988
|
};
|
|
17958
17989
|
const openMcpPicker = () => {
|
|
17959
|
-
openMcpServersPicker();
|
|
17990
|
+
return openMcpServersPicker();
|
|
17960
17991
|
};
|
|
17961
17992
|
const skillsStatus = async () => {
|
|
17962
17993
|
let status;
|
|
@@ -18488,7 +18519,7 @@ function createMaintenancePickers({
|
|
|
18488
18519
|
settled();
|
|
18489
18520
|
});
|
|
18490
18521
|
};
|
|
18491
|
-
|
|
18522
|
+
return Promise.resolve(render2({ checking: true })).catch((e) => {
|
|
18492
18523
|
store.pushNotice(`update panel failed: ${e?.message || e}`, "error");
|
|
18493
18524
|
return false;
|
|
18494
18525
|
}).then((painted) => {
|
|
@@ -18621,8 +18652,7 @@ function createMaintenancePickers({
|
|
|
18621
18652
|
setSettingsPrompt(null);
|
|
18622
18653
|
own.context(null);
|
|
18623
18654
|
closeUsagePanel();
|
|
18624
|
-
|
|
18625
|
-
else render2();
|
|
18655
|
+
return Promise.resolve(options.advanced === true ? renderAdvanced() : render2()).catch((e) => store.pushNotice(`auto-clear panel failed: ${e?.message || e}`, "error"));
|
|
18626
18656
|
};
|
|
18627
18657
|
const openProfilePicker = async (options = {}) => {
|
|
18628
18658
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
|
|
@@ -18867,6 +18897,7 @@ var providerDisplayName = (provider) => {
|
|
|
18867
18897
|
if (key === "xai" || key === "xai-api") return "xAI API";
|
|
18868
18898
|
if (key === "deepseek" || key === "deepseek-api") return "DeepSeek API";
|
|
18869
18899
|
if (key === "opencode-go") return "OpenCode Go API";
|
|
18900
|
+
if (key === "openrouter") return "OpenRouter";
|
|
18870
18901
|
if (key === "ollama") return "Ollama";
|
|
18871
18902
|
if (key === "lmstudio") return "LM Studio";
|
|
18872
18903
|
if (key === "default") return "Default";
|
|
@@ -18882,6 +18913,7 @@ var providerDisplayRank = (provider) => {
|
|
|
18882
18913
|
"antigravity-oauth": 31,
|
|
18883
18914
|
"cursor-oauth": 32,
|
|
18884
18915
|
"opencode-go": 35,
|
|
18916
|
+
openrouter: 36,
|
|
18885
18917
|
openai: 40,
|
|
18886
18918
|
"openai-api": 40,
|
|
18887
18919
|
anthropic: 50,
|
|
@@ -19877,6 +19909,7 @@ function createModelPicker({
|
|
|
19877
19909
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
|
|
19878
19910
|
const returnLabel = String(options.returnLabel || "Agents");
|
|
19879
19911
|
const returnOnNestedCancel = options.returnOnNestedCancel === true;
|
|
19912
|
+
const handoffPanel = options.handoffPanel && typeof options.handoffPanel === "object" ? options.handoffPanel : null;
|
|
19880
19913
|
const cancelModelPicker = () => {
|
|
19881
19914
|
modelPickerClosed = true;
|
|
19882
19915
|
if (returnTo) returnTo();
|
|
@@ -19893,6 +19926,7 @@ function createModelPicker({
|
|
|
19893
19926
|
title: options.title || "Model",
|
|
19894
19927
|
description: options.loadingDescription || "Loading models...",
|
|
19895
19928
|
help: returnTo ? `\u2191/\u2193 Select \xB7 Enter Open \xB7 Esc ${returnLabel}` : "\u2191/\u2193 Select \xB7 Enter Open \xB7 Esc Back",
|
|
19929
|
+
loading: true,
|
|
19896
19930
|
items: [],
|
|
19897
19931
|
onCancel: cancelModelPicker
|
|
19898
19932
|
});
|
|
@@ -20162,7 +20196,7 @@ ${model?.id || ""}`;
|
|
|
20162
20196
|
if (typeof options.onImmediateSelect === "function") {
|
|
20163
20197
|
options.onImmediateSelect(routeInput, selected, effort);
|
|
20164
20198
|
} else {
|
|
20165
|
-
own.paint(
|
|
20199
|
+
own.paint(handoffPanel);
|
|
20166
20200
|
}
|
|
20167
20201
|
const afterSelect2 = own.defer(() => {
|
|
20168
20202
|
if (typeof options.onAfterSelect === "function") options.onAfterSelect();
|
|
@@ -20171,10 +20205,13 @@ ${model?.id || ""}`;
|
|
|
20171
20205
|
if (result) clearModelCaches("all");
|
|
20172
20206
|
afterSelect2();
|
|
20173
20207
|
return result;
|
|
20174
|
-
}).catch((e) =>
|
|
20208
|
+
}).catch((e) => {
|
|
20209
|
+
store.pushNotice(`Couldn\u2019t save model: ${e?.message || e}`, "error");
|
|
20210
|
+
if (handoffPanel) afterSelect2();
|
|
20211
|
+
});
|
|
20175
20212
|
return;
|
|
20176
20213
|
}
|
|
20177
|
-
own.paint(
|
|
20214
|
+
own.paint(handoffPanel);
|
|
20178
20215
|
const afterSelect = own.defer(() => {
|
|
20179
20216
|
if (typeof options.onAfterSelect === "function") options.onAfterSelect();
|
|
20180
20217
|
});
|
|
@@ -20185,7 +20222,10 @@ ${model?.id || ""}`;
|
|
|
20185
20222
|
ok ? "info" : "warn"
|
|
20186
20223
|
);
|
|
20187
20224
|
if (ok) afterSelect();
|
|
20188
|
-
}).catch((e) =>
|
|
20225
|
+
}).catch((e) => {
|
|
20226
|
+
store.pushNotice(`Couldn\u2019t switch model: ${e?.message || e}`, "error");
|
|
20227
|
+
if (handoffPanel) afterSelect();
|
|
20228
|
+
});
|
|
20189
20229
|
};
|
|
20190
20230
|
const renderProviderModels = () => {
|
|
20191
20231
|
const providerModelItems = buildProviderModelItems(models, provider, activeRoute);
|
|
@@ -20448,6 +20488,7 @@ function createRoutePickers({
|
|
|
20448
20488
|
};
|
|
20449
20489
|
const openWorkflowPicker = async (options = {}) => {
|
|
20450
20490
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
|
|
20491
|
+
const handoffPanel = options.handoffPanel && typeof options.handoffPanel === "object" ? options.handoffPanel : null;
|
|
20451
20492
|
const own = surface.claim();
|
|
20452
20493
|
let workflows = [];
|
|
20453
20494
|
try {
|
|
@@ -20482,27 +20523,33 @@ function createRoutePickers({
|
|
|
20482
20523
|
onSelect: (_value, item) => {
|
|
20483
20524
|
const workflow = item?._workflow;
|
|
20484
20525
|
if (!workflow) return;
|
|
20485
|
-
own.paint(
|
|
20526
|
+
own.paint(handoffPanel);
|
|
20486
20527
|
const returnAfterSwitch = own.defer(() => {
|
|
20487
20528
|
if (returnTo) returnTo();
|
|
20488
20529
|
});
|
|
20489
20530
|
void store.setWorkflow?.(workflow.id).then((result) => {
|
|
20490
20531
|
if (!result) {
|
|
20491
20532
|
store.pushNotice("Workflow switch is already running.", "warn");
|
|
20533
|
+
if (handoffPanel) returnAfterSwitch();
|
|
20492
20534
|
return;
|
|
20493
20535
|
}
|
|
20494
20536
|
store.pushNotice(workflowSwitchNotice2(result), "info");
|
|
20495
20537
|
returnAfterSwitch();
|
|
20496
|
-
}).catch((e) =>
|
|
20538
|
+
}).catch((e) => {
|
|
20539
|
+
store.pushNotice(`Couldn\u2019t switch workflow: ${e?.message || e}`, "error");
|
|
20540
|
+
if (handoffPanel) returnAfterSwitch();
|
|
20541
|
+
});
|
|
20497
20542
|
},
|
|
20498
20543
|
onCancel: () => {
|
|
20499
|
-
own.
|
|
20544
|
+
if (handoffPanel) own.paint(handoffPanel);
|
|
20545
|
+
else own.close();
|
|
20500
20546
|
if (returnTo) returnTo();
|
|
20501
20547
|
}
|
|
20502
20548
|
});
|
|
20503
20549
|
};
|
|
20504
20550
|
const openOutputStylePicker = async (options = {}) => {
|
|
20505
20551
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
|
|
20552
|
+
const handoffPanel = options.handoffPanel && typeof options.handoffPanel === "object" ? options.handoffPanel : null;
|
|
20506
20553
|
const onboarding = options.onboarding || null;
|
|
20507
20554
|
const own = surface.claim();
|
|
20508
20555
|
let status = null;
|
|
@@ -20534,7 +20581,7 @@ function createRoutePickers({
|
|
|
20534
20581
|
closeUsagePanel();
|
|
20535
20582
|
const saveStyle = (styleId, { advance = false } = {}) => {
|
|
20536
20583
|
if (!styleId) return;
|
|
20537
|
-
if (!(advance && onboarding)) own.paint(
|
|
20584
|
+
if (!(advance && onboarding)) own.paint(handoffPanel);
|
|
20538
20585
|
const advanceAfterSave = own.defer(() => {
|
|
20539
20586
|
if (advance && onboarding) onboarding.onAdvance?.();
|
|
20540
20587
|
else if (returnTo) returnTo();
|
|
@@ -20546,7 +20593,10 @@ function createRoutePickers({
|
|
|
20546
20593
|
store.pushNotice(outputStyleNotice(result), "info");
|
|
20547
20594
|
}
|
|
20548
20595
|
advanceAfterSave();
|
|
20549
|
-
}).catch((e) =>
|
|
20596
|
+
}).catch((e) => {
|
|
20597
|
+
store.pushNotice(`Couldn\u2019t switch output style: ${e?.message || e}`, "error");
|
|
20598
|
+
if (handoffPanel) advanceAfterSave();
|
|
20599
|
+
});
|
|
20550
20600
|
};
|
|
20551
20601
|
own.paint({
|
|
20552
20602
|
title: "Output Style",
|
|
@@ -20579,7 +20629,8 @@ function createRoutePickers({
|
|
|
20579
20629
|
saveStyle(style.id, { advance: Boolean(onboarding) });
|
|
20580
20630
|
},
|
|
20581
20631
|
onCancel: () => {
|
|
20582
|
-
own.
|
|
20632
|
+
if (handoffPanel) own.paint(handoffPanel);
|
|
20633
|
+
else own.close();
|
|
20583
20634
|
if (onboarding) onboarding.onCancel?.();
|
|
20584
20635
|
else if (returnTo) returnTo();
|
|
20585
20636
|
}
|
|
@@ -20749,6 +20800,15 @@ function createSettingsPicker({
|
|
|
20749
20800
|
openMemoryCorePicker,
|
|
20750
20801
|
openUpdatePicker
|
|
20751
20802
|
}) {
|
|
20803
|
+
const settingsHandoffPanel = (description = "Loading settings...") => ({
|
|
20804
|
+
title: "Settings",
|
|
20805
|
+
description,
|
|
20806
|
+
help: "Esc Close",
|
|
20807
|
+
indexMode: "never",
|
|
20808
|
+
pickerKey: "settings-handoff",
|
|
20809
|
+
loading: true,
|
|
20810
|
+
items: []
|
|
20811
|
+
});
|
|
20752
20812
|
const nextSettingsRequest = () => {
|
|
20753
20813
|
if (!settingsRequestRef) return 0;
|
|
20754
20814
|
settingsRequestRef.current = (Number(settingsRequestRef.current) || 0) + 1;
|
|
@@ -20758,6 +20818,7 @@ function createSettingsPicker({
|
|
|
20758
20818
|
const buildSettingsPicker = async (opts = {}, requestId = 0) => {
|
|
20759
20819
|
const own = surface.claim();
|
|
20760
20820
|
const light = opts.light === true;
|
|
20821
|
+
if (!light && !own.paint(settingsHandoffPanel())) return;
|
|
20761
20822
|
const overrides = opts.overrides || null;
|
|
20762
20823
|
const heavyCache = light ? settingsHeavyCacheRef.current : null;
|
|
20763
20824
|
const snapshot = await store.getSettingsSnapshot?.({ heavy: !heavyCache }) || {};
|
|
@@ -21100,14 +21161,24 @@ function createSettingsPicker({
|
|
|
21100
21161
|
else if (item._action === "memory-enabled") toggleMemory();
|
|
21101
21162
|
else if (item._action === "memory-cycles") toggleMemoryCycles();
|
|
21102
21163
|
else if (item._action === "voice") applyVoice();
|
|
21103
|
-
else if (item._action === "output-style") openOutputStylePicker({
|
|
21104
|
-
|
|
21105
|
-
|
|
21164
|
+
else if (item._action === "output-style") openOutputStylePicker({
|
|
21165
|
+
returnTo: openSettingsPicker,
|
|
21166
|
+
handoffPanel: settingsHandoffPanel("Applying output style...")
|
|
21167
|
+
});
|
|
21168
|
+
else if (item._action === "theme") openThemePicker({
|
|
21169
|
+
returnTo: openSettingsPicker,
|
|
21170
|
+
handoffPanel: settingsHandoffPanel("Applying theme...")
|
|
21171
|
+
});
|
|
21172
|
+
else if (item._action === "workflow") openWorkflowPicker({
|
|
21173
|
+
returnTo: openSettingsPicker,
|
|
21174
|
+
handoffPanel: settingsHandoffPanel("Switching workflow...")
|
|
21175
|
+
});
|
|
21106
21176
|
else if (item._action === "model") openModelPicker({
|
|
21107
21177
|
returnTo: openSettingsPicker,
|
|
21108
21178
|
returnLabel: "Settings",
|
|
21109
21179
|
returnOnNestedCancel: true,
|
|
21110
|
-
onAfterSelect: openSettingsPicker
|
|
21180
|
+
onAfterSelect: openSettingsPicker,
|
|
21181
|
+
handoffPanel: settingsHandoffPanel("Switching model...")
|
|
21111
21182
|
});
|
|
21112
21183
|
else if (item._action === "websearch") openWebSearchPicker({
|
|
21113
21184
|
returnTo: openSettingsPicker,
|
|
@@ -21199,6 +21270,42 @@ function createSlashDispatch({
|
|
|
21199
21270
|
runDoctor,
|
|
21200
21271
|
requestExit
|
|
21201
21272
|
}) {
|
|
21273
|
+
const openSlashPanel = (command, title, open) => {
|
|
21274
|
+
const own = surface.claim();
|
|
21275
|
+
if (!own.paint({
|
|
21276
|
+
_kind: `slash-loading:${command}`,
|
|
21277
|
+
title,
|
|
21278
|
+
description: `Loading ${title.toLowerCase()}...`,
|
|
21279
|
+
help: "Esc Close",
|
|
21280
|
+
indexMode: "never",
|
|
21281
|
+
pickerKey: `slash-loading:${command}`,
|
|
21282
|
+
loading: true,
|
|
21283
|
+
items: [],
|
|
21284
|
+
onSelect: () => {
|
|
21285
|
+
},
|
|
21286
|
+
onCancel: () => own.close()
|
|
21287
|
+
})) return;
|
|
21288
|
+
const finishUnclaimedLoading = () => {
|
|
21289
|
+
if (own.owns()) own.close();
|
|
21290
|
+
};
|
|
21291
|
+
try {
|
|
21292
|
+
const opening = open();
|
|
21293
|
+
if (opening && typeof opening.then === "function") {
|
|
21294
|
+
void Promise.resolve(opening).then(
|
|
21295
|
+
finishUnclaimedLoading,
|
|
21296
|
+
(error) => {
|
|
21297
|
+
finishUnclaimedLoading();
|
|
21298
|
+
store.pushNotice(`${title} panel failed: ${error?.message || error}`, "error");
|
|
21299
|
+
}
|
|
21300
|
+
);
|
|
21301
|
+
} else {
|
|
21302
|
+
finishUnclaimedLoading();
|
|
21303
|
+
}
|
|
21304
|
+
} catch (error) {
|
|
21305
|
+
finishUnclaimedLoading();
|
|
21306
|
+
store.pushNotice(`${title} panel failed: ${error?.message || error}`, "error");
|
|
21307
|
+
}
|
|
21308
|
+
};
|
|
21202
21309
|
const runSlashCommand = (cmd, arg = "") => {
|
|
21203
21310
|
const rawName = String(cmd || "").toLowerCase();
|
|
21204
21311
|
cmd = normalizeSlashCommandName2(cmd);
|
|
@@ -21225,25 +21332,27 @@ function createSlashDispatch({
|
|
|
21225
21332
|
return true;
|
|
21226
21333
|
case "model":
|
|
21227
21334
|
if (!arg) {
|
|
21228
|
-
openModelPicker();
|
|
21335
|
+
openSlashPanel("model", "Model", () => openModelPicker());
|
|
21229
21336
|
return true;
|
|
21230
21337
|
}
|
|
21231
21338
|
if (arg.trim().toLowerCase() === "refresh") {
|
|
21232
|
-
openModelPicker({ refreshModels: true });
|
|
21339
|
+
openSlashPanel("model", "Model", () => openModelPicker({ refreshModels: true }));
|
|
21233
21340
|
return true;
|
|
21234
21341
|
}
|
|
21235
21342
|
void store.setModel(arg).then((ok) => store.pushNotice(ok ? modelSwitchNotice2() : "Model switch is already running.", ok ? "info" : "warn")).catch((e) => store.pushNotice(`Couldn\u2019t switch model: ${e?.message || e}`, "error"));
|
|
21236
21343
|
return true;
|
|
21237
21344
|
case "websearch":
|
|
21238
21345
|
if (arg) store.pushNotice("/websearch sets the web-search provider/model; the web_search tool uses that model when called.", "warn");
|
|
21239
|
-
openWebSearchPicker();
|
|
21346
|
+
openSlashPanel("websearch", "Web Search Model", () => openWebSearchPicker());
|
|
21240
21347
|
return true;
|
|
21241
21348
|
case "agents":
|
|
21242
|
-
|
|
21349
|
+
openSlashPanel("agents", "Agents", () => openAgentsPicker(
|
|
21350
|
+
arg.trim().toLowerCase() === "refresh" ? { refreshModels: true } : {}
|
|
21351
|
+
));
|
|
21243
21352
|
return true;
|
|
21244
21353
|
case "workflow":
|
|
21245
21354
|
if (!arg) {
|
|
21246
|
-
openWorkflowPicker();
|
|
21355
|
+
openSlashPanel("workflow", "Workflow", () => openWorkflowPicker());
|
|
21247
21356
|
return true;
|
|
21248
21357
|
}
|
|
21249
21358
|
void store.setWorkflow?.(arg.trim()).then((result) => {
|
|
@@ -21262,7 +21371,7 @@ function createSlashDispatch({
|
|
|
21262
21371
|
const value = arg.trim();
|
|
21263
21372
|
const lower = value.toLowerCase();
|
|
21264
21373
|
if (!value) {
|
|
21265
|
-
openOutputStylePicker();
|
|
21374
|
+
openSlashPanel("outputstyle", "Output Style", () => openOutputStylePicker());
|
|
21266
21375
|
return true;
|
|
21267
21376
|
}
|
|
21268
21377
|
if (lower === "status" || lower === "current" || lower === "show") {
|
|
@@ -21285,7 +21394,7 @@ function createSlashDispatch({
|
|
|
21285
21394
|
const value = arg.trim();
|
|
21286
21395
|
const lower = value.toLowerCase();
|
|
21287
21396
|
if (!value) {
|
|
21288
|
-
openThemePicker();
|
|
21397
|
+
openSlashPanel("theme", "Theme", () => openThemePicker());
|
|
21289
21398
|
return true;
|
|
21290
21399
|
}
|
|
21291
21400
|
let themes = [];
|
|
@@ -21318,7 +21427,7 @@ function createSlashDispatch({
|
|
|
21318
21427
|
case "effort": {
|
|
21319
21428
|
const pendingTurn = state.busy ? " (applies from the next turn)" : "";
|
|
21320
21429
|
if (!arg) {
|
|
21321
|
-
openEffortPicker();
|
|
21430
|
+
openSlashPanel("effort", "Effort", () => openEffortPicker());
|
|
21322
21431
|
return true;
|
|
21323
21432
|
}
|
|
21324
21433
|
void store.setEffort(arg).then((result) => store.pushNotice(result ? `Effort set to ${result}${pendingTurn}` : "Effort switch is already running.", result ? "info" : "warn")).catch((e) => store.pushNotice(`Couldn\u2019t switch effort: ${e?.message || e}`, "error"));
|
|
@@ -21350,23 +21459,23 @@ function createSlashDispatch({
|
|
|
21350
21459
|
enterProject(target);
|
|
21351
21460
|
return true;
|
|
21352
21461
|
}
|
|
21353
|
-
openProjectPicker();
|
|
21462
|
+
openSlashPanel("project", "Projects", () => openProjectPicker());
|
|
21354
21463
|
return true;
|
|
21355
21464
|
}
|
|
21356
21465
|
case "mcp":
|
|
21357
|
-
openMcpPicker();
|
|
21466
|
+
openSlashPanel("mcp", "MCP Servers", () => openMcpPicker());
|
|
21358
21467
|
return true;
|
|
21359
21468
|
case "skills":
|
|
21360
|
-
openSkillsPicker();
|
|
21469
|
+
openSlashPanel("skills", "Skills", () => openSkillsPicker());
|
|
21361
21470
|
return true;
|
|
21362
21471
|
case "plugins":
|
|
21363
|
-
openPluginsPicker();
|
|
21472
|
+
openSlashPanel("plugins", "Plugins", () => openPluginsPicker());
|
|
21364
21473
|
return true;
|
|
21365
21474
|
case "hooks":
|
|
21366
|
-
openHooksPicker();
|
|
21475
|
+
openSlashPanel("hooks", "Hooks", () => openHooksPicker());
|
|
21367
21476
|
return true;
|
|
21368
21477
|
case "providers":
|
|
21369
|
-
|
|
21478
|
+
openSlashPanel("providers", "Providers", () => openProviderSetupPicker());
|
|
21370
21479
|
return true;
|
|
21371
21480
|
case "schedules":
|
|
21372
21481
|
case "webhooks":
|
|
@@ -21374,7 +21483,7 @@ function createSlashDispatch({
|
|
|
21374
21483
|
return true;
|
|
21375
21484
|
case "memory": {
|
|
21376
21485
|
if (!arg.trim()) {
|
|
21377
|
-
openMemoryCorePicker({ returnTo: null });
|
|
21486
|
+
openSlashPanel("memory", "Memory", () => openMemoryCorePicker({ returnTo: null }));
|
|
21378
21487
|
return true;
|
|
21379
21488
|
}
|
|
21380
21489
|
void store.memoryControl?.(parseMemoryCommand2(arg)).catch((e) => store.pushNotice(`memory failed: ${e?.message || e}`, "error"));
|
|
@@ -21383,7 +21492,7 @@ function createSlashDispatch({
|
|
|
21383
21492
|
case "autoclear": {
|
|
21384
21493
|
const value = arg.trim().toLowerCase();
|
|
21385
21494
|
if (!value) {
|
|
21386
|
-
openAutoClearPicker();
|
|
21495
|
+
openSlashPanel("autoclear", "Auto-clear", () => openAutoClearPicker());
|
|
21387
21496
|
return true;
|
|
21388
21497
|
}
|
|
21389
21498
|
void Promise.resolve(
|
|
@@ -21422,6 +21531,15 @@ function createSlashDispatch({
|
|
|
21422
21531
|
store.pushNotice("Compact done.", "info");
|
|
21423
21532
|
}).catch((error) => store.pushNotice(compactFailureNotice(error), "error"));
|
|
21424
21533
|
return true;
|
|
21534
|
+
case "goal":
|
|
21535
|
+
void Promise.resolve(store.goalControl?.({ command: arg })).then((result) => {
|
|
21536
|
+
if (!result) {
|
|
21537
|
+
store.pushNotice("Goal is unavailable.", "warn");
|
|
21538
|
+
return;
|
|
21539
|
+
}
|
|
21540
|
+
store.pushNotice(result.message || "Goal updated.", "info");
|
|
21541
|
+
}).catch((error) => store.pushNotice(`Goal failed: ${error?.message || error}`, "error"));
|
|
21542
|
+
return true;
|
|
21425
21543
|
case "resume":
|
|
21426
21544
|
if (state.busy) {
|
|
21427
21545
|
store.pushNotice("wait for the current turn to finish before /resume", "warn");
|
|
@@ -21430,14 +21548,14 @@ function createSlashDispatch({
|
|
|
21430
21548
|
if (arg) {
|
|
21431
21549
|
void store.resume(arg).then((ok) => store.pushNotice(ok ? `Resumed ${arg}` : "Couldn\u2019t resume chat.", ok ? "info" : "warn")).catch((e) => store.pushNotice(`Couldn\u2019t resume chat: ${e?.message || e}`, "error"));
|
|
21432
21550
|
} else {
|
|
21433
|
-
openResumePicker();
|
|
21551
|
+
openSlashPanel("resume", "Resume", () => openResumePicker());
|
|
21434
21552
|
}
|
|
21435
21553
|
return true;
|
|
21436
21554
|
case "usage":
|
|
21437
|
-
openUsagePanel(arg);
|
|
21555
|
+
openSlashPanel("usage", "Provider Quotas", () => openUsagePanel(arg));
|
|
21438
21556
|
return true;
|
|
21439
21557
|
case "context":
|
|
21440
|
-
openContextPicker();
|
|
21558
|
+
openSlashPanel("context", "Context Usage", () => openContextPicker());
|
|
21441
21559
|
return true;
|
|
21442
21560
|
case "inherit":
|
|
21443
21561
|
if (state.busy) {
|
|
@@ -21457,13 +21575,13 @@ function createSlashDispatch({
|
|
|
21457
21575
|
return true;
|
|
21458
21576
|
case "settings":
|
|
21459
21577
|
case "config":
|
|
21460
|
-
openSettingsPicker();
|
|
21578
|
+
openSlashPanel("settings", "Settings", () => openSettingsPicker());
|
|
21461
21579
|
return true;
|
|
21462
21580
|
case "profile":
|
|
21463
|
-
openProfilePicker();
|
|
21581
|
+
openSlashPanel("profile", "Profile", () => openProfilePicker());
|
|
21464
21582
|
return true;
|
|
21465
21583
|
case "update":
|
|
21466
|
-
openUpdatePicker();
|
|
21584
|
+
openSlashPanel("update", "Update", () => openUpdatePicker());
|
|
21467
21585
|
return true;
|
|
21468
21586
|
case "doctor":
|
|
21469
21587
|
if (state.commandBusy) {
|
|
@@ -22648,6 +22766,7 @@ function createProjectPicker({
|
|
|
22648
22766
|
description: "Opening folder picker\u2026 choose a folder in the dialog window.",
|
|
22649
22767
|
help: "Waiting for the system folder dialog\u2026",
|
|
22650
22768
|
indexMode: "never",
|
|
22769
|
+
loading: true,
|
|
22651
22770
|
items: [],
|
|
22652
22771
|
onSelect: () => {
|
|
22653
22772
|
},
|
|
@@ -48,6 +48,7 @@ export function createContextState({ runtime, getState, updateState, getPendingS
|
|
|
48
48
|
webSearchRoute: runtime.getWebSearchRoute?.() || runtime.webSearchRoute || null,
|
|
49
49
|
autoClear: autoClearState(),
|
|
50
50
|
workflow: runtime.workflow || null,
|
|
51
|
+
goal: runtime.goalStatus?.() || null,
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
const routeState = () => {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
function clean(value) {
|
|
2
|
+
return String(value ?? '').trim();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function isGoalContinuation(entry) {
|
|
6
|
+
return entry?.mode === 'goal-continuation';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createGoalContinuation({
|
|
10
|
+
runtime,
|
|
11
|
+
flags,
|
|
12
|
+
getState,
|
|
13
|
+
set,
|
|
14
|
+
getPending,
|
|
15
|
+
enqueue,
|
|
16
|
+
} = {}) {
|
|
17
|
+
let scheduled = null;
|
|
18
|
+
let disposed = false;
|
|
19
|
+
|
|
20
|
+
const cancelQueuedGoalContinuations = () => {
|
|
21
|
+
const pending = getPending();
|
|
22
|
+
let removed = 0;
|
|
23
|
+
for (let index = pending.length - 1; index >= 0; index -= 1) {
|
|
24
|
+
if (!isGoalContinuation(pending[index])) continue;
|
|
25
|
+
pending.splice(index, 1);
|
|
26
|
+
removed += 1;
|
|
27
|
+
}
|
|
28
|
+
return removed;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const refreshGoalState = () => {
|
|
32
|
+
const goal = runtime.goalStatus?.() || null;
|
|
33
|
+
if (getState().goal !== goal) set({ goal });
|
|
34
|
+
return goal;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const continuationDecision = () => {
|
|
38
|
+
const decision = runtime.goalContinuation?.() || { run: false, reason: 'unavailable', goal: null };
|
|
39
|
+
if (getState().goal !== decision.goal) set({ goal: decision.goal || null });
|
|
40
|
+
return decision;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const shouldRunGoalContinuation = (entry) => {
|
|
44
|
+
if (disposed || flags.disposed || flags.pendingSessionReset) return false;
|
|
45
|
+
if (getState().sessionRemoteAttached) return false;
|
|
46
|
+
const decision = continuationDecision();
|
|
47
|
+
if (!decision.run) return false;
|
|
48
|
+
const queuedGoalId = clean(entry?.goalId);
|
|
49
|
+
return !queuedGoalId || queuedGoalId === clean(decision.goal?.id);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const scheduleGoalContinuation = () => {
|
|
53
|
+
if (disposed || scheduled) return false;
|
|
54
|
+
scheduled = setImmediate(() => {
|
|
55
|
+
scheduled = null;
|
|
56
|
+
if (disposed || flags.disposed || flags.pendingSessionReset) return;
|
|
57
|
+
const state = getState();
|
|
58
|
+
if (state.busy || state.commandBusy || state.sessionRemoteAttached) return;
|
|
59
|
+
const pending = getPending();
|
|
60
|
+
if (pending.some((entry) => !isGoalContinuation(entry))) return;
|
|
61
|
+
if (pending.some(isGoalContinuation)) return;
|
|
62
|
+
const decision = continuationDecision();
|
|
63
|
+
if (!decision.run || !clean(decision.prompt)) return;
|
|
64
|
+
enqueue(decision.prompt, {
|
|
65
|
+
mode: 'goal-continuation',
|
|
66
|
+
priority: 'later',
|
|
67
|
+
isMeta: true,
|
|
68
|
+
suppressDisplay: true,
|
|
69
|
+
skipSlashCommands: true,
|
|
70
|
+
restorable: false,
|
|
71
|
+
goalId: clean(decision.goal?.id),
|
|
72
|
+
displayText: '',
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
scheduled.unref?.();
|
|
76
|
+
return true;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const onGoalChanged = (event = {}) => {
|
|
80
|
+
const currentSessionId = clean(getState().sessionId || runtime.id);
|
|
81
|
+
if (clean(event.sessionId) && clean(event.sessionId) !== currentSessionId) return;
|
|
82
|
+
cancelQueuedGoalContinuations();
|
|
83
|
+
set({ goal: event.goal || runtime.goalStatus?.() || null });
|
|
84
|
+
if ((event.goal || runtime.goalStatus?.())?.status === 'active') scheduleGoalContinuation();
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const unsubscribe = runtime.onGoalStatusChange?.(onGoalChanged) || (() => {});
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
cancelQueuedGoalContinuations,
|
|
91
|
+
refreshGoalState,
|
|
92
|
+
scheduleGoalContinuation,
|
|
93
|
+
shouldRunGoalContinuation,
|
|
94
|
+
onGoalTurnSettled(status) {
|
|
95
|
+
if (status === 'done') scheduleGoalContinuation();
|
|
96
|
+
},
|
|
97
|
+
archiveCompletedGoalOnUserInput() {
|
|
98
|
+
cancelQueuedGoalContinuations();
|
|
99
|
+
void Promise.resolve(runtime.archiveCompletedGoalOnUserInput?.())
|
|
100
|
+
.then(() => refreshGoalState())
|
|
101
|
+
.catch(() => {});
|
|
102
|
+
},
|
|
103
|
+
disposeGoalContinuation() {
|
|
104
|
+
disposed = true;
|
|
105
|
+
if (scheduled) clearImmediate(scheduled);
|
|
106
|
+
scheduled = null;
|
|
107
|
+
try { unsubscribe(); } catch {}
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|