mixdog 0.9.24 → 0.9.26
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/package.json +2 -1
- package/scripts/build-runtime-windows.ps1 +242 -242
- package/scripts/explore-bench-tmp.mjs +1 -1
- package/scripts/recall-usecase-cases.json +1 -1
- package/scripts/smoke-runtime-negative.ps1 +106 -106
- package/scripts/steering-fold-provenance-test.mjs +71 -0
- package/scripts/tool-efficiency-diag.mjs +1 -1
- package/scripts/webhook-smoke.mjs +46 -53
- package/src/defaults/cycle3-review-prompt.md +11 -4
- package/src/defaults/memory-promote-prompt.md +9 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/rules/lead/02-channels.md +3 -3
- package/src/rules/shared/01-tool.md +8 -4
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +17 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +2 -2
- package/src/runtime/agent/orchestrator/mcp/client.mjs +28 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +51 -15
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +164 -9
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/shell-state.mjs +7 -3
- package/src/runtime/channels/backends/discord.mjs +10 -3
- package/src/runtime/channels/lib/config.mjs +13 -11
- package/src/runtime/channels/lib/inbound-handler.mjs +45 -1
- package/src/runtime/channels/lib/memory-client.mjs +22 -2
- package/src/runtime/channels/lib/owned-runtime.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +226 -208
- package/src/runtime/channels/lib/status-snapshot.mjs +16 -0
- package/src/runtime/channels/lib/webhook/deliveries.mjs +7 -318
- package/src/runtime/channels/lib/webhook.mjs +98 -150
- package/src/runtime/channels/lib/worker-main.mjs +1 -1
- package/src/runtime/memory/index.mjs +50 -25
- package/src/runtime/memory/lib/cycle-scheduler.mjs +20 -2
- package/src/runtime/memory/lib/memory-config-flags.mjs +13 -1
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +59 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +10 -3
- package/src/runtime/memory/lib/memory-cycle3.mjs +79 -9
- package/src/runtime/memory/lib/pg/adapter.mjs +6 -1
- package/src/runtime/memory/lib/pg/process.mjs +19 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +125 -14
- package/src/runtime/memory/lib/query-handlers.mjs +102 -0
- package/src/runtime/memory/lib/recall-format.mjs +60 -22
- package/src/runtime/memory/lib/session-ingest-runtime.mjs +20 -6
- package/src/runtime/memory/tool-defs.mjs +1 -1
- package/src/runtime/shared/child-guardian.mjs +2 -2
- package/src/runtime/shared/open-url.mjs +2 -1
- package/src/runtime/shared/schedules-db.mjs +350 -0
- package/src/runtime/shared/service-discovery.mjs +169 -0
- package/src/runtime/shared/spawn-flags.mjs +27 -0
- package/src/runtime/shared/tool-primitives.mjs +3 -1
- package/src/runtime/shared/tool-surface.mjs +19 -3
- package/src/runtime/shared/update-checker.mjs +54 -10
- package/src/runtime/shared/webhooks-db.mjs +405 -0
- package/src/session-runtime/channel-config-api.mjs +13 -13
- package/src/session-runtime/lifecycle-api.mjs +14 -0
- package/src/session-runtime/runtime-core.mjs +39 -20
- package/src/standalone/agent-tool.mjs +42 -11
- package/src/standalone/channel-admin.mjs +173 -121
- package/src/standalone/channel-worker.mjs +2 -2
- package/src/standalone/memory-runtime-proxy.mjs +10 -5
- package/src/tui/App.jsx +32 -10
- package/src/tui/app/channel-pickers.mjs +9 -9
- package/src/tui/app/clipboard.mjs +14 -0
- package/src/tui/app/doctor.mjs +1 -1
- package/src/tui/app/maintenance-pickers.mjs +17 -7
- package/src/tui/app/settings-picker.mjs +2 -2
- package/src/tui/app/transcript-window.mjs +37 -1
- package/src/tui/app/use-mouse-input.mjs +19 -6
- package/src/tui/components/ToolExecution.jsx +12 -4
- package/src/tui/display-width.mjs +10 -4
- package/src/tui/dist/index.mjs +166 -58
- package/src/tui/engine/agent-job-feed.mjs +42 -3
- package/src/tui/engine/session-api-ext.mjs +12 -12
- package/src/tui/index.jsx +12 -2
- package/src/ui/statusline-segments.mjs +12 -1
- package/src/workflows/default/WORKFLOW.md +29 -38
- package/src/workflows/solo/WORKFLOW.md +15 -20
- package/vendor/ink/build/display-width.js +5 -4
- package/src/runtime/shared/schedules-store.mjs +0 -82
package/src/tui/dist/index.mjs
CHANGED
|
@@ -1798,7 +1798,7 @@ function isExternalMcpToolName(name) {
|
|
|
1798
1798
|
return isMcpToolName(name) && !isSelfMcpToolName(name);
|
|
1799
1799
|
}
|
|
1800
1800
|
function titleCaseMcpServer(server) {
|
|
1801
|
-
return String(server || "").split(/[_\s-]+/).filter(Boolean).map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)
|
|
1801
|
+
return String(server || "").split(/[_\s-]+/).filter(Boolean).map((part) => part === part.toLowerCase() ? `${part.slice(0, 1).toUpperCase()}${part.slice(1)}` : part).join(" ");
|
|
1802
1802
|
}
|
|
1803
1803
|
var TOOL_NAME_ALIASES = { tool_search: "load_tool" };
|
|
1804
1804
|
function normalizeToolName(name) {
|
|
@@ -2839,8 +2839,12 @@ function toolWorkUnit(name, args = {}, category = "") {
|
|
|
2839
2839
|
case "web_search_call":
|
|
2840
2840
|
return unitDescriptor("Web Research", { count: queryCount(a, "query", "queries", "keywords") || 1, noun: "query", pluralNoun: "queries" });
|
|
2841
2841
|
case "web_fetch":
|
|
2842
|
-
case "fetch":
|
|
2843
2842
|
return unitDescriptor("Web Research", { count: queryCount(a, "url", "urls", "uri", "uris") || 1, active: "Fetching", done: "Fetched", noun: "URL", pluralNoun: "URLs" });
|
|
2843
|
+
case "fetch": {
|
|
2844
|
+
const fetchLimit = Number(a.limit ?? a.messages);
|
|
2845
|
+
const fetchCount = Number.isFinite(fetchLimit) && fetchLimit > 0 ? Math.floor(fetchLimit) : queryCount(a, "messages") || 1;
|
|
2846
|
+
return unitDescriptor("Web Research", { count: fetchCount, active: "Fetching", done: "Fetched", noun: "message" });
|
|
2847
|
+
}
|
|
2844
2848
|
case "recall":
|
|
2845
2849
|
case "recall_memory":
|
|
2846
2850
|
case "search_memories":
|
|
@@ -2848,8 +2852,14 @@ function toolWorkUnit(name, args = {}, category = "") {
|
|
|
2848
2852
|
case "remember":
|
|
2849
2853
|
case "save_memory":
|
|
2850
2854
|
case "update_memory":
|
|
2851
|
-
case "memory":
|
|
2852
2855
|
return unitDescriptor("Memory", { count: queryCount(a, "entries", "items", "memories", "query", "text", "value") || 1, active: "Writing", done: "Wrote", noun: "memory item" });
|
|
2856
|
+
case "memory": {
|
|
2857
|
+
const action = String(a.action || "").toLowerCase();
|
|
2858
|
+
const op = String(a.op || "").toLowerCase();
|
|
2859
|
+
const isMutation = op === "add" || op === "edit" || op === "delete" || op === "promote" || op === "dismiss" || action === "core" && !op;
|
|
2860
|
+
if (isMutation) return unitDescriptor("Memory", { count: queryCount(a, "entries", "items", "memories", "query", "text", "value") || 1, active: "Writing", done: "Wrote", noun: "memory item" });
|
|
2861
|
+
return unitDescriptor("Memory", { count: queryCount(a, "entries", "items", "memories", "query", "text", "value") || 1, active: "Checking", done: "Checked", noun: "memory item" });
|
|
2862
|
+
}
|
|
2853
2863
|
case "explore":
|
|
2854
2864
|
return unitDescriptor("Explore", { count: queryCount(a, "query", "queries", "prompt", "task", "goal") || 1, noun: "query", pluralNoun: "queries" });
|
|
2855
2865
|
case "shell":
|
|
@@ -2861,8 +2871,11 @@ function toolWorkUnit(name, args = {}, category = "") {
|
|
|
2861
2871
|
case "agent":
|
|
2862
2872
|
case "bridge":
|
|
2863
2873
|
return unitDescriptor("Agent", { count: queryCount(a, "agents", "roles", "role", "tag", "task_id", "sessionId") || 1, noun: "agent" });
|
|
2864
|
-
case "task":
|
|
2874
|
+
case "task": {
|
|
2875
|
+
const action = String(a.action || "").toLowerCase();
|
|
2876
|
+
if (action === "cancel") return unitDescriptor("Task", { count: queryCount(a, "task_id", "task_ids", "id", "ids") || 1, active: "Cancelling", done: "Cancelled", noun: "task" });
|
|
2865
2877
|
return unitDescriptor("Task", { count: queryCount(a, "task_id", "task_ids", "id", "ids") || 1, noun: "task" });
|
|
2878
|
+
}
|
|
2866
2879
|
case "skill":
|
|
2867
2880
|
case "skill_execute":
|
|
2868
2881
|
case "skill_view":
|
|
@@ -4209,11 +4222,11 @@ function isProblemCodePoint(cp) {
|
|
|
4209
4222
|
return cp >= 9312 && cp <= 9471 || cp >= 8592 && cp <= 8703;
|
|
4210
4223
|
}
|
|
4211
4224
|
var PROBLEM_RE = /[\u2190-\u21ff\u2460-\u24ff]/;
|
|
4212
|
-
function resolveAmbiguousWidePolicy(env = process.env) {
|
|
4225
|
+
function resolveAmbiguousWidePolicy(env = process.env, platform = process.platform) {
|
|
4213
4226
|
const override = env?.MIXDOG_TUI_AMBIGUOUS_WIDE;
|
|
4214
4227
|
if (override === "1") return true;
|
|
4215
4228
|
if (override === "0") return false;
|
|
4216
|
-
return Boolean(env?.WT_SESSION);
|
|
4229
|
+
return platform === "win32" || Boolean(env?.WT_SESSION);
|
|
4217
4230
|
}
|
|
4218
4231
|
var AMBIGUOUS_WIDE = resolveAmbiguousWidePolicy();
|
|
4219
4232
|
function displayWidthWith(str, wide) {
|
|
@@ -7910,8 +7923,15 @@ function osc52ClipboardSequence(text) {
|
|
|
7910
7923
|
return `\x1BPtmux;${raw.replaceAll("\x1B", "\x1B\x1B")}\x1B\\`;
|
|
7911
7924
|
}
|
|
7912
7925
|
var OSC52_MAX_BYTES = 256 * 1024;
|
|
7926
|
+
function shouldSkipOsc52() {
|
|
7927
|
+
if (process.platform !== "win32") return false;
|
|
7928
|
+
if (process.env.TMUX) return false;
|
|
7929
|
+
if (process.env.SSH_CONNECTION || process.env.SSH_TTY) return false;
|
|
7930
|
+
return true;
|
|
7931
|
+
}
|
|
7913
7932
|
function writeOsc52Clipboard(text) {
|
|
7914
7933
|
const value = String(text ?? "");
|
|
7934
|
+
if (shouldSkipOsc52()) return false;
|
|
7915
7935
|
if (Buffer3.byteLength(value, "utf8") > OSC52_MAX_BYTES) return false;
|
|
7916
7936
|
try {
|
|
7917
7937
|
process.stdout.write(osc52ClipboardSequence(value));
|
|
@@ -9998,6 +10018,26 @@ function toolArgPathForRows(item) {
|
|
|
9998
10018
|
const a = backgroundArgsForRows(item?.args);
|
|
9999
10019
|
return a?.path ?? a?.file_path ?? a?.file ?? "";
|
|
10000
10020
|
}
|
|
10021
|
+
function agentCardKeepsCollapsedDetailForRows(item, normalizedName) {
|
|
10022
|
+
if (normalizedName !== "agent") return false;
|
|
10023
|
+
if (toolItemPendingForRows(item)) return false;
|
|
10024
|
+
const bgArgs = backgroundArgsForRows(item.args);
|
|
10025
|
+
const isError = Boolean(item.isError);
|
|
10026
|
+
const hasDisplayResult = toolHasDisplayResultForRows(item);
|
|
10027
|
+
const displayedResultText = toolDisplayedResultTextForRows(item);
|
|
10028
|
+
const rt = item.result == null ? "" : String(item.result).replace(/\s+$/, "");
|
|
10029
|
+
const isAgentResponse = hasDisplayResult && isAgentResponseResultText(rt);
|
|
10030
|
+
const briefRaw = summarizeAgentSurfaceBrief(item.name, bgArgs, displayedResultText, {
|
|
10031
|
+
isError,
|
|
10032
|
+
isResponse: isAgentResponse
|
|
10033
|
+
});
|
|
10034
|
+
const brief = String(briefRaw || "").trim();
|
|
10035
|
+
const status = String(bgArgs.status || "").toLowerCase();
|
|
10036
|
+
const failureText = /\b(cancelled|canceled|failed)\b/i.test(brief) || /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(status);
|
|
10037
|
+
const agentHeaderFailure = isError && String(bgArgs.error || "").trim() && !hasDisplayResult;
|
|
10038
|
+
if (agentHeaderFailure && !brief) return false;
|
|
10039
|
+
return isError || failureText;
|
|
10040
|
+
}
|
|
10001
10041
|
function isShellSurfaceForRows(normalizedName, label = "") {
|
|
10002
10042
|
const n = String(normalizedName || "").toLowerCase();
|
|
10003
10043
|
const l = String(label || "").toLowerCase();
|
|
@@ -10049,6 +10089,9 @@ function estimateTranscriptItemRows(item, columns, toolOutputExpanded) {
|
|
|
10049
10089
|
if (toolHeaderFailureOnlyForRows(item, normalizedName, hasDisplayResult)) {
|
|
10050
10090
|
return TOOL_MARGIN_TOP + 1;
|
|
10051
10091
|
}
|
|
10092
|
+
if (isAgentSurface) {
|
|
10093
|
+
return agentCardKeepsCollapsedDetailForRows(item, normalizedName) ? TOOL_MARGIN_TOP + 1 + 1 : TOOL_MARGIN_TOP + 1;
|
|
10094
|
+
}
|
|
10052
10095
|
return TOOL_MARGIN_TOP + 1 + 1;
|
|
10053
10096
|
}
|
|
10054
10097
|
if (hasRawResult) {
|
|
@@ -10056,7 +10099,9 @@ function estimateTranscriptItemRows(item, columns, toolOutputExpanded) {
|
|
|
10056
10099
|
const rawOpts = item.aggregate ? {} : { pathArg: toolArgPathForRows(item), isShell: isShellSurfaceForToolItem(item, normalizedName) };
|
|
10057
10100
|
return TOOL_MARGIN_TOP + 1 + estimateToolRenderedResultRows(estimateText, { ...rawOpts, columns });
|
|
10058
10101
|
}
|
|
10059
|
-
if (isAgentSurface && !hasResult)
|
|
10102
|
+
if (isAgentSurface && !hasResult) {
|
|
10103
|
+
return agentCardKeepsCollapsedDetailForRows(item, normalizedName) ? TOOL_MARGIN_TOP + 1 + 1 : TOOL_MARGIN_TOP + 1;
|
|
10104
|
+
}
|
|
10060
10105
|
if (isSkillSurface && !hasResult) return TOOL_MARGIN_TOP + 1;
|
|
10061
10106
|
if (item.aggregate) {
|
|
10062
10107
|
if (hasRawResult) {
|
|
@@ -10437,7 +10482,6 @@ function transcriptRenderWindow(items, { scrollOffset = 0, viewportHeight = 24,
|
|
|
10437
10482
|
var MOUSE_TRACKING_ON = "\x1B[?1000h\x1B[?1002h\x1B[?1006h";
|
|
10438
10483
|
var MOUSE_TRACKING_OFF = "\x1B[?1006l\x1B[?1002l\x1B[?1000l";
|
|
10439
10484
|
var ALT_SCROLL_OFF = "\x1B[?1007l";
|
|
10440
|
-
var ALT_SCROLL_ON = "\x1B[?1007h";
|
|
10441
10485
|
var MOUSE_MODIFIER_MASK = 4 | 8 | 16;
|
|
10442
10486
|
var MOUSE_CTRL_MASK = 16;
|
|
10443
10487
|
var MOUSE_SHIFT_MASK = 4;
|
|
@@ -10478,14 +10522,19 @@ function useMouseInput({
|
|
|
10478
10522
|
} catch {
|
|
10479
10523
|
return;
|
|
10480
10524
|
}
|
|
10481
|
-
|
|
10482
|
-
zoomTimerRef.current = setTimeout(() => {
|
|
10525
|
+
const restore = (attempt) => {
|
|
10483
10526
|
zoomTimerRef.current = null;
|
|
10484
10527
|
try {
|
|
10485
|
-
stdout.write(
|
|
10528
|
+
stdout.write(MOUSE_TRACKING_ON + ALT_SCROLL_OFF);
|
|
10486
10529
|
} catch {
|
|
10530
|
+
if (attempt < 5) {
|
|
10531
|
+
zoomTimerRef.current = setTimeout(() => restore(attempt + 1), 200);
|
|
10532
|
+
zoomTimerRef.current.unref?.();
|
|
10533
|
+
}
|
|
10487
10534
|
}
|
|
10488
|
-
}
|
|
10535
|
+
};
|
|
10536
|
+
if (zoomTimerRef.current) clearTimeout(zoomTimerRef.current);
|
|
10537
|
+
zoomTimerRef.current = setTimeout(() => restore(0), 700);
|
|
10489
10538
|
zoomTimerRef.current.unref?.();
|
|
10490
10539
|
}, [stdout, zoomTimerRef]);
|
|
10491
10540
|
useEffect6(() => () => {
|
|
@@ -13348,13 +13397,14 @@ function createMaintenancePickers({
|
|
|
13348
13397
|
const upd = readSettings();
|
|
13349
13398
|
const status = readStatus();
|
|
13350
13399
|
const current = upd.currentVersion || "unknown";
|
|
13400
|
+
const installedVersion = status.phase === "installed" ? status.version || upd.latestVersion || null : null;
|
|
13351
13401
|
const latestMeta = checking || status.phase === "checking" ? "checking\u2026" : upd.latestVersion || "unknown";
|
|
13352
13402
|
const items = [
|
|
13353
13403
|
{
|
|
13354
13404
|
value: "current",
|
|
13355
13405
|
label: "Current version",
|
|
13356
|
-
meta: current,
|
|
13357
|
-
description: "Installed mixdog version.",
|
|
13406
|
+
meta: installedVersion ? `${current} \u2192 ${installedVersion}` : current,
|
|
13407
|
+
description: installedVersion ? `v${installedVersion} installed \u2014 restart mixdog to apply.` : "Installed mixdog version.",
|
|
13358
13408
|
_action: "current"
|
|
13359
13409
|
},
|
|
13360
13410
|
{
|
|
@@ -13388,11 +13438,11 @@ function createMaintenancePickers({
|
|
|
13388
13438
|
buttons: [
|
|
13389
13439
|
{
|
|
13390
13440
|
value: "update-now",
|
|
13391
|
-
label: upd.updateAvailable ? `Update to v${upd.latestVersion || "latest"}` : "Update now"
|
|
13441
|
+
label: installedVersion ? `v${installedVersion} installed \u2014 restart to apply` : status.phase === "installing" ? "Installing\u2026" : upd.updateAvailable ? `Update to v${upd.latestVersion || "latest"}` : "Update now"
|
|
13392
13442
|
}
|
|
13393
13443
|
],
|
|
13394
13444
|
onConfirm: (button) => {
|
|
13395
|
-
if (button?.value === "update-now") runUpdate();
|
|
13445
|
+
if (button?.value === "update-now" && !installedVersion && status.phase !== "installing") runUpdate();
|
|
13396
13446
|
}
|
|
13397
13447
|
},
|
|
13398
13448
|
onSelect: (_value, item) => {
|
|
@@ -13428,7 +13478,7 @@ function createMaintenancePickers({
|
|
|
13428
13478
|
store.pushNotice("Updating\u2026", "info");
|
|
13429
13479
|
void Promise.resolve(store.runUpdateNow?.()).then((result) => {
|
|
13430
13480
|
if (result?.ok) {
|
|
13431
|
-
store.pushNotice(`v${result.version} installed \u2014 restart to apply`, "
|
|
13481
|
+
store.pushNotice(`v${result.version} installed \u2014 restart to apply`, "warn");
|
|
13432
13482
|
} else {
|
|
13433
13483
|
store.pushNotice(`Update failed: ${result?.error || "unknown error"}`, "error");
|
|
13434
13484
|
}
|
|
@@ -14958,7 +15008,7 @@ function createChannelPickers({
|
|
|
14958
15008
|
onboardingWarnReopen
|
|
14959
15009
|
}) {
|
|
14960
15010
|
let pickerGen = 0;
|
|
14961
|
-
const openChannelTypeActionsPicker = (backend, options = {}) => {
|
|
15011
|
+
const openChannelTypeActionsPicker = async (backend, options = {}) => {
|
|
14962
15012
|
pickerGen += 1;
|
|
14963
15013
|
const parentReturn = typeof options.returnTo === "function" ? options.returnTo : () => openChannelSettingTypePicker();
|
|
14964
15014
|
setProviderPrompt(null);
|
|
@@ -14967,7 +15017,7 @@ function createChannelPickers({
|
|
|
14967
15017
|
setContextPanel(null);
|
|
14968
15018
|
let setup;
|
|
14969
15019
|
try {
|
|
14970
|
-
setup = store.getChannelSetup();
|
|
15020
|
+
setup = await store.getChannelSetup();
|
|
14971
15021
|
} catch (e) {
|
|
14972
15022
|
store.pushNotice(`channels failed: ${e?.message || e}`, "error");
|
|
14973
15023
|
return;
|
|
@@ -15041,7 +15091,7 @@ function createChannelPickers({
|
|
|
15041
15091
|
}
|
|
15042
15092
|
});
|
|
15043
15093
|
};
|
|
15044
|
-
const openChannelSettingTypePicker = (options = {}) => {
|
|
15094
|
+
const openChannelSettingTypePicker = async (options = {}) => {
|
|
15045
15095
|
pickerGen += 1;
|
|
15046
15096
|
const returnTo = typeof options.returnTo === "function" ? options.returnTo : () => {
|
|
15047
15097
|
};
|
|
@@ -15052,7 +15102,7 @@ function createChannelPickers({
|
|
|
15052
15102
|
setContextPanel(null);
|
|
15053
15103
|
let setup;
|
|
15054
15104
|
try {
|
|
15055
|
-
setup = store.getChannelSetup();
|
|
15105
|
+
setup = await store.getChannelSetup();
|
|
15056
15106
|
} catch (e) {
|
|
15057
15107
|
store.pushNotice(`channels failed: ${e?.message || e}`, "error");
|
|
15058
15108
|
return;
|
|
@@ -15115,7 +15165,7 @@ function createChannelPickers({
|
|
|
15115
15165
|
setContextPanel(null);
|
|
15116
15166
|
let setup;
|
|
15117
15167
|
try {
|
|
15118
|
-
setup = store.getChannelSetup();
|
|
15168
|
+
setup = await store.getChannelSetup();
|
|
15119
15169
|
} catch (e) {
|
|
15120
15170
|
store.pushNotice(`channels failed: ${e?.message || e}`, "error");
|
|
15121
15171
|
return;
|
|
@@ -15148,14 +15198,14 @@ function createChannelPickers({
|
|
|
15148
15198
|
_action: "noop"
|
|
15149
15199
|
}]
|
|
15150
15200
|
];
|
|
15151
|
-
const toggleSchedule = (item) => {
|
|
15201
|
+
const toggleSchedule = async (item) => {
|
|
15152
15202
|
if (item._action !== "schedule-toggle") return;
|
|
15153
15203
|
if (!channelRemoteEnabled) {
|
|
15154
15204
|
store.pushNotice("enable channel first", "warn");
|
|
15155
15205
|
return;
|
|
15156
15206
|
}
|
|
15157
15207
|
try {
|
|
15158
|
-
store.setScheduleEnabled?.(item._name, !item._enabled);
|
|
15208
|
+
await store.setScheduleEnabled?.(item._name, !item._enabled);
|
|
15159
15209
|
void openChannelSetupPicker("schedules", { highlightValue: `schedule:${item._name}` });
|
|
15160
15210
|
} catch (e) {
|
|
15161
15211
|
store.pushNotice(`schedule toggle failed: ${e?.message || e}`, "error");
|
|
@@ -15251,14 +15301,14 @@ function createChannelPickers({
|
|
|
15251
15301
|
_action: "noop"
|
|
15252
15302
|
}]
|
|
15253
15303
|
];
|
|
15254
|
-
const toggleWebhook = (item) => {
|
|
15304
|
+
const toggleWebhook = async (item) => {
|
|
15255
15305
|
if (item._action !== "webhook-toggle") return;
|
|
15256
15306
|
if (!channelRemoteEnabled) {
|
|
15257
15307
|
store.pushNotice("enable channel first", "warn");
|
|
15258
15308
|
return;
|
|
15259
15309
|
}
|
|
15260
15310
|
try {
|
|
15261
|
-
store.setWebhookEnabled?.(item._name, !item._enabled);
|
|
15311
|
+
await store.setWebhookEnabled?.(item._name, !item._enabled);
|
|
15262
15312
|
void openChannelSetupPicker("webhooks", { highlightValue: `webhook:${item._name}` });
|
|
15263
15313
|
} catch (e) {
|
|
15264
15314
|
store.pushNotice(`webhook toggle failed: ${e?.message || e}`, "error");
|
|
@@ -16722,7 +16772,7 @@ function createSettingsPicker({
|
|
|
16722
16772
|
openUpdatePicker,
|
|
16723
16773
|
openChannelSettingTypePicker
|
|
16724
16774
|
}) {
|
|
16725
|
-
const openSettingsPicker = (opts = {}) => {
|
|
16775
|
+
const openSettingsPicker = async (opts = {}) => {
|
|
16726
16776
|
const light = opts.light === true;
|
|
16727
16777
|
const overrides = opts.overrides || null;
|
|
16728
16778
|
const heavyCache = light ? settingsHeavyCacheRef.current : null;
|
|
@@ -16742,7 +16792,7 @@ function createSettingsPicker({
|
|
|
16742
16792
|
channelBackend = heavyCache.channelBackend || "discord";
|
|
16743
16793
|
} else {
|
|
16744
16794
|
try {
|
|
16745
|
-
channelBackend = store.getChannelSetup?.()?.backend || "discord";
|
|
16795
|
+
channelBackend = (await store.getChannelSetup?.())?.backend || "discord";
|
|
16746
16796
|
} catch {
|
|
16747
16797
|
channelBackend = "discord";
|
|
16748
16798
|
}
|
|
@@ -18672,7 +18722,7 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, exp
|
|
|
18672
18722
|
}, [pending, pendingDisplayReady, startedAtMs]);
|
|
18673
18723
|
if (pending && !pendingDisplayReady) {
|
|
18674
18724
|
const placeholderNormalizedName = String(formatToolSurface(name, args)?.normalizedName || "").toLowerCase();
|
|
18675
|
-
const placeholderSingleRow = !aggregate && SKILL_SURFACE_NAMES2.has(placeholderNormalizedName);
|
|
18725
|
+
const placeholderSingleRow = !aggregate && (SKILL_SURFACE_NAMES2.has(placeholderNormalizedName) || isAgentTool(placeholderNormalizedName));
|
|
18676
18726
|
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", marginTop: attached ? 0 : 1, width: rowWidth, overflow: "hidden", children: [
|
|
18677
18727
|
/* @__PURE__ */ jsx16(Text16, { children: " " }),
|
|
18678
18728
|
placeholderSingleRow ? null : /* @__PURE__ */ jsx16(Text16, { children: " " })
|
|
@@ -18784,7 +18834,9 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, exp
|
|
|
18784
18834
|
} else if (isAgentSurfaceCard && !showRawResult) {
|
|
18785
18835
|
const agentDetailFallback = collapsedDetail || (pending ? pendingDetailPlaceholder || "Running" : "Finished");
|
|
18786
18836
|
const agentDetailLine = agentSurfaceBrief || truncateToWidth(String(agentDetailFallback), Math.min(AGENT_SURFACE_BRIEF_MAX, maxResultChars));
|
|
18787
|
-
|
|
18837
|
+
const agentFailureText = /\b(Cancelled|Canceled|Failed)\b/i.test(agentSurfaceBrief || collapsedDetail || "");
|
|
18838
|
+
const keepAgentDetail = (isError || agentFailureText) && !(agentHeaderFailure && !agentSurfaceBrief);
|
|
18839
|
+
visibleDetailLines = keepAgentDetail ? [agentDetailLine] : [];
|
|
18788
18840
|
}
|
|
18789
18841
|
const finalStatusColor = toolStatusColor({ pending, groupCount, failedCount, terminalStatus });
|
|
18790
18842
|
const dotColor = finalStatusColor;
|
|
@@ -19932,7 +19984,9 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19932
19984
|
copySelection();
|
|
19933
19985
|
return;
|
|
19934
19986
|
}
|
|
19935
|
-
|
|
19987
|
+
if (process.platform !== "win32") {
|
|
19988
|
+
showSelectionCopyHint("select text to copy \xB7 Esc interrupts", "plain");
|
|
19989
|
+
}
|
|
19936
19990
|
return;
|
|
19937
19991
|
}
|
|
19938
19992
|
if (key.ctrl && (input === "o" || input === "O")) {
|
|
@@ -20398,19 +20452,25 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
20398
20452
|
}
|
|
20399
20453
|
if (channelPrompt.kind === "schedule-add") {
|
|
20400
20454
|
const [name, time, instructions, channel, model] = parts;
|
|
20401
|
-
store.saveSchedule({ name, time, instructions, channel, model })
|
|
20402
|
-
|
|
20403
|
-
|
|
20455
|
+
Promise.resolve(store.saveSchedule({ name, time, instructions, channel, model })).then(() => {
|
|
20456
|
+
setChannelPrompt(null);
|
|
20457
|
+
void openChannelSetupPicker("schedules");
|
|
20458
|
+
}).catch((e) => {
|
|
20459
|
+
store.pushNotice(`schedule save failed: ${e?.message || e}`, "error");
|
|
20460
|
+
});
|
|
20404
20461
|
return true;
|
|
20405
20462
|
}
|
|
20406
20463
|
if (channelPrompt.kind === "webhook-add") {
|
|
20407
20464
|
const [name, instructions, channel, model, parser] = parts;
|
|
20408
|
-
|
|
20409
|
-
|
|
20410
|
-
|
|
20411
|
-
|
|
20412
|
-
|
|
20413
|
-
|
|
20465
|
+
Promise.resolve(store.saveWebhook({ name, instructions, channel, model, parser })).then((result) => {
|
|
20466
|
+
if (result?.secret) {
|
|
20467
|
+
store.pushNotice(`webhook secret for ${result.name}: ${result.secret}`, "info");
|
|
20468
|
+
}
|
|
20469
|
+
setChannelPrompt(null);
|
|
20470
|
+
void openChannelSetupPicker("webhooks");
|
|
20471
|
+
}).catch((e) => {
|
|
20472
|
+
store.pushNotice(`webhook save failed: ${e?.message || e}`, "error");
|
|
20473
|
+
});
|
|
20414
20474
|
return true;
|
|
20415
20475
|
}
|
|
20416
20476
|
} catch (e) {
|
|
@@ -22810,6 +22870,15 @@ function createToolCardResults({
|
|
|
22810
22870
|
}
|
|
22811
22871
|
|
|
22812
22872
|
// src/tui/engine/agent-job-feed.mjs
|
|
22873
|
+
function parseInboundImagePaths(raw) {
|
|
22874
|
+
if (typeof raw !== "string" || !raw) return [];
|
|
22875
|
+
try {
|
|
22876
|
+
const arr = JSON.parse(raw);
|
|
22877
|
+
return Array.isArray(arr) ? arr.filter((p) => typeof p === "string" && p.length > 0) : [];
|
|
22878
|
+
} catch {
|
|
22879
|
+
return [];
|
|
22880
|
+
}
|
|
22881
|
+
}
|
|
22813
22882
|
function createAgentJobFeed({
|
|
22814
22883
|
runtime,
|
|
22815
22884
|
getState,
|
|
@@ -22896,13 +22965,38 @@ function createAgentJobFeed({
|
|
|
22896
22965
|
set(agentStatusState({ force: true }));
|
|
22897
22966
|
}
|
|
22898
22967
|
const modelContent = String(delivery.modelContent ?? delivery.displayText ?? text).trim();
|
|
22899
|
-
|
|
22900
|
-
|
|
22968
|
+
const imagePaths = parseInboundImagePaths(event?.meta?.image_paths);
|
|
22969
|
+
if (!modelContent && imagePaths.length === 0) return true;
|
|
22970
|
+
const enqueueOpts = {
|
|
22901
22971
|
mode: "task-notification",
|
|
22902
22972
|
priority: "next",
|
|
22903
22973
|
key: notificationKey || void 0,
|
|
22904
22974
|
displayText: delivery.displayText || text
|
|
22905
|
-
}
|
|
22975
|
+
};
|
|
22976
|
+
if (imagePaths.length > 0) {
|
|
22977
|
+
void (async () => {
|
|
22978
|
+
if (getDisposed()) return;
|
|
22979
|
+
const parts = [];
|
|
22980
|
+
if (modelContent) parts.push({ type: "text", text: modelContent });
|
|
22981
|
+
for (const p of imagePaths) {
|
|
22982
|
+
let att = null;
|
|
22983
|
+
try {
|
|
22984
|
+
att = await readImageAttachmentFromPath(p);
|
|
22985
|
+
} catch {
|
|
22986
|
+
att = null;
|
|
22987
|
+
}
|
|
22988
|
+
if (!att) continue;
|
|
22989
|
+
if (att.metadataText) parts.push({ type: "text", text: att.metadataText });
|
|
22990
|
+
parts.push({ type: "image", data: att.content, mimeType: att.mediaType || "image/png" });
|
|
22991
|
+
}
|
|
22992
|
+
if (getDisposed()) return;
|
|
22993
|
+
const hasImage = parts.some((part) => part.type === "image");
|
|
22994
|
+
if (!hasImage && !modelContent) return;
|
|
22995
|
+
enqueue(hasImage ? parts : modelContent, enqueueOpts);
|
|
22996
|
+
})();
|
|
22997
|
+
return true;
|
|
22998
|
+
}
|
|
22999
|
+
enqueue(modelContent, enqueueOpts);
|
|
22906
23000
|
return true;
|
|
22907
23001
|
});
|
|
22908
23002
|
}
|
|
@@ -24757,33 +24851,33 @@ function createEngineApiB(bag) {
|
|
|
24757
24851
|
pushNotice("webhook config updated", "info");
|
|
24758
24852
|
return result;
|
|
24759
24853
|
},
|
|
24760
|
-
saveSchedule: (entry) => {
|
|
24761
|
-
const result = runtime.saveSchedule(entry);
|
|
24854
|
+
saveSchedule: async (entry) => {
|
|
24855
|
+
const result = await runtime.saveSchedule(entry);
|
|
24762
24856
|
pushNotice(`schedule saved: ${result.name}`, "info");
|
|
24763
24857
|
return result;
|
|
24764
24858
|
},
|
|
24765
|
-
deleteSchedule: (name) => {
|
|
24766
|
-
const result = runtime.deleteSchedule(name);
|
|
24859
|
+
deleteSchedule: async (name) => {
|
|
24860
|
+
const result = await runtime.deleteSchedule(name);
|
|
24767
24861
|
pushNotice(`schedule deleted: ${name}`, "info");
|
|
24768
24862
|
return result;
|
|
24769
24863
|
},
|
|
24770
|
-
setScheduleEnabled: (name, enabled) => {
|
|
24771
|
-
const result = runtime.setScheduleEnabled(name, enabled);
|
|
24864
|
+
setScheduleEnabled: async (name, enabled) => {
|
|
24865
|
+
const result = await runtime.setScheduleEnabled(name, enabled);
|
|
24772
24866
|
pushNotice(`schedule ${enabled ? "enabled" : "disabled"}: ${name}`, "info");
|
|
24773
24867
|
return result;
|
|
24774
24868
|
},
|
|
24775
|
-
saveWebhook: (entry) => {
|
|
24776
|
-
const result = runtime.saveWebhook(entry);
|
|
24869
|
+
saveWebhook: async (entry) => {
|
|
24870
|
+
const result = await runtime.saveWebhook(entry);
|
|
24777
24871
|
pushNotice(`webhook saved: ${result.name}`, "info");
|
|
24778
24872
|
return result;
|
|
24779
24873
|
},
|
|
24780
|
-
deleteWebhook: (name) => {
|
|
24781
|
-
const result = runtime.deleteWebhook(name);
|
|
24874
|
+
deleteWebhook: async (name) => {
|
|
24875
|
+
const result = await runtime.deleteWebhook(name);
|
|
24782
24876
|
pushNotice(`webhook deleted: ${name}`, "info");
|
|
24783
24877
|
return result;
|
|
24784
24878
|
},
|
|
24785
|
-
setWebhookEnabled: (name, enabled) => {
|
|
24786
|
-
const result = runtime.setWebhookEnabled(name, enabled);
|
|
24879
|
+
setWebhookEnabled: async (name, enabled) => {
|
|
24880
|
+
const result = await runtime.setWebhookEnabled(name, enabled);
|
|
24787
24881
|
pushNotice(`webhook ${enabled ? "enabled" : "disabled"}: ${name}`, "info");
|
|
24788
24882
|
return result;
|
|
24789
24883
|
},
|
|
@@ -24961,11 +25055,24 @@ function createEngineApiB(bag) {
|
|
|
24961
25055
|
// src/runtime/shared/update-checker.mjs
|
|
24962
25056
|
import { dirname as dirname7, join as join8 } from "node:path";
|
|
24963
25057
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
25058
|
+
|
|
25059
|
+
// src/runtime/shared/spawn-flags.mjs
|
|
25060
|
+
var isWin = process.platform === "win32";
|
|
25061
|
+
var detachedSpawnOpts = Object.freeze({
|
|
25062
|
+
windowsHide: true,
|
|
25063
|
+
...isWin ? {} : { detached: true }
|
|
25064
|
+
});
|
|
25065
|
+
var hiddenSpawnOpts = Object.freeze({
|
|
25066
|
+
windowsHide: true
|
|
25067
|
+
});
|
|
25068
|
+
|
|
25069
|
+
// src/runtime/shared/update-checker.mjs
|
|
24964
25070
|
var PACKAGE_NAME = "mixdog";
|
|
24965
25071
|
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
24966
25072
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
24967
25073
|
var _MODULE_DIR = dirname7(fileURLToPath2(import.meta.url));
|
|
24968
25074
|
var _PACKAGE_JSON_PATH = join8(_MODULE_DIR, "..", "..", "..", "package.json");
|
|
25075
|
+
var _PACKAGE_ROOT = dirname7(_PACKAGE_JSON_PATH);
|
|
24969
25076
|
function parseSemver(value) {
|
|
24970
25077
|
const text = String(value || "").trim().replace(/^v/i, "");
|
|
24971
25078
|
const [core, ...preParts] = text.split("-");
|
|
@@ -25112,7 +25219,7 @@ async function buildDoctorReport(runtime = {}, getState = () => ({})) {
|
|
|
25112
25219
|
return;
|
|
25113
25220
|
}
|
|
25114
25221
|
const worker = settings.status || runtime.getChannelWorkerStatus?.() || {};
|
|
25115
|
-
const setup = runtime.getChannelSetup?.() || {};
|
|
25222
|
+
const setup = await runtime.getChannelSetup?.() || {};
|
|
25116
25223
|
const tokens = [];
|
|
25117
25224
|
if (setup.discord?.authenticated) tokens.push("discord");
|
|
25118
25225
|
if (setup.telegram?.authenticated) tokens.push("telegram");
|
|
@@ -26279,7 +26386,8 @@ var TERMINAL_MODE_RESET = "\x1B[?1006l\x1B[?1005l\x1B[?1015l\x1B[?1003l\x1B[?100
|
|
|
26279
26386
|
var TERMINAL_OSC_RESET_BG = "\x1B]111\x07";
|
|
26280
26387
|
var TERMINAL_MODE_RESET_HIDDEN_CURSOR = TERMINAL_MODE_RESET.replace("\x1B[?25h", "\x1B[?25l");
|
|
26281
26388
|
var XTSHIFTESCAPE_ON = process.env.WT_SESSION ? "" : "\x1B[>1s";
|
|
26282
|
-
var MOUSE_TRACKING_ON2 = `\x1B[?1000h\x1B[?1002h\x1B[?1006h${XTSHIFTESCAPE_ON}`;
|
|
26389
|
+
var MOUSE_TRACKING_ON2 = `\x1B[?1000h\x1B[?1002h\x1B[?1006h\x1B[?1007l${XTSHIFTESCAPE_ON}`;
|
|
26390
|
+
var ALT_SCROLL_RESTORE = "\x1B[?1007h";
|
|
26283
26391
|
var BOOT_PROFILE_ENABLED2 = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_BOOT_PROFILE || ""));
|
|
26284
26392
|
var BOOT_PROFILE_START2 = globalThis.__mixdogBootProfileStart || (globalThis.__mixdogBootProfileStart = performance3.now());
|
|
26285
26393
|
var EXIT_WAIT_TIMEOUT_MS = positiveIntEnv2("MIXDOG_TUI_EXIT_WAIT_MS", 2500);
|
|
@@ -26655,7 +26763,7 @@ async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {
|
|
|
26655
26763
|
process.stdout.write(
|
|
26656
26764
|
// Pop kitty + disable modifyOtherKeys BEFORE leaving the alt screen.
|
|
26657
26765
|
// Both are no-ops if nothing was enabled, so this is always safe.
|
|
26658
|
-
`${TERMINAL_MODE_RESET}\x1B[0 q${POP_KITTY}${DISABLE_MODIFY_OTHER_KEYS}\x1B[?1049l${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`
|
|
26766
|
+
`${TERMINAL_MODE_RESET}${ALT_SCROLL_RESTORE}\x1B[0 q${POP_KITTY}${DISABLE_MODIFY_OTHER_KEYS}\x1B[?1049l${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`
|
|
26659
26767
|
);
|
|
26660
26768
|
} catch {
|
|
26661
26769
|
}
|
|
@@ -23,6 +23,20 @@ import {
|
|
|
23
23
|
notificationQueueKey,
|
|
24
24
|
resolveTuiRuntimeNotificationDelivery,
|
|
25
25
|
} from './notification-plan.mjs';
|
|
26
|
+
import { readImageAttachmentFromPath } from '../paste-attachments.mjs';
|
|
27
|
+
|
|
28
|
+
// Channel inbound images arrive as a JSON-array-of-paths meta value (stringified
|
|
29
|
+
// across the notify IPC boundary). Parse defensively; a malformed value simply
|
|
30
|
+
// yields no images and the notification degrades to its text body.
|
|
31
|
+
function parseInboundImagePaths(raw) {
|
|
32
|
+
if (typeof raw !== 'string' || !raw) return [];
|
|
33
|
+
try {
|
|
34
|
+
const arr = JSON.parse(raw);
|
|
35
|
+
return Array.isArray(arr) ? arr.filter((p) => typeof p === 'string' && p.length > 0) : [];
|
|
36
|
+
} catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
26
40
|
|
|
27
41
|
export function createAgentJobFeed({
|
|
28
42
|
runtime,
|
|
@@ -117,13 +131,38 @@ export function createAgentJobFeed({
|
|
|
117
131
|
set(agentStatusState({ force: true }));
|
|
118
132
|
}
|
|
119
133
|
const modelContent = String(delivery.modelContent ?? delivery.displayText ?? text).trim();
|
|
120
|
-
|
|
121
|
-
|
|
134
|
+
const imagePaths = parseInboundImagePaths(event?.meta?.image_paths);
|
|
135
|
+
if (!modelContent && imagePaths.length === 0) return true;
|
|
136
|
+
const enqueueOpts = {
|
|
122
137
|
mode: 'task-notification',
|
|
123
138
|
priority: 'next',
|
|
124
139
|
key: notificationKey || undefined,
|
|
125
140
|
displayText: delivery.displayText || text,
|
|
126
|
-
}
|
|
141
|
+
};
|
|
142
|
+
if (imagePaths.length > 0) {
|
|
143
|
+
// Read each downloaded image into a real image content block so the
|
|
144
|
+
// channel turn is vision-visible. Async, but the notification is
|
|
145
|
+
// already "handled" (return true) — the enqueue lands on resolve.
|
|
146
|
+
// Any unreadable path is skipped; if none load, fall back to text.
|
|
147
|
+
void (async () => {
|
|
148
|
+
if (getDisposed()) return;
|
|
149
|
+
const parts = [];
|
|
150
|
+
if (modelContent) parts.push({ type: 'text', text: modelContent });
|
|
151
|
+
for (const p of imagePaths) {
|
|
152
|
+
let att = null;
|
|
153
|
+
try { att = await readImageAttachmentFromPath(p); } catch { att = null; }
|
|
154
|
+
if (!att) continue;
|
|
155
|
+
if (att.metadataText) parts.push({ type: 'text', text: att.metadataText });
|
|
156
|
+
parts.push({ type: 'image', data: att.content, mimeType: att.mediaType || 'image/png' });
|
|
157
|
+
}
|
|
158
|
+
if (getDisposed()) return;
|
|
159
|
+
const hasImage = parts.some((part) => part.type === 'image');
|
|
160
|
+
if (!hasImage && !modelContent) return;
|
|
161
|
+
enqueue(hasImage ? parts : modelContent, enqueueOpts);
|
|
162
|
+
})();
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
enqueue(modelContent, enqueueOpts);
|
|
127
166
|
return true;
|
|
128
167
|
});
|
|
129
168
|
}
|
|
@@ -279,33 +279,33 @@ export function createEngineApiB(bag) {
|
|
|
279
279
|
pushNotice('webhook config updated', 'info');
|
|
280
280
|
return result;
|
|
281
281
|
},
|
|
282
|
-
saveSchedule: (entry) => {
|
|
283
|
-
const result = runtime.saveSchedule(entry);
|
|
282
|
+
saveSchedule: async (entry) => {
|
|
283
|
+
const result = await runtime.saveSchedule(entry);
|
|
284
284
|
pushNotice(`schedule saved: ${result.name}`, 'info');
|
|
285
285
|
return result;
|
|
286
286
|
},
|
|
287
|
-
deleteSchedule: (name) => {
|
|
288
|
-
const result = runtime.deleteSchedule(name);
|
|
287
|
+
deleteSchedule: async (name) => {
|
|
288
|
+
const result = await runtime.deleteSchedule(name);
|
|
289
289
|
pushNotice(`schedule deleted: ${name}`, 'info');
|
|
290
290
|
return result;
|
|
291
291
|
},
|
|
292
|
-
setScheduleEnabled: (name, enabled) => {
|
|
293
|
-
const result = runtime.setScheduleEnabled(name, enabled);
|
|
292
|
+
setScheduleEnabled: async (name, enabled) => {
|
|
293
|
+
const result = await runtime.setScheduleEnabled(name, enabled);
|
|
294
294
|
pushNotice(`schedule ${enabled ? 'enabled' : 'disabled'}: ${name}`, 'info');
|
|
295
295
|
return result;
|
|
296
296
|
},
|
|
297
|
-
saveWebhook: (entry) => {
|
|
298
|
-
const result = runtime.saveWebhook(entry);
|
|
297
|
+
saveWebhook: async (entry) => {
|
|
298
|
+
const result = await runtime.saveWebhook(entry);
|
|
299
299
|
pushNotice(`webhook saved: ${result.name}`, 'info');
|
|
300
300
|
return result;
|
|
301
301
|
},
|
|
302
|
-
deleteWebhook: (name) => {
|
|
303
|
-
const result = runtime.deleteWebhook(name);
|
|
302
|
+
deleteWebhook: async (name) => {
|
|
303
|
+
const result = await runtime.deleteWebhook(name);
|
|
304
304
|
pushNotice(`webhook deleted: ${name}`, 'info');
|
|
305
305
|
return result;
|
|
306
306
|
},
|
|
307
|
-
setWebhookEnabled: (name, enabled) => {
|
|
308
|
-
const result = runtime.setWebhookEnabled(name, enabled);
|
|
307
|
+
setWebhookEnabled: async (name, enabled) => {
|
|
308
|
+
const result = await runtime.setWebhookEnabled(name, enabled);
|
|
309
309
|
pushNotice(`webhook ${enabled ? 'enabled' : 'disabled'}: ${name}`, 'info');
|
|
310
310
|
return result;
|
|
311
311
|
},
|
package/src/tui/index.jsx
CHANGED
|
@@ -33,7 +33,17 @@ const TERMINAL_MODE_RESET_HIDDEN_CURSOR = TERMINAL_MODE_RESET.replace('\x1b[?25h
|
|
|
33
33
|
// highlight, native copy); ctrl+click/right-click remain the app-side
|
|
34
34
|
// extend triggers there. Restored via `\x1b[>0s` in TERMINAL_MODE_RESET.
|
|
35
35
|
const XTSHIFTESCAPE_ON = process.env.WT_SESSION ? '' : '\x1b[>1s';
|
|
36
|
-
|
|
36
|
+
// Trailing `\x1b[?1007l` keeps alternate-scroll OFF for the whole session:
|
|
37
|
+
// while mouse tracking is on it is irrelevant (wheel arrives as SGR events),
|
|
38
|
+
// but if tracking ever drops (failed re-enable after the ctrl+wheel zoom
|
|
39
|
+
// passthrough, terminal hiccup), an enabled 1007 makes the terminal convert
|
|
40
|
+
// wheel input into Up/Down arrows — which lands in PROMPT HISTORY instead of
|
|
41
|
+
// transcript scroll. With 1007 forced off the wheel degrades to a no-op, never
|
|
42
|
+
// to history navigation. Restored to on (`\x1b[?1007h`) at teardown so
|
|
43
|
+
// alt-screen apps that rely on alternate scroll (less/vim under Windows
|
|
44
|
+
// Terminal, whose default is on) keep working after mixdog exits.
|
|
45
|
+
const MOUSE_TRACKING_ON = `\x1b[?1000h\x1b[?1002h\x1b[?1006h\x1b[?1007l${XTSHIFTESCAPE_ON}`;
|
|
46
|
+
const ALT_SCROLL_RESTORE = '\x1b[?1007h';
|
|
37
47
|
// Keyboard-protocol teardown. App.jsx enables kitty + modifyOtherKeys
|
|
38
48
|
// synchronously at raw-mode-on (no query); here we just pop/disable them on
|
|
39
49
|
// exit. POP_KITTY / DISABLE_MODIFY_OTHER_KEYS come from keyboard-protocol.mjs.
|
|
@@ -434,7 +444,7 @@ export async function runTui({ provider, model, toolMode, remote, forceOnboardin
|
|
|
434
444
|
process.stdout.write(
|
|
435
445
|
// Pop kitty + disable modifyOtherKeys BEFORE leaving the alt screen.
|
|
436
446
|
// Both are no-ops if nothing was enabled, so this is always safe.
|
|
437
|
-
`${TERMINAL_MODE_RESET}\x1b[0 q${POP_KITTY}${DISABLE_MODIFY_OTHER_KEYS}\x1b[?1049l${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`,
|
|
447
|
+
`${TERMINAL_MODE_RESET}${ALT_SCROLL_RESTORE}\x1b[0 q${POP_KITTY}${DISABLE_MODIFY_OTHER_KEYS}\x1b[?1049l${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`,
|
|
438
448
|
);
|
|
439
449
|
} catch { /* ignore */ }
|
|
440
450
|
};
|