mixdog 0.9.26 → 0.9.28
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 +7 -2
- package/scripts/arg-guard-test.mjs +68 -0
- package/scripts/compacted-placeholder-scrub-test.mjs +77 -0
- package/src/app.mjs +14 -0
- package/src/cli.mjs +40 -4
- package/src/rules/shared/01-tool.md +3 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +5 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +14 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
- package/src/runtime/memory/tool-defs.mjs +3 -3
- package/src/runtime/shared/staged-install-worker.mjs +14 -0
- package/src/runtime/shared/staged-update.mjs +530 -0
- package/src/runtime/shared/update-checker.mjs +1 -1
- package/src/session-runtime/lifecycle-api.mjs +9 -11
- package/src/session-runtime/runtime-core.mjs +61 -40
- package/src/standalone/agent-tool/tool-def.mjs +2 -2
- package/src/tui/App.jsx +2 -1
- package/src/tui/app/transcript-window.mjs +26 -6
- package/src/tui/components/Spinner.jsx +5 -2
- package/src/tui/components/StatusLine.jsx +9 -9
- package/src/tui/components/ToolExecution.jsx +34 -59
- package/src/tui/display-width.mjs +8 -4
- package/src/tui/dist/index.mjs +545 -425
- package/src/tui/engine/notification-plan.mjs +5 -1
- package/src/tui/hooks/useSharedTick.mjs +103 -0
- package/src/tui/index.jsx +2 -1
- package/src/tui/markdown/format-token.mjs +46 -8
- package/src/tui/markdown/render-ansi.mjs +24 -1
- package/src/tui/markdown/stream-fence.mjs +60 -0
- package/src/tui/markdown/streaming-markdown.mjs +22 -1
- package/src/workflows/default/WORKFLOW.md +12 -8
- package/vendor/ink/build/display-width.js +5 -4
package/src/tui/dist/index.mjs
CHANGED
|
@@ -156,14 +156,14 @@ var require_mixdog_debug = __commonJS({
|
|
|
156
156
|
// src/tui/index.jsx
|
|
157
157
|
import React21 from "react";
|
|
158
158
|
import { render } from "../../../vendor/ink/build/index.js";
|
|
159
|
-
import { closeSync as closeSync2, constants as fsConstants, createWriteStream, mkdirSync as
|
|
159
|
+
import { closeSync as closeSync2, constants as fsConstants, createWriteStream, mkdirSync as mkdirSync7, openSync as openSync2, readSync } from "node:fs";
|
|
160
160
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
161
161
|
import { dirname as dirname9, join as join10 } from "node:path";
|
|
162
162
|
import { performance as performance3 } from "node:perf_hooks";
|
|
163
163
|
import { format } from "node:util";
|
|
164
164
|
|
|
165
165
|
// src/tui/App.jsx
|
|
166
|
-
import React20, { useState as useState8, useCallback as useCallback6, useEffect as useEffect10, useLayoutEffect as useLayoutEffect4, useMemo as useMemo2, useRef as
|
|
166
|
+
import React20, { useState as useState8, useCallback as useCallback6, useEffect as useEffect10, useLayoutEffect as useLayoutEffect4, useMemo as useMemo2, useRef as useRef10 } from "react";
|
|
167
167
|
import { Box as Box18, Text as Text20, useApp, useInput as useInput5, useStdin as useStdin3, useStdout as useStdout2 } from "../../../vendor/ink/build/index.js";
|
|
168
168
|
|
|
169
169
|
// src/tui/themes/base.mjs
|
|
@@ -3099,9 +3099,136 @@ function formatAggregateDetail(summaries) {
|
|
|
3099
3099
|
return order.map((item) => item.type === "metric" ? metrics.get(item.key)?.render(metrics.get(item.key)) : item.text).filter(Boolean).join(", ");
|
|
3100
3100
|
}
|
|
3101
3101
|
|
|
3102
|
+
// src/runtime/shared/update-checker.mjs
|
|
3103
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3104
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
3105
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3106
|
+
|
|
3107
|
+
// src/runtime/shared/plugin-paths.mjs
|
|
3108
|
+
import { homedir } from "os";
|
|
3109
|
+
import { dirname, join } from "path";
|
|
3110
|
+
import { fileURLToPath } from "url";
|
|
3111
|
+
var DEFAULT_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
3112
|
+
function mixdogHome() {
|
|
3113
|
+
return process.env.MIXDOG_HOME || join(homedir(), ".mixdog");
|
|
3114
|
+
}
|
|
3115
|
+
function resolvePluginData() {
|
|
3116
|
+
return process.env.MIXDOG_DATA_DIR || join(mixdogHome(), "data");
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3119
|
+
// src/runtime/shared/spawn-flags.mjs
|
|
3120
|
+
var isWin = process.platform === "win32";
|
|
3121
|
+
var detachedSpawnOpts = Object.freeze({
|
|
3122
|
+
windowsHide: true,
|
|
3123
|
+
...isWin ? {} : { detached: true }
|
|
3124
|
+
});
|
|
3125
|
+
var hiddenSpawnOpts = Object.freeze({
|
|
3126
|
+
windowsHide: true
|
|
3127
|
+
});
|
|
3128
|
+
|
|
3129
|
+
// src/runtime/shared/update-checker.mjs
|
|
3130
|
+
var PACKAGE_NAME = "mixdog";
|
|
3131
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
3132
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
3133
|
+
var _MODULE_DIR = dirname2(fileURLToPath2(import.meta.url));
|
|
3134
|
+
var _PACKAGE_JSON_PATH = join2(_MODULE_DIR, "..", "..", "..", "package.json");
|
|
3135
|
+
var _PACKAGE_ROOT = dirname2(_PACKAGE_JSON_PATH);
|
|
3136
|
+
var _localVersionCache = null;
|
|
3137
|
+
function localPackageVersion() {
|
|
3138
|
+
if (_localVersionCache) return _localVersionCache;
|
|
3139
|
+
try {
|
|
3140
|
+
const raw = JSON.parse(readFileSync(_PACKAGE_JSON_PATH, "utf8"));
|
|
3141
|
+
_localVersionCache = String(raw?.version || "0.0.0");
|
|
3142
|
+
} catch {
|
|
3143
|
+
_localVersionCache = "0.0.0";
|
|
3144
|
+
}
|
|
3145
|
+
return _localVersionCache;
|
|
3146
|
+
}
|
|
3147
|
+
function parseSemver(value) {
|
|
3148
|
+
const text = String(value || "").trim().replace(/^v/i, "");
|
|
3149
|
+
const [core, ...preParts] = text.split("-");
|
|
3150
|
+
const parts = core.split(".").map((n) => {
|
|
3151
|
+
const num2 = Number.parseInt(n, 10);
|
|
3152
|
+
return Number.isFinite(num2) ? num2 : 0;
|
|
3153
|
+
});
|
|
3154
|
+
while (parts.length < 3) parts.push(0);
|
|
3155
|
+
return { parts, prerelease: preParts.join("-") };
|
|
3156
|
+
}
|
|
3157
|
+
function compareSemver(a, b) {
|
|
3158
|
+
const pa = parseSemver(a);
|
|
3159
|
+
const pb = parseSemver(b);
|
|
3160
|
+
for (let i = 0; i < 3; i++) {
|
|
3161
|
+
const diff = (pa.parts[i] || 0) - (pb.parts[i] || 0);
|
|
3162
|
+
if (diff !== 0) return diff;
|
|
3163
|
+
}
|
|
3164
|
+
if (pa.prerelease && !pb.prerelease) return -1;
|
|
3165
|
+
if (!pa.prerelease && pb.prerelease) return 1;
|
|
3166
|
+
if (pa.prerelease !== pb.prerelease) return pa.prerelease < pb.prerelease ? -1 : 1;
|
|
3167
|
+
return 0;
|
|
3168
|
+
}
|
|
3169
|
+
|
|
3102
3170
|
// src/tui/components/Spinner.jsx
|
|
3103
|
-
import React, { useRef } from "react";
|
|
3104
|
-
import { Box, Text
|
|
3171
|
+
import React, { useRef as useRef2 } from "react";
|
|
3172
|
+
import { Box, Text } from "../../../vendor/ink/build/index.js";
|
|
3173
|
+
|
|
3174
|
+
// src/tui/hooks/useSharedTick.mjs
|
|
3175
|
+
import { useEffect, useRef, useState } from "react";
|
|
3176
|
+
var TICK_SLOP_MS = 16;
|
|
3177
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
3178
|
+
var timer = null;
|
|
3179
|
+
function nextDelayMs(now) {
|
|
3180
|
+
let soonest = Infinity;
|
|
3181
|
+
for (const sub of subscribers) {
|
|
3182
|
+
const due = sub.lastFire + sub.interval - now;
|
|
3183
|
+
if (due < soonest) soonest = due;
|
|
3184
|
+
}
|
|
3185
|
+
return Number.isFinite(soonest) ? Math.max(1, soonest) : null;
|
|
3186
|
+
}
|
|
3187
|
+
function reconcileTimer() {
|
|
3188
|
+
if (timer) {
|
|
3189
|
+
clearTimeout(timer);
|
|
3190
|
+
timer = null;
|
|
3191
|
+
}
|
|
3192
|
+
const delay = nextDelayMs(Date.now());
|
|
3193
|
+
if (delay == null) return;
|
|
3194
|
+
timer = setTimeout(onTick, delay);
|
|
3195
|
+
timer.unref?.();
|
|
3196
|
+
}
|
|
3197
|
+
function onTick() {
|
|
3198
|
+
timer = null;
|
|
3199
|
+
const now = Date.now();
|
|
3200
|
+
for (const sub of Array.from(subscribers)) {
|
|
3201
|
+
if (!subscribers.has(sub)) continue;
|
|
3202
|
+
if (now - sub.lastFire >= sub.interval - TICK_SLOP_MS) {
|
|
3203
|
+
sub.lastFire = now;
|
|
3204
|
+
sub.notify(now);
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
reconcileTimer();
|
|
3208
|
+
}
|
|
3209
|
+
function useSharedTick(intervalMs, isActive = true, onTick2 = null) {
|
|
3210
|
+
const [, setTick] = useState(0);
|
|
3211
|
+
const cbRef = useRef(onTick2);
|
|
3212
|
+
cbRef.current = onTick2;
|
|
3213
|
+
useEffect(() => {
|
|
3214
|
+
if (!isActive) return void 0;
|
|
3215
|
+
const interval = Math.max(1, Number(intervalMs) || 0);
|
|
3216
|
+
const sub = {
|
|
3217
|
+
interval,
|
|
3218
|
+
lastFire: Date.now(),
|
|
3219
|
+
notify: (now) => {
|
|
3220
|
+
if (cbRef.current) cbRef.current(now);
|
|
3221
|
+
else setTick((t) => (t + 1) % 1e6);
|
|
3222
|
+
}
|
|
3223
|
+
};
|
|
3224
|
+
subscribers.add(sub);
|
|
3225
|
+
reconcileTimer();
|
|
3226
|
+
return () => {
|
|
3227
|
+
subscribers.delete(sub);
|
|
3228
|
+
reconcileTimer();
|
|
3229
|
+
};
|
|
3230
|
+
}, [intervalMs, isActive]);
|
|
3231
|
+
}
|
|
3105
3232
|
|
|
3106
3233
|
// src/tui/spinner-verbs.mjs
|
|
3107
3234
|
var SPINNER_VERBS = [
|
|
@@ -3438,19 +3565,19 @@ function tokenModeGlyph(mode) {
|
|
|
3438
3565
|
}
|
|
3439
3566
|
}
|
|
3440
3567
|
function Spinner({ verb = "Working", startedAt, outputTokens = 0, tokens = 0, thinking = false, thinkingActiveSince = 0, mode = "responding", columns = 80, marginTop = 1 }) {
|
|
3441
|
-
|
|
3568
|
+
useSharedTick(FRAME_MS);
|
|
3442
3569
|
const { TEXT_RGB, SHIMMER_RGB, SPINNER_GLYPH_RGB, THINKING_INACTIVE, THINKING_SHIMMER, STALL_RGB } = spinnerRgb();
|
|
3443
3570
|
const now = Date.now();
|
|
3444
3571
|
const elapsedMs = startedAt ? Math.max(0, now - startedAt) : 0;
|
|
3445
3572
|
const frame = Math.floor(elapsedMs / FRAME_MS);
|
|
3446
|
-
const lastGrowRef =
|
|
3447
|
-
const lastTokensRef =
|
|
3448
|
-
const displayedOutputRef =
|
|
3449
|
-
const displayVerbRef =
|
|
3450
|
-
const displayVerbModeRef =
|
|
3451
|
-
const nextVerbCheckRef =
|
|
3452
|
-
const stallSmoothRef =
|
|
3453
|
-
const lastStallTickRef =
|
|
3573
|
+
const lastGrowRef = useRef2(now);
|
|
3574
|
+
const lastTokensRef = useRef2(0);
|
|
3575
|
+
const displayedOutputRef = useRef2(0);
|
|
3576
|
+
const displayVerbRef = useRef2("");
|
|
3577
|
+
const displayVerbModeRef = useRef2("");
|
|
3578
|
+
const nextVerbCheckRef = useRef2(0);
|
|
3579
|
+
const stallSmoothRef = useRef2(0);
|
|
3580
|
+
const lastStallTickRef = useRef2(0);
|
|
3454
3581
|
const targetOutputTokens = Math.max(0, Number(outputTokens || tokens || 0));
|
|
3455
3582
|
if (targetOutputTokens > lastTokensRef.current) {
|
|
3456
3583
|
lastTokensRef.current = targetOutputTokens;
|
|
@@ -3559,7 +3686,7 @@ function Spinner({ verb = "Working", startedAt, outputTokens = 0, tokens = 0, th
|
|
|
3559
3686
|
}
|
|
3560
3687
|
|
|
3561
3688
|
// src/tui/components/StatusLine.jsx
|
|
3562
|
-
import React2, { useEffect, useRef as
|
|
3689
|
+
import React2, { useEffect as useEffect2, useRef as useRef3, useState as useState2 } from "react";
|
|
3563
3690
|
import { Box as Box2, Text as Text2 } from "../../../vendor/ink/build/index.js";
|
|
3564
3691
|
|
|
3565
3692
|
// src/tui/statusline-ansi-bridge.mjs
|
|
@@ -3693,11 +3820,11 @@ var statuslineModulePrewarmScheduled = false;
|
|
|
3693
3820
|
function scheduleStatuslineModulePrewarm() {
|
|
3694
3821
|
if (statuslineModulePrewarmScheduled) return;
|
|
3695
3822
|
statuslineModulePrewarmScheduled = true;
|
|
3696
|
-
const
|
|
3823
|
+
const timer2 = setTimeout(() => {
|
|
3697
3824
|
loadStatuslineModule().catch(() => {
|
|
3698
3825
|
});
|
|
3699
3826
|
}, STATUSLINE_MODULE_PREWARM_DELAY_MS);
|
|
3700
|
-
|
|
3827
|
+
timer2.unref?.();
|
|
3701
3828
|
}
|
|
3702
3829
|
var STATUSLINE_BOOT_FULL_DELAY_MS = 1e3;
|
|
3703
3830
|
var STATUSLINE_BOOT_FULL_DELAY_ACTIVE_MS = 2200;
|
|
@@ -4006,7 +4133,7 @@ function workflowModeLabel(workflow = {}, remoteEnabled = false) {
|
|
|
4006
4133
|
return remoteEnabled === true ? `Remote / ${base}` : base;
|
|
4007
4134
|
}
|
|
4008
4135
|
function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fast, cwd, stats, contextWindow, displayContextWindow = 0, compactBoundaryTokens = 0, autoCompactTokenLimit = 0, rawContextWindow, resizeEpoch, agentRevision = "", agentWorkers = [], agentJobs = [], activeTools = null, initialLine = "", workflow = null, remoteEnabled = false, themeEpoch = 0 }) {
|
|
4009
|
-
const [line, setLine] =
|
|
4136
|
+
const [line, setLine] = useState2(() => normalizeStatusLine(initialLine || localBootStatusLine({
|
|
4010
4137
|
provider,
|
|
4011
4138
|
model,
|
|
4012
4139
|
effort,
|
|
@@ -4021,19 +4148,19 @@ function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fas
|
|
|
4021
4148
|
agentJobs,
|
|
4022
4149
|
activeTools
|
|
4023
4150
|
})));
|
|
4024
|
-
const [refreshTick, setRefreshTick] =
|
|
4025
|
-
const statuslineArgsRef =
|
|
4026
|
-
const bootFullDoneRef =
|
|
4027
|
-
const mountAtRef =
|
|
4028
|
-
const lineRef =
|
|
4029
|
-
const bootFullNextAttemptAtRef =
|
|
4030
|
-
const bootFullRetryBackoffMsRef =
|
|
4031
|
-
const renderEffectIdRef =
|
|
4032
|
-
const lastImmediateArgsRef =
|
|
4033
|
-
const themeEpochRef =
|
|
4034
|
-
const lastRawFullLineRef =
|
|
4035
|
-
const lastRawFullLineCacheKeyRef =
|
|
4036
|
-
const lastRawFullLineAtRef =
|
|
4151
|
+
const [refreshTick, setRefreshTick] = useState2(0);
|
|
4152
|
+
const statuslineArgsRef = useRef3(null);
|
|
4153
|
+
const bootFullDoneRef = useRef3(false);
|
|
4154
|
+
const mountAtRef = useRef3(Date.now());
|
|
4155
|
+
const lineRef = useRef3("");
|
|
4156
|
+
const bootFullNextAttemptAtRef = useRef3(0);
|
|
4157
|
+
const bootFullRetryBackoffMsRef = useRef3(STATUSLINE_BOOT_FULL_RETRY_MS);
|
|
4158
|
+
const renderEffectIdRef = useRef3(0);
|
|
4159
|
+
const lastImmediateArgsRef = useRef3(null);
|
|
4160
|
+
const themeEpochRef = useRef3(themeEpoch);
|
|
4161
|
+
const lastRawFullLineRef = useRef3("");
|
|
4162
|
+
const lastRawFullLineCacheKeyRef = useRef3("");
|
|
4163
|
+
const lastRawFullLineAtRef = useRef3(0);
|
|
4037
4164
|
const statuslineArgs = {
|
|
4038
4165
|
sessionId,
|
|
4039
4166
|
clientHostPid,
|
|
@@ -4074,17 +4201,13 @@ function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fas
|
|
|
4074
4201
|
String(statsForSignature.currentContextSource || "")
|
|
4075
4202
|
].join("|");
|
|
4076
4203
|
const refreshMs = hasActiveStatuslineWork(line, agentWorkers, agentJobs, activeTools) ? STATUSLINE_ACTIVE_REFRESH_MS : STATUSLINE_REFRESH_MS;
|
|
4077
|
-
|
|
4204
|
+
useEffect2(() => {
|
|
4078
4205
|
scheduleStatuslineModulePrewarm();
|
|
4079
4206
|
}, []);
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
timer.unref?.();
|
|
4085
|
-
return () => clearInterval(timer);
|
|
4086
|
-
}, [refreshMs]);
|
|
4087
|
-
useEffect(() => {
|
|
4207
|
+
useSharedTick(refreshMs, true, () => {
|
|
4208
|
+
setRefreshTick((tick) => (tick + 1) % 1e6);
|
|
4209
|
+
});
|
|
4210
|
+
useEffect2(() => {
|
|
4088
4211
|
let alive = true;
|
|
4089
4212
|
let bootRetryTimer = null;
|
|
4090
4213
|
const effectId = renderEffectIdRef.current + 1;
|
|
@@ -4146,7 +4269,7 @@ ${grafted}` : cachedL1;
|
|
|
4146
4269
|
autoCompactTokenLimit: args.autoCompactTokenLimit,
|
|
4147
4270
|
stats: args.stats
|
|
4148
4271
|
};
|
|
4149
|
-
const
|
|
4272
|
+
const timer2 = setTimeout(() => {
|
|
4150
4273
|
if (bootFullDoneRef.current !== true) {
|
|
4151
4274
|
if (!bootFullRenderEligible(mountAtRef.current, lineRef.current, args.agentWorkers, args.agentJobs, args.activeTools)) {
|
|
4152
4275
|
const active = hasActiveStatuslineWork(lineRef.current, args.agentWorkers, args.agentJobs, args.activeTools);
|
|
@@ -4192,10 +4315,10 @@ ${grafted}` : cachedL1;
|
|
|
4192
4315
|
resetStatuslineModuleLoad();
|
|
4193
4316
|
});
|
|
4194
4317
|
}, STATUSLINE_RENDER_DEBOUNCE_MS);
|
|
4195
|
-
|
|
4318
|
+
timer2.unref?.();
|
|
4196
4319
|
return () => {
|
|
4197
4320
|
alive = false;
|
|
4198
|
-
clearTimeout(
|
|
4321
|
+
clearTimeout(timer2);
|
|
4199
4322
|
clearTimeout(bootRetryTimer);
|
|
4200
4323
|
};
|
|
4201
4324
|
}, [sessionId, clientHostPid, provider, model, effort, fast, cwd, statsSignature, contextWindow, displayContextWindow, compactBoundaryTokens, autoCompactTokenLimit, rawContextWindow, resizeEpoch, agentRevision, agentWorkersSignature, agentJobsSignature, activeToolsSignature, refreshTick, themeEpoch]);
|
|
@@ -4203,25 +4326,25 @@ ${grafted}` : cachedL1;
|
|
|
4203
4326
|
const workflowLabel = workflowModeLabel(workflow, remoteEnabled);
|
|
4204
4327
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: "100%", height: 3, overflow: "hidden", justifyContent: "flex-start", paddingLeft: 2, backgroundColor: surfaceBackground(), children: [
|
|
4205
4328
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", width: "100%", overflow: "hidden", children: [
|
|
4206
|
-
/* @__PURE__ */ jsx2(Box2, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", children: lines[0] || " " }) }),
|
|
4329
|
+
/* @__PURE__ */ jsx2(Box2, { flexGrow: 1, flexShrink: 1, flexBasis: 0, overflow: "hidden", children: /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", children: lines[0] || " " }) }),
|
|
4207
4330
|
/* @__PURE__ */ jsx2(Box2, { flexShrink: 0, marginLeft: 1, marginRight: 1, children: /* @__PURE__ */ jsx2(Text2, { color: theme.statusText, wrap: "truncate", children: workflowLabel }) })
|
|
4208
4331
|
] }),
|
|
4209
|
-
/* @__PURE__ */ jsx2(Box2, { flexDirection: "row", width: "100%", overflow: "hidden", children: /* @__PURE__ */ jsx2(Box2, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", children: lines[1] || " " }) }) })
|
|
4332
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "row", width: "100%", overflow: "hidden", children: /* @__PURE__ */ jsx2(Box2, { flexGrow: 1, flexShrink: 1, flexBasis: 0, overflow: "hidden", children: /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", children: lines[1] || " " }) }) })
|
|
4210
4333
|
] });
|
|
4211
4334
|
}
|
|
4212
4335
|
var StatusLine = React2.memo(StatusLineView);
|
|
4213
4336
|
|
|
4214
4337
|
// src/tui/components/PromptInput.jsx
|
|
4215
|
-
import React3, { useEffect as
|
|
4338
|
+
import React3, { useEffect as useEffect3, useLayoutEffect, useState as useState3, useRef as useRef4 } from "react";
|
|
4216
4339
|
import { Box as Box3, Text as Text3, useInput, usePaste, useStdin } from "../../../vendor/ink/build/index.js";
|
|
4217
4340
|
|
|
4218
4341
|
// src/tui/display-width.mjs
|
|
4219
4342
|
import stringWidth from "string-width";
|
|
4220
4343
|
var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
4221
4344
|
function isProblemCodePoint(cp) {
|
|
4222
|
-
return cp >= 9312 && cp <= 9471 || cp >=
|
|
4345
|
+
return cp >= 9312 && cp <= 9471 || cp >= 8596 && cp <= 8703;
|
|
4223
4346
|
}
|
|
4224
|
-
var PROBLEM_RE = /[\
|
|
4347
|
+
var PROBLEM_RE = /[\u2194-\u21ff\u2460-\u24ff]/;
|
|
4225
4348
|
function resolveAmbiguousWidePolicy(env = process.env, platform = process.platform) {
|
|
4226
4349
|
const override = env?.MIXDOG_TUI_AMBIGUOUS_WIDE;
|
|
4227
4350
|
if (override === "1") return true;
|
|
@@ -4577,29 +4700,29 @@ function PromptInput({
|
|
|
4577
4700
|
mouseSelectionRef,
|
|
4578
4701
|
suppressShiftNavRef
|
|
4579
4702
|
}) {
|
|
4580
|
-
const [draft, setDraft] =
|
|
4703
|
+
const [draft, setDraft] = useState3(() => {
|
|
4581
4704
|
const value2 = String(initialValue || "");
|
|
4582
4705
|
return { value: value2, cursor: value2.length, selectionAnchor: null };
|
|
4583
4706
|
});
|
|
4584
|
-
const [, bumpCursorAnchorEpoch] =
|
|
4585
|
-
const draftRef =
|
|
4586
|
-
const lastReportedValueRef =
|
|
4587
|
-
const pasteGenerationRef =
|
|
4707
|
+
const [, bumpCursorAnchorEpoch] = useState3(0);
|
|
4708
|
+
const draftRef = useRef4(draft);
|
|
4709
|
+
const lastReportedValueRef = useRef4(draft.value);
|
|
4710
|
+
const pasteGenerationRef = useRef4(0);
|
|
4588
4711
|
if (valueRef) valueRef.current = draftRef.current.value;
|
|
4589
4712
|
const { isRawModeSupported } = useStdin();
|
|
4590
|
-
const boxRef =
|
|
4591
|
-
const cursorEnabledRef =
|
|
4592
|
-
const contentWidthRef =
|
|
4593
|
-
const preferredColumnRef =
|
|
4594
|
-
const mouseExtendCoalesceRef =
|
|
4595
|
-
const undoRef =
|
|
4713
|
+
const boxRef = useRef4(null);
|
|
4714
|
+
const cursorEnabledRef = useRef4(false);
|
|
4715
|
+
const contentWidthRef = useRef4(80);
|
|
4716
|
+
const preferredColumnRef = useRef4(null);
|
|
4717
|
+
const mouseExtendCoalesceRef = useRef4({ pendingNext: null, timer: null, t: 0 });
|
|
4718
|
+
const undoRef = useRef4({ past: [], future: [], lastPushAt: 0, lastValue: null });
|
|
4596
4719
|
const { value, cursor } = draft;
|
|
4597
4720
|
draftRef.current = draft;
|
|
4598
4721
|
if (selectionRef) {
|
|
4599
4722
|
const range = selectionRange(draft);
|
|
4600
4723
|
selectionRef.current = range ? { range, text: mask ? "" : draft.value.slice(range.start, range.end) } : null;
|
|
4601
4724
|
}
|
|
4602
|
-
const flushThrottleRef =
|
|
4725
|
+
const flushThrottleRef = useRef4({ lastAt: 0, timer: null });
|
|
4603
4726
|
const flushImmediate = () => {
|
|
4604
4727
|
let node = boxRef.current;
|
|
4605
4728
|
for (let i = 0; node && i < 64; i++) {
|
|
@@ -4816,7 +4939,7 @@ function PromptInput({
|
|
|
4816
4939
|
}
|
|
4817
4940
|
};
|
|
4818
4941
|
}
|
|
4819
|
-
|
|
4942
|
+
useEffect3(() => () => {
|
|
4820
4943
|
const state = mouseExtendCoalesceRef.current;
|
|
4821
4944
|
if (state.timer) clearTimeout(state.timer);
|
|
4822
4945
|
state.timer = null;
|
|
@@ -4879,13 +5002,13 @@ function PromptInput({
|
|
|
4879
5002
|
apply(handled);
|
|
4880
5003
|
}
|
|
4881
5004
|
};
|
|
4882
|
-
|
|
5005
|
+
useEffect3(() => {
|
|
4883
5006
|
if (!draftOverride || typeof draftOverride.value !== "string") return;
|
|
4884
5007
|
pasteGenerationRef.current += 1;
|
|
4885
5008
|
commitDraft({ value: draftOverride.value, cursor: draftOverride.value.length, selectionAnchor: null }, { skipHistory: true });
|
|
4886
5009
|
resetUndo();
|
|
4887
5010
|
}, [draftOverride?.id]);
|
|
4888
|
-
|
|
5011
|
+
useEffect3(() => () => {
|
|
4889
5012
|
pasteGenerationRef.current += 1;
|
|
4890
5013
|
if (selectionRef) selectionRef.current = null;
|
|
4891
5014
|
}, [selectionRef]);
|
|
@@ -5270,7 +5393,7 @@ function QueuedCommands({ queued, columns, compact = false }) {
|
|
|
5270
5393
|
}
|
|
5271
5394
|
|
|
5272
5395
|
// src/tui/components/Picker.jsx
|
|
5273
|
-
import React6, { useState as
|
|
5396
|
+
import React6, { useState as useState4, useCallback, useEffect as useEffect4, useRef as useRef5 } from "react";
|
|
5274
5397
|
import { Box as Box6, Text as Text6, useInput as useInput2 } from "../../../vendor/ink/build/index.js";
|
|
5275
5398
|
import stringWidth2 from "string-width";
|
|
5276
5399
|
|
|
@@ -5388,20 +5511,20 @@ function Picker({
|
|
|
5388
5511
|
themeEpoch = 0
|
|
5389
5512
|
}) {
|
|
5390
5513
|
const visibleLimit = Math.max(1, Math.floor(Number(visibleCount) || MAX_VISIBLE));
|
|
5391
|
-
const [selectedIndex, setSelectedIndex] =
|
|
5514
|
+
const [selectedIndex, setSelectedIndex] = useState4(() => Math.max(0, Math.min(Number(initialIndex) || 0, Math.max(0, items.length - 1))));
|
|
5392
5515
|
const confirmButtons = Array.isArray(confirmBar?.buttons) ? confirmBar.buttons.filter(Boolean) : [];
|
|
5393
5516
|
const hasConfirm = confirmButtons.length > 0;
|
|
5394
|
-
const [confirmFocus, setConfirmFocus] =
|
|
5395
|
-
const lastTabAtRef =
|
|
5396
|
-
|
|
5517
|
+
const [confirmFocus, setConfirmFocus] = useState4(-1);
|
|
5518
|
+
const lastTabAtRef = useRef5(0);
|
|
5519
|
+
useEffect4(() => {
|
|
5397
5520
|
setConfirmFocus(-1);
|
|
5398
5521
|
}, [confirmButtons.length, confirmBar]);
|
|
5399
|
-
const [selectionMemo] =
|
|
5400
|
-
|
|
5522
|
+
const [selectionMemo] = useState4(() => ({ value: null, initialIndex }));
|
|
5523
|
+
useEffect4(() => {
|
|
5401
5524
|
const item = items[selectedIndex];
|
|
5402
5525
|
if (item && item.value != null) selectionMemo.value = item.value;
|
|
5403
5526
|
}, [items, selectedIndex, selectionMemo]);
|
|
5404
|
-
|
|
5527
|
+
useEffect4(() => {
|
|
5405
5528
|
setSelectedIndex((i) => {
|
|
5406
5529
|
if (selectionMemo.value != null) {
|
|
5407
5530
|
const found = items.findIndex((entry) => entry && entry.value === selectionMemo.value);
|
|
@@ -5412,7 +5535,7 @@ function Picker({
|
|
|
5412
5535
|
return Math.min(Math.max(0, i), Math.max(0, items.length - 1));
|
|
5413
5536
|
});
|
|
5414
5537
|
}, [items, selectionMemo, initialIndex]);
|
|
5415
|
-
|
|
5538
|
+
useEffect4(() => {
|
|
5416
5539
|
if (initialIndex == null) {
|
|
5417
5540
|
selectionMemo.initialIndex = null;
|
|
5418
5541
|
return;
|
|
@@ -5421,7 +5544,7 @@ function Picker({
|
|
|
5421
5544
|
selectionMemo.initialIndex = initialIndex;
|
|
5422
5545
|
setSelectedIndex(Math.max(0, Math.min(Number(initialIndex) || 0, Math.max(0, items.length - 1))));
|
|
5423
5546
|
}, [initialIndex, items.length, selectionMemo]);
|
|
5424
|
-
|
|
5547
|
+
useEffect4(() => {
|
|
5425
5548
|
if (typeof onHighlight !== "function") return;
|
|
5426
5549
|
const item = items[selectedIndex];
|
|
5427
5550
|
if (item) onHighlight(item.value, item, selectedIndex);
|
|
@@ -6048,7 +6171,7 @@ function ContextPanel({ rows, title = "Context Usage", columns = 80, fillHeight
|
|
|
6048
6171
|
}
|
|
6049
6172
|
|
|
6050
6173
|
// src/tui/components/UsagePanel.jsx
|
|
6051
|
-
import React9, { useEffect as
|
|
6174
|
+
import React9, { useEffect as useEffect5, useState as useState5 } from "react";
|
|
6052
6175
|
import { Box as Box9, Text as Text9, useInput as useInput3 } from "../../../vendor/ink/build/index.js";
|
|
6053
6176
|
import stringWidth5 from "string-width";
|
|
6054
6177
|
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
@@ -6265,11 +6388,11 @@ function UsagePanel({ dashboard, loading = false, columns = 80, fillHeight = fal
|
|
|
6265
6388
|
const hasMeasuredRows = Number(panelRows) > 0;
|
|
6266
6389
|
const maxProviderRows = hasMeasuredRows ? Math.max(1, Math.floor(panelRows) - 6) : rows.length;
|
|
6267
6390
|
const maxScrollOffset = Math.max(0, rows.length - maxProviderRows);
|
|
6268
|
-
const [scrollOffset, setScrollOffset] =
|
|
6391
|
+
const [scrollOffset, setScrollOffset] = useState5(0);
|
|
6269
6392
|
const visibleRows = hasMeasuredRows ? rows.slice(scrollOffset, scrollOffset + maxProviderRows) : rows;
|
|
6270
6393
|
const scrollable = rows.length > maxProviderRows;
|
|
6271
6394
|
const helpText = `${scrollable || isLoading || isChecking ? "\u2191/\u2193 Scroll \xB7 PgUp/PgDn Page \xB7 " : ""}Esc Back \xB7 /usage refresh`;
|
|
6272
|
-
|
|
6395
|
+
useEffect5(() => {
|
|
6273
6396
|
setScrollOffset((offset) => Math.min(Math.max(0, offset), maxScrollOffset));
|
|
6274
6397
|
}, [maxScrollOffset]);
|
|
6275
6398
|
useInput3((input, key) => {
|
|
@@ -6342,7 +6465,7 @@ function UsagePanel({ dashboard, loading = false, columns = 80, fillHeight = fal
|
|
|
6342
6465
|
}
|
|
6343
6466
|
|
|
6344
6467
|
// src/tui/components/TextEntryPanel.jsx
|
|
6345
|
-
import React10, { useEffect as
|
|
6468
|
+
import React10, { useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useRef as useRef6, useState as useState6 } from "react";
|
|
6346
6469
|
import { Box as Box10, Text as Text10, useInput as useInput4, usePaste as usePaste2, useStdin as useStdin2 } from "../../../vendor/ink/build/index.js";
|
|
6347
6470
|
import stringWidth6 from "string-width";
|
|
6348
6471
|
|
|
@@ -6555,13 +6678,13 @@ function TextEntryPanel({
|
|
|
6555
6678
|
onSubmit,
|
|
6556
6679
|
onCancel
|
|
6557
6680
|
}) {
|
|
6558
|
-
const [draft, setDraft] =
|
|
6559
|
-
const [, bumpCursorAnchorEpoch] =
|
|
6560
|
-
const draftRef =
|
|
6561
|
-
const boxRef =
|
|
6562
|
-
const cursorEnabledRef =
|
|
6563
|
-
const contentWidthRef =
|
|
6564
|
-
const preferredColumnRef =
|
|
6681
|
+
const [draft, setDraft] = useState6(() => ({ value: String(initialValue || ""), cursor: String(initialValue || "").length, selectionAnchor: null }));
|
|
6682
|
+
const [, bumpCursorAnchorEpoch] = useState6(0);
|
|
6683
|
+
const draftRef = useRef6(draft);
|
|
6684
|
+
const boxRef = useRef6(null);
|
|
6685
|
+
const cursorEnabledRef = useRef6(false);
|
|
6686
|
+
const contentWidthRef = useRef6(80);
|
|
6687
|
+
const preferredColumnRef = useRef6(null);
|
|
6565
6688
|
const { isRawModeSupported } = useStdin2();
|
|
6566
6689
|
draftRef.current = draft;
|
|
6567
6690
|
const flushImmediate = () => {
|
|
@@ -6597,13 +6720,13 @@ function TextEntryPanel({
|
|
|
6597
6720
|
commitDraft(moveCursor(current, moved.cursor, { extend }), { keepPreferredColumn: true });
|
|
6598
6721
|
return true;
|
|
6599
6722
|
};
|
|
6600
|
-
|
|
6723
|
+
useEffect6(() => {
|
|
6601
6724
|
const value = String(initialValue || "");
|
|
6602
6725
|
commitDraft({ value, cursor: value.length, selectionAnchor: null });
|
|
6603
6726
|
}, [title, initialValue]);
|
|
6604
6727
|
const labelCells = stringWidth6(String(promptLabel || ""));
|
|
6605
6728
|
const contentCells = Math.max(1, columns - 4 - labelCells);
|
|
6606
|
-
|
|
6729
|
+
useEffect6(() => {
|
|
6607
6730
|
if (!multiline) {
|
|
6608
6731
|
onContentRowsChange?.(1);
|
|
6609
6732
|
return;
|
|
@@ -6876,7 +6999,7 @@ function TextEntryPanel({
|
|
|
6876
6999
|
import { execFile } from "node:child_process";
|
|
6877
7000
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
6878
7001
|
import { randomBytes } from "node:crypto";
|
|
6879
|
-
import { existsSync, unlinkSync } from "node:fs";
|
|
7002
|
+
import { existsSync as existsSync2, unlinkSync } from "node:fs";
|
|
6880
7003
|
import { readFile as readFileAsync, stat as statAsync } from "node:fs/promises";
|
|
6881
7004
|
import { tmpdir } from "node:os";
|
|
6882
7005
|
import { basename, extname, isAbsolute, resolve } from "node:path";
|
|
@@ -7158,7 +7281,7 @@ async function readClipboardImageToTempFile() {
|
|
|
7158
7281
|
const r = await execFileBuffer("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", ps], {
|
|
7159
7282
|
env: { ...process.env, MIXDOG_CLIPBOARD_IMAGE_PATH: out }
|
|
7160
7283
|
});
|
|
7161
|
-
return r.ok &&
|
|
7284
|
+
return r.ok && existsSync2(out) ? out : null;
|
|
7162
7285
|
}
|
|
7163
7286
|
if (process.platform === "darwin") {
|
|
7164
7287
|
const script = `set png_data to (the clipboard as \xABclass PNGf\xBB)
|
|
@@ -7166,7 +7289,7 @@ set fp to open for access POSIX file "${out.replace(/"/g, '\\"')}" with write pe
|
|
|
7166
7289
|
write png_data to fp
|
|
7167
7290
|
close access fp`;
|
|
7168
7291
|
const r = await execFileBuffer("osascript", ["-e", script]);
|
|
7169
|
-
return r.ok &&
|
|
7292
|
+
return r.ok && existsSync2(out) ? out : null;
|
|
7170
7293
|
}
|
|
7171
7294
|
return null;
|
|
7172
7295
|
}
|
|
@@ -7216,11 +7339,11 @@ async function readClipboardText() {
|
|
|
7216
7339
|
}
|
|
7217
7340
|
|
|
7218
7341
|
// src/standalone/projects.mjs
|
|
7219
|
-
import { homedir } from "node:os";
|
|
7220
|
-
import { existsSync as
|
|
7221
|
-
import { basename as basename2, dirname, isAbsolute as isAbsolute2, join, resolve as resolve2 } from "node:path";
|
|
7222
|
-
var MIXDOG_HOME = process.env.MIXDOG_HOME ||
|
|
7223
|
-
var PROJECTS_FILE =
|
|
7342
|
+
import { homedir as homedir2 } from "node:os";
|
|
7343
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
7344
|
+
import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve as resolve2 } from "node:path";
|
|
7345
|
+
var MIXDOG_HOME = process.env.MIXDOG_HOME || join3(homedir2(), ".mixdog");
|
|
7346
|
+
var PROJECTS_FILE = join3(MIXDOG_HOME, "projects.json");
|
|
7224
7347
|
function toAbsolute(rawPath) {
|
|
7225
7348
|
const text = String(rawPath || "").trim();
|
|
7226
7349
|
if (!text) return "";
|
|
@@ -7232,8 +7355,8 @@ function normalizeKey(absPath) {
|
|
|
7232
7355
|
}
|
|
7233
7356
|
function readStore() {
|
|
7234
7357
|
try {
|
|
7235
|
-
if (!
|
|
7236
|
-
const raw =
|
|
7358
|
+
if (!existsSync3(PROJECTS_FILE)) return { projects: [] };
|
|
7359
|
+
const raw = readFileSync2(PROJECTS_FILE, "utf8");
|
|
7237
7360
|
const parsed = JSON.parse(raw);
|
|
7238
7361
|
const projects = Array.isArray(parsed?.projects) ? parsed.projects : [];
|
|
7239
7362
|
return {
|
|
@@ -7250,9 +7373,9 @@ function readStore() {
|
|
|
7250
7373
|
}
|
|
7251
7374
|
function writeStore(store) {
|
|
7252
7375
|
try {
|
|
7253
|
-
|
|
7376
|
+
mkdirSync2(dirname3(PROJECTS_FILE), { recursive: true });
|
|
7254
7377
|
const tmp = `${PROJECTS_FILE}.${process.pid}.tmp`;
|
|
7255
|
-
|
|
7378
|
+
writeFileSync2(tmp, `${JSON.stringify(store, null, 2)}
|
|
7256
7379
|
`, "utf8");
|
|
7257
7380
|
renameSync(tmp, PROJECTS_FILE);
|
|
7258
7381
|
} catch {
|
|
@@ -7266,14 +7389,14 @@ function ensureProjectIdMarker(absPath, name) {
|
|
|
7266
7389
|
} catch {
|
|
7267
7390
|
return;
|
|
7268
7391
|
}
|
|
7269
|
-
const markerPath =
|
|
7270
|
-
if (
|
|
7392
|
+
const markerPath = join3(absPath, ".mixdog", "project.id");
|
|
7393
|
+
if (existsSync3(markerPath)) return;
|
|
7271
7394
|
const value = String(name || basename2(absPath) || "").trim();
|
|
7272
7395
|
if (!value || value.toLowerCase() === "common") return;
|
|
7273
|
-
const markerDir =
|
|
7274
|
-
|
|
7396
|
+
const markerDir = join3(absPath, ".mixdog");
|
|
7397
|
+
mkdirSync2(markerDir, { recursive: true });
|
|
7275
7398
|
const tmp = `${markerPath}.${process.pid}.tmp`;
|
|
7276
|
-
|
|
7399
|
+
writeFileSync2(tmp, `${value}
|
|
7277
7400
|
`, "utf8");
|
|
7278
7401
|
renameSync(tmp, markerPath);
|
|
7279
7402
|
} catch {
|
|
@@ -7341,7 +7464,7 @@ function renameProject(rawPath, nextName) {
|
|
|
7341
7464
|
}
|
|
7342
7465
|
function pathExists(rawPath) {
|
|
7343
7466
|
const absPath = toAbsolute(rawPath);
|
|
7344
|
-
return !!absPath &&
|
|
7467
|
+
return !!absPath && existsSync3(absPath);
|
|
7345
7468
|
}
|
|
7346
7469
|
function isDirectory(rawPath) {
|
|
7347
7470
|
const absPath = toAbsolute(rawPath);
|
|
@@ -7356,7 +7479,7 @@ function ensureDir(rawPath) {
|
|
|
7356
7479
|
const absPath = toAbsolute(rawPath);
|
|
7357
7480
|
if (!absPath) return "";
|
|
7358
7481
|
try {
|
|
7359
|
-
|
|
7482
|
+
mkdirSync2(absPath, { recursive: true });
|
|
7360
7483
|
return absPath;
|
|
7361
7484
|
} catch {
|
|
7362
7485
|
return "";
|
|
@@ -7381,7 +7504,7 @@ function runCapture(cmd, args, { timeoutMs = DIALOG_TIMEOUT_MS } = {}) {
|
|
|
7381
7504
|
}
|
|
7382
7505
|
let stdout = "";
|
|
7383
7506
|
let settled = false;
|
|
7384
|
-
const
|
|
7507
|
+
const timer2 = setTimeout(() => {
|
|
7385
7508
|
if (settled) return;
|
|
7386
7509
|
settled = true;
|
|
7387
7510
|
try {
|
|
@@ -7390,20 +7513,20 @@ function runCapture(cmd, args, { timeoutMs = DIALOG_TIMEOUT_MS } = {}) {
|
|
|
7390
7513
|
}
|
|
7391
7514
|
resolve5({ ok: false, code: -1, stdout: "", error: new Error("dialog timed out") });
|
|
7392
7515
|
}, timeoutMs);
|
|
7393
|
-
|
|
7516
|
+
timer2.unref?.();
|
|
7394
7517
|
child.stdout.on("data", (chunk) => {
|
|
7395
7518
|
stdout += chunk.toString("utf8");
|
|
7396
7519
|
});
|
|
7397
7520
|
child.on("error", (error) => {
|
|
7398
7521
|
if (settled) return;
|
|
7399
7522
|
settled = true;
|
|
7400
|
-
clearTimeout(
|
|
7523
|
+
clearTimeout(timer2);
|
|
7401
7524
|
resolve5({ ok: false, code: -1, stdout: "", error });
|
|
7402
7525
|
});
|
|
7403
7526
|
child.on("close", (code) => {
|
|
7404
7527
|
if (settled) return;
|
|
7405
7528
|
settled = true;
|
|
7406
|
-
clearTimeout(
|
|
7529
|
+
clearTimeout(timer2);
|
|
7407
7530
|
resolve5({ ok: code === 0, code, stdout });
|
|
7408
7531
|
});
|
|
7409
7532
|
});
|
|
@@ -7989,7 +8112,7 @@ function copyToClipboard(text) {
|
|
|
7989
8112
|
import stringWidth11 from "string-width";
|
|
7990
8113
|
|
|
7991
8114
|
// src/tui/app/use-mouse-input.mjs
|
|
7992
|
-
import { useCallback as useCallback2, useEffect as
|
|
8115
|
+
import { useCallback as useCallback2, useEffect as useEffect7, useRef as useRef7 } from "react";
|
|
7993
8116
|
|
|
7994
8117
|
// src/tui/markdown/measure-rendered-rows.mjs
|
|
7995
8118
|
import stripAnsi4 from "strip-ansi";
|
|
@@ -8454,6 +8577,25 @@ function collectFlatBodyLines(text, codeBlock, bandWidth) {
|
|
|
8454
8577
|
}
|
|
8455
8578
|
return lines;
|
|
8456
8579
|
}
|
|
8580
|
+
function normalizeCodePlain(text) {
|
|
8581
|
+
return String(text ?? "").replace(/\r\n?/g, "\n").replace(/\t/g, " ").replace(/[\u0000-\u0009\u000b-\u001f\u007f]/g, " ");
|
|
8582
|
+
}
|
|
8583
|
+
function collectPlainBodyLines(text, codeBlock, bandWidth) {
|
|
8584
|
+
const max = Math.max(1, bandWidth);
|
|
8585
|
+
const lines = [];
|
|
8586
|
+
for (const line of String(text ?? "").split(EOL)) {
|
|
8587
|
+
if (!line) {
|
|
8588
|
+
lines.push("");
|
|
8589
|
+
continue;
|
|
8590
|
+
}
|
|
8591
|
+
if (line.length <= max && displayWidth(line) <= max) {
|
|
8592
|
+
lines.push(codeBlock(line));
|
|
8593
|
+
} else {
|
|
8594
|
+
for (const seg of wrapCodeLine(codeBlock(line), max)) lines.push(seg);
|
|
8595
|
+
}
|
|
8596
|
+
}
|
|
8597
|
+
return lines;
|
|
8598
|
+
}
|
|
8457
8599
|
function collectHighlightedBodyLines(text, hljsLang, bandWidth) {
|
|
8458
8600
|
const highlighted = highlightCodeText(text, hljsLang);
|
|
8459
8601
|
const { codeBlock } = colorizers();
|
|
@@ -8469,19 +8611,24 @@ function renderCodeBlock(token, width = 0) {
|
|
|
8469
8611
|
const { codeBlock } = colorizers();
|
|
8470
8612
|
const c = extraColorizers();
|
|
8471
8613
|
const lang = normalizeLang(token.lang);
|
|
8472
|
-
const text = normalizeCodeText(decodeEntities(token.text ?? ""));
|
|
8473
8614
|
const renderWidth = Math.max(8, Number(width) || 80);
|
|
8474
8615
|
const contentWidth = Math.max(1, renderWidth - CODE_GUTTER.length);
|
|
8475
8616
|
let bodyLines;
|
|
8476
|
-
if (
|
|
8477
|
-
|
|
8617
|
+
if (token.plain) {
|
|
8618
|
+
const text = normalizeCodePlain(decodeEntities(token.text ?? ""));
|
|
8619
|
+
bodyLines = collectPlainBodyLines(text, codeBlock, contentWidth);
|
|
8478
8620
|
} else {
|
|
8479
|
-
const
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
bodyLines = collectHighlightedBodyLines(text, hljsLang, contentWidth);
|
|
8621
|
+
const text = normalizeCodeText(decodeEntities(token.text ?? ""));
|
|
8622
|
+
if (DIFF_LANGS.has(lang) || !lang && looksLikeUnifiedDiff(text)) {
|
|
8623
|
+
bodyLines = collectDiffBodyLines(text, c, contentWidth);
|
|
8483
8624
|
} else {
|
|
8484
|
-
|
|
8625
|
+
const hljsLang = resolveHljsLanguage(lang);
|
|
8626
|
+
const family = LANG_FAMILY[lang];
|
|
8627
|
+
if (hljsLang && family !== "md") {
|
|
8628
|
+
bodyLines = collectHighlightedBodyLines(text, hljsLang, contentWidth);
|
|
8629
|
+
} else {
|
|
8630
|
+
bodyLines = collectFlatBodyLines(text, codeBlock, contentWidth);
|
|
8631
|
+
}
|
|
8485
8632
|
}
|
|
8486
8633
|
}
|
|
8487
8634
|
const indentedBody = bodyLines.map((line) => `${CODE_GUTTER}${line ?? ""}`);
|
|
@@ -8903,6 +9050,38 @@ function trimPartialClosingFences(tokens) {
|
|
|
8903
9050
|
if (lastLine.length >= marker.length || lastLine !== marker[0].repeat(lastLine.length)) return;
|
|
8904
9051
|
token.text = String(token.text ?? "").slice(0, -lastLine.length).replace(/\n$/, "");
|
|
8905
9052
|
}
|
|
9053
|
+
var OPEN_FENCE_RE = /^( {0,3})(`{3,}|~{3,})(.*)$/;
|
|
9054
|
+
var CLOSE_FENCE_RE = /^ {0,3}([`~]+)[ \t]*$/;
|
|
9055
|
+
function isClosingFence(line, char, openLen) {
|
|
9056
|
+
const m = CLOSE_FENCE_RE.exec(line);
|
|
9057
|
+
if (!m) return false;
|
|
9058
|
+
const run = m[1];
|
|
9059
|
+
return run.startsWith(char.repeat(openLen));
|
|
9060
|
+
}
|
|
9061
|
+
function findOpenFenceStart(text) {
|
|
9062
|
+
const value = String(text ?? "");
|
|
9063
|
+
let open = null;
|
|
9064
|
+
let start = 0;
|
|
9065
|
+
for (let i = 0; i <= value.length; i++) {
|
|
9066
|
+
if (i !== value.length && value[i] !== "\n") continue;
|
|
9067
|
+
const line = value.slice(start, i);
|
|
9068
|
+
if (!open) {
|
|
9069
|
+
const m = OPEN_FENCE_RE.exec(line);
|
|
9070
|
+
if (m) {
|
|
9071
|
+
const char = m[2][0];
|
|
9072
|
+
const info = m[3];
|
|
9073
|
+
if (!(char === "`" && info.indexOf("`") !== -1)) {
|
|
9074
|
+
open = { index: start, indent: m[1].length, char, len: m[2].length, lang: info.trim() };
|
|
9075
|
+
}
|
|
9076
|
+
}
|
|
9077
|
+
} else if (isClosingFence(line, open.char, open.len)) {
|
|
9078
|
+
open = null;
|
|
9079
|
+
}
|
|
9080
|
+
start = i + 1;
|
|
9081
|
+
}
|
|
9082
|
+
if (!open || open.indent !== 0) return null;
|
|
9083
|
+
return { index: open.index, lang: open.lang };
|
|
9084
|
+
}
|
|
8906
9085
|
|
|
8907
9086
|
// src/tui/markdown/render-ansi.mjs
|
|
8908
9087
|
var TOKEN_CACHE_MAX = 500;
|
|
@@ -8932,6 +9111,23 @@ function lexMarkdown(content, { trimPartialFences = false } = {}) {
|
|
|
8932
9111
|
}];
|
|
8933
9112
|
}
|
|
8934
9113
|
if (trimPartialFences) {
|
|
9114
|
+
const open = findOpenFenceStart(text);
|
|
9115
|
+
if (open) {
|
|
9116
|
+
const post = text.slice(open.index);
|
|
9117
|
+
const nl = post.indexOf("\n");
|
|
9118
|
+
const codeToken = {
|
|
9119
|
+
type: "code",
|
|
9120
|
+
raw: post,
|
|
9121
|
+
lang: open.lang,
|
|
9122
|
+
text: nl === -1 ? "" : post.slice(nl + 1),
|
|
9123
|
+
plain: true
|
|
9124
|
+
};
|
|
9125
|
+
const pre = text.slice(0, open.index);
|
|
9126
|
+
const tokens3 = pre ? marked.lexer(pre) : [];
|
|
9127
|
+
tokens3.push(codeToken);
|
|
9128
|
+
trimPartialClosingFences(tokens3);
|
|
9129
|
+
return tokens3;
|
|
9130
|
+
}
|
|
8935
9131
|
const tokens2 = marked.lexer(text);
|
|
8936
9132
|
trimPartialClosingFences(tokens2);
|
|
8937
9133
|
return tokens2;
|
|
@@ -9077,6 +9273,21 @@ function resolveStreamingMarkdownParts(text, streamKey) {
|
|
|
9077
9273
|
if (!t.startsWith(stablePrefix)) {
|
|
9078
9274
|
stablePrefix = "";
|
|
9079
9275
|
}
|
|
9276
|
+
const open = findOpenFenceStart(t);
|
|
9277
|
+
if (open) {
|
|
9278
|
+
let openPrefix = t.substring(0, open.index);
|
|
9279
|
+
if (isWhitespaceOnlyText(openPrefix)) openPrefix = "";
|
|
9280
|
+
if (key && openPrefix) touchStablePrefixKey(key, openPrefix);
|
|
9281
|
+
else if (key) stablePrefixByStreamKey.delete(key);
|
|
9282
|
+
const unstableSuffix2 = t.substring(openPrefix.length);
|
|
9283
|
+
return {
|
|
9284
|
+
plain: false,
|
|
9285
|
+
openFence: true,
|
|
9286
|
+
stablePrefix: openPrefix,
|
|
9287
|
+
unstableSuffix: unstableSuffix2,
|
|
9288
|
+
unstableForRender: unstableSuffix2
|
|
9289
|
+
};
|
|
9290
|
+
}
|
|
9080
9291
|
try {
|
|
9081
9292
|
configureMarked();
|
|
9082
9293
|
const boundary = stablePrefix.length;
|
|
@@ -9831,6 +10042,8 @@ function positiveIntEnv(name, fallback) {
|
|
|
9831
10042
|
var TRANSCRIPT_WINDOW_MIN_ITEMS = positiveIntEnv("MIXDOG_TUI_TRANSCRIPT_WINDOW_MIN_ITEMS", 12);
|
|
9832
10043
|
var TRANSCRIPT_WINDOW_OVERSCAN_ROWS = positiveIntEnv("MIXDOG_TUI_TRANSCRIPT_OVERSCAN_ROWS", 16);
|
|
9833
10044
|
var TRANSCRIPT_WINDOW_MAX_ITEMS = positiveIntEnv("MIXDOG_TUI_TRANSCRIPT_WINDOW_ITEMS", 80);
|
|
10045
|
+
var TRANSCRIPT_WINDOW_TAIL_OVERSCAN_ROWS = positiveIntEnv("MIXDOG_TUI_TRANSCRIPT_TAIL_OVERSCAN_ROWS", 4);
|
|
10046
|
+
var TRANSCRIPT_WINDOW_TAIL_MAX_ITEMS = positiveIntEnv("MIXDOG_TUI_TRANSCRIPT_WINDOW_TAIL_ITEMS", 20);
|
|
9834
10047
|
var SELECTION_PAINT_INTERVAL_MS = positiveIntEnv("MIXDOG_TUI_SELECTION_PAINT_MS", 24);
|
|
9835
10048
|
var SCROLL_COALESCE_MS = positiveIntEnv("MIXDOG_TUI_SCROLL_COALESCE_MS", 16);
|
|
9836
10049
|
var PROMPT_HISTORY_LIMIT = 50;
|
|
@@ -10449,12 +10662,14 @@ function transcriptRenderWindow(items, { scrollOffset = 0, viewportHeight = 24,
|
|
|
10449
10662
|
return { startIndex: 0, endIndex: itemCount, items: allItems, bottomSpacerRows: 0, totalRows, maxScrollRows, effectiveScrollOffset };
|
|
10450
10663
|
}
|
|
10451
10664
|
const minItems = Math.min(TRANSCRIPT_WINDOW_MIN_ITEMS, itemCount);
|
|
10452
|
-
const
|
|
10665
|
+
const atTail = effectiveScrollOffset === 0;
|
|
10666
|
+
const overscanRows = atTail ? TRANSCRIPT_WINDOW_TAIL_OVERSCAN_ROWS : TRANSCRIPT_WINDOW_OVERSCAN_ROWS;
|
|
10667
|
+
const maxItems = Math.max(minItems, atTail ? TRANSCRIPT_WINDOW_TAIL_MAX_ITEMS : TRANSCRIPT_WINDOW_MAX_ITEMS);
|
|
10453
10668
|
const prefixRows = fallbackIndex.prefixRows;
|
|
10454
10669
|
const visibleTop = Math.max(0, totalRows - effectiveScrollOffset - viewRows);
|
|
10455
10670
|
const visibleBottom = Math.min(totalRows, totalRows - effectiveScrollOffset);
|
|
10456
|
-
const desiredTop = Math.max(0, visibleTop -
|
|
10457
|
-
const desiredBottom = Math.min(totalRows, visibleBottom +
|
|
10671
|
+
const desiredTop = Math.max(0, visibleTop - overscanRows);
|
|
10672
|
+
const desiredBottom = Math.min(totalRows, visibleBottom + overscanRows);
|
|
10458
10673
|
let startIndex = Math.max(0, upperBound(prefixRows, desiredTop) - 1);
|
|
10459
10674
|
let endIndex = Math.min(itemCount, Math.max(startIndex + 1, lowerBound(prefixRows, Math.max(desiredBottom, desiredTop + 1))));
|
|
10460
10675
|
while (endIndex - startIndex < minItems && startIndex > 0) startIndex--;
|
|
@@ -10462,9 +10677,10 @@ function transcriptRenderWindow(items, { scrollOffset = 0, viewportHeight = 24,
|
|
|
10462
10677
|
if (endIndex - startIndex > maxItems) {
|
|
10463
10678
|
const visibleStartIndex = Math.max(0, upperBound(prefixRows, visibleTop) - 1);
|
|
10464
10679
|
const visibleEndIndex = Math.min(itemCount, Math.max(visibleStartIndex + 1, lowerBound(prefixRows, Math.max(visibleBottom, visibleTop + 1))));
|
|
10465
|
-
|
|
10466
|
-
|
|
10467
|
-
|
|
10680
|
+
const effectiveMaxItems = Math.max(maxItems, visibleEndIndex - visibleStartIndex);
|
|
10681
|
+
startIndex = Math.max(0, Math.min(visibleStartIndex, itemCount - effectiveMaxItems));
|
|
10682
|
+
endIndex = Math.min(itemCount, Math.max(visibleEndIndex, startIndex + effectiveMaxItems));
|
|
10683
|
+
if (endIndex - startIndex > effectiveMaxItems) startIndex = Math.max(0, endIndex - effectiveMaxItems);
|
|
10468
10684
|
}
|
|
10469
10685
|
const bottomSpacerRows = Math.max(0, totalRows - (prefixRows[endIndex] || totalRows));
|
|
10470
10686
|
return {
|
|
@@ -10513,8 +10729,8 @@ function useMouseInput({
|
|
|
10513
10729
|
setMeasuredRowsVersion,
|
|
10514
10730
|
clearStitchBuffer
|
|
10515
10731
|
}) {
|
|
10516
|
-
const zoomTimerRef =
|
|
10517
|
-
const edgeAutoscrollRef =
|
|
10732
|
+
const zoomTimerRef = useRef7(null);
|
|
10733
|
+
const edgeAutoscrollRef = useRef7({ dir: 0, timer: null, noMove: 0 });
|
|
10518
10734
|
const passthroughCtrlWheelZoom = useCallback2(() => {
|
|
10519
10735
|
if (!stdout?.write) return;
|
|
10520
10736
|
try {
|
|
@@ -10537,10 +10753,10 @@ function useMouseInput({
|
|
|
10537
10753
|
zoomTimerRef.current = setTimeout(() => restore(0), 700);
|
|
10538
10754
|
zoomTimerRef.current.unref?.();
|
|
10539
10755
|
}, [stdout, zoomTimerRef]);
|
|
10540
|
-
|
|
10756
|
+
useEffect7(() => () => {
|
|
10541
10757
|
if (zoomTimerRef.current) clearTimeout(zoomTimerRef.current);
|
|
10542
10758
|
}, [zoomTimerRef]);
|
|
10543
|
-
|
|
10759
|
+
useEffect7(() => {
|
|
10544
10760
|
if (!inkInput || !isRawModeSupported) return void 0;
|
|
10545
10761
|
const WHEEL_SGR = /\x1b\[<(\d+);/;
|
|
10546
10762
|
const linearSelection = (a, b) => {
|
|
@@ -10917,7 +11133,7 @@ function useMouseInput({
|
|
|
10917
11133
|
}
|
|
10918
11134
|
|
|
10919
11135
|
// src/tui/app/use-transcript-scroll.mjs
|
|
10920
|
-
import { useCallback as useCallback3, useEffect as
|
|
11136
|
+
import { useCallback as useCallback3, useEffect as useEffect8, useRef as useRef8 } from "react";
|
|
10921
11137
|
function useTranscriptScroll({
|
|
10922
11138
|
store,
|
|
10923
11139
|
frameColumns,
|
|
@@ -10937,13 +11153,13 @@ function useTranscriptScroll({
|
|
|
10937
11153
|
selectionLayoutRef,
|
|
10938
11154
|
selectionTextRef
|
|
10939
11155
|
}) {
|
|
10940
|
-
const scrollAnimationRef =
|
|
10941
|
-
const selectionPaintRef =
|
|
10942
|
-
const scrollCoalesceRef =
|
|
10943
|
-
const selectionTextTimerRef =
|
|
10944
|
-
const stitchBufferRef =
|
|
10945
|
-
const stitchHarvestTimerRef =
|
|
10946
|
-
const stitchHarvestScrollRef =
|
|
11156
|
+
const scrollAnimationRef = useRef8(null);
|
|
11157
|
+
const selectionPaintRef = useRef8({ t: 0, rect: null, pending: null, timer: null });
|
|
11158
|
+
const scrollCoalesceRef = useRef8({ pendingRows: 0, timer: null });
|
|
11159
|
+
const selectionTextTimerRef = useRef8(null);
|
|
11160
|
+
const stitchBufferRef = useRef8(/* @__PURE__ */ new Map());
|
|
11161
|
+
const stitchHarvestTimerRef = useRef8(null);
|
|
11162
|
+
const stitchHarvestScrollRef = useRef8(0);
|
|
10947
11163
|
const clearStitchBuffer = useCallback3(() => {
|
|
10948
11164
|
stitchBufferRef.current.clear();
|
|
10949
11165
|
if (stitchHarvestTimerRef.current) {
|
|
@@ -11210,14 +11426,14 @@ function useTranscriptScroll({
|
|
|
11210
11426
|
if (lr != null && Number.isFinite(lr.x2)) return Math.max(0, lr.x2);
|
|
11211
11427
|
return Math.max(0, frameColumns - 1);
|
|
11212
11428
|
}, [store, frameColumns]);
|
|
11213
|
-
const gridSelectionActiveRef =
|
|
11429
|
+
const gridSelectionActiveRef = useRef8(() => {
|
|
11214
11430
|
const drag = dragRef.current;
|
|
11215
11431
|
if (!drag || drag.active) return false;
|
|
11216
11432
|
if (drag.region !== "transcript" && drag.region !== "status") return false;
|
|
11217
11433
|
const rect = drag.rect;
|
|
11218
11434
|
return Boolean(rect) && !(rect.x1 === rect.x2 && rect.y1 === rect.y2);
|
|
11219
11435
|
});
|
|
11220
|
-
|
|
11436
|
+
useEffect8(() => () => {
|
|
11221
11437
|
const paintState = selectionPaintRef.current;
|
|
11222
11438
|
if (paintState.timer) clearTimeout(paintState.timer);
|
|
11223
11439
|
paintState.timer = null;
|
|
@@ -11421,7 +11637,7 @@ function useTranscriptScroll({
|
|
|
11421
11637
|
}
|
|
11422
11638
|
|
|
11423
11639
|
// src/tui/app/use-transcript-window.mjs
|
|
11424
|
-
import { useCallback as useCallback4, useEffect as
|
|
11640
|
+
import { useCallback as useCallback4, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useMemo, useRef as useRef9, useState as useState7 } from "react";
|
|
11425
11641
|
function useTranscriptWindow({
|
|
11426
11642
|
items,
|
|
11427
11643
|
themeEpoch,
|
|
@@ -11450,14 +11666,14 @@ function useTranscriptWindow({
|
|
|
11450
11666
|
measuredRowsVersion,
|
|
11451
11667
|
setMeasuredRowsVersion
|
|
11452
11668
|
}) {
|
|
11453
|
-
const transcriptTotalRowsRef =
|
|
11454
|
-
const preservedScrollDeltaRef =
|
|
11455
|
-
const committedMaxScrollRowsRef =
|
|
11456
|
-
const incrementalRowIndexCacheRef =
|
|
11457
|
-
const prevViewportGeomRef =
|
|
11458
|
-
const transcriptItemElsRef =
|
|
11459
|
-
const transcriptMeasureRefCache =
|
|
11460
|
-
const transcriptMeasureItemsRef =
|
|
11669
|
+
const transcriptTotalRowsRef = useRef9(0);
|
|
11670
|
+
const preservedScrollDeltaRef = useRef9(0);
|
|
11671
|
+
const committedMaxScrollRowsRef = useRef9(0);
|
|
11672
|
+
const incrementalRowIndexCacheRef = useRef9(null);
|
|
11673
|
+
const prevViewportGeomRef = useRef9({ contentHeight: 0, floatingPanelRows: 0 });
|
|
11674
|
+
const transcriptItemElsRef = useRef9(/* @__PURE__ */ new Map());
|
|
11675
|
+
const transcriptMeasureRefCache = useRef9(/* @__PURE__ */ new Map());
|
|
11676
|
+
const transcriptMeasureItemsRef = useRef9(/* @__PURE__ */ new Map());
|
|
11461
11677
|
const transcriptMeasureRef = useCallback4((item) => {
|
|
11462
11678
|
if (!TRANSCRIPT_MEASURED_ROWS || !item || item.id == null) return void 0;
|
|
11463
11679
|
if (shouldSuppressFullyFailedToolItem(item)) {
|
|
@@ -11855,13 +12071,13 @@ function useTranscriptWindow({
|
|
|
11855
12071
|
dragRef.current = { ...dragRef.current, rect: clippedRect };
|
|
11856
12072
|
paintSelectionRect(clippedRect, { rememberText: false, immediate: true });
|
|
11857
12073
|
}, [transcriptContentHeight, transcriptWindow.totalRows, transcriptWindow.effectiveScrollOffset, withSelectionClip, paintSelectionRect]);
|
|
11858
|
-
|
|
12074
|
+
useEffect9(() => {
|
|
11859
12075
|
if (!dragRef.current.rect) return;
|
|
11860
12076
|
const clippedRect = withSelectionClip(dragRef.current.rect);
|
|
11861
12077
|
dragRef.current = { ...dragRef.current, rect: clippedRect };
|
|
11862
12078
|
paintSelectionRect(clippedRect, { rememberText: false, immediate: true });
|
|
11863
12079
|
}, [themeEpoch, withSelectionClip, paintSelectionRect]);
|
|
11864
|
-
|
|
12080
|
+
useEffect9(() => {
|
|
11865
12081
|
const maxRows = Math.max(0, Number(transcriptWindow.maxScrollRows) || 0);
|
|
11866
12082
|
if (scrollTargetRef.current <= maxRows && scrollPositionRef.current <= maxRows && scrollOffset <= maxRows) return;
|
|
11867
12083
|
stopSmoothScroll();
|
|
@@ -14014,37 +14230,25 @@ function createOnboardingSteps({
|
|
|
14014
14230
|
}
|
|
14015
14231
|
|
|
14016
14232
|
// src/runtime/shared/config.mjs
|
|
14017
|
-
import { readFileSync as
|
|
14018
|
-
import { join as
|
|
14233
|
+
import { readFileSync as readFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync6 } from "fs";
|
|
14234
|
+
import { join as join6, dirname as dirname6 } from "path";
|
|
14019
14235
|
import { createRequire as createRequire2 } from "module";
|
|
14020
14236
|
|
|
14021
|
-
// src/runtime/shared/plugin-paths.mjs
|
|
14022
|
-
import { homedir as homedir2 } from "os";
|
|
14023
|
-
import { dirname as dirname2, join as join2 } from "path";
|
|
14024
|
-
import { fileURLToPath } from "url";
|
|
14025
|
-
var DEFAULT_ROOT = join2(dirname2(fileURLToPath(import.meta.url)), "..", "..");
|
|
14026
|
-
function mixdogHome() {
|
|
14027
|
-
return process.env.MIXDOG_HOME || join2(homedir2(), ".mixdog");
|
|
14028
|
-
}
|
|
14029
|
-
function resolvePluginData() {
|
|
14030
|
-
return process.env.MIXDOG_DATA_DIR || join2(mixdogHome(), "data");
|
|
14031
|
-
}
|
|
14032
|
-
|
|
14033
14237
|
// src/runtime/shared/atomic-file.mjs
|
|
14034
14238
|
import {
|
|
14035
14239
|
closeSync,
|
|
14036
|
-
existsSync as
|
|
14240
|
+
existsSync as existsSync4,
|
|
14037
14241
|
fsyncSync,
|
|
14038
14242
|
linkSync,
|
|
14039
|
-
mkdirSync as
|
|
14243
|
+
mkdirSync as mkdirSync3,
|
|
14040
14244
|
openSync,
|
|
14041
|
-
readFileSync as
|
|
14245
|
+
readFileSync as readFileSync3,
|
|
14042
14246
|
renameSync as renameSync2,
|
|
14043
14247
|
statSync as statSync2,
|
|
14044
14248
|
unlinkSync as unlinkSync2,
|
|
14045
|
-
writeFileSync as
|
|
14249
|
+
writeFileSync as writeFileSync3
|
|
14046
14250
|
} from "fs";
|
|
14047
|
-
import { dirname as
|
|
14251
|
+
import { dirname as dirname4, basename as basename3, join as join4 } from "path";
|
|
14048
14252
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
14049
14253
|
import { execFile as execFile2, execFileSync } from "child_process";
|
|
14050
14254
|
import { promisify } from "util";
|
|
@@ -14096,7 +14300,7 @@ function withFileLockSync(lockPath, fn, opts = {}) {
|
|
|
14096
14300
|
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : DEFAULT_LOCK_TIMEOUT_MS;
|
|
14097
14301
|
const staleMs = Number.isFinite(opts.staleMs) ? opts.staleMs : 3e4;
|
|
14098
14302
|
const deadline = Date.now() + timeoutMs;
|
|
14099
|
-
|
|
14303
|
+
mkdirSync3(dirname4(lockPath), { recursive: true });
|
|
14100
14304
|
let attempt = 0;
|
|
14101
14305
|
let lastErr = null;
|
|
14102
14306
|
while (true) {
|
|
@@ -14124,7 +14328,7 @@ function withFileLockSync(lockPath, fn, opts = {}) {
|
|
|
14124
14328
|
continue;
|
|
14125
14329
|
}
|
|
14126
14330
|
try {
|
|
14127
|
-
|
|
14331
|
+
writeFileSync3(fd, `${process.pid} ${Date.now()} ${_OWNER_TOKEN}
|
|
14128
14332
|
`, "utf8");
|
|
14129
14333
|
} catch {
|
|
14130
14334
|
}
|
|
@@ -14149,7 +14353,7 @@ function withFileLockSync(lockPath, fn, opts = {}) {
|
|
|
14149
14353
|
}
|
|
14150
14354
|
function _readLockOwnerPid(lockPath) {
|
|
14151
14355
|
try {
|
|
14152
|
-
const raw =
|
|
14356
|
+
const raw = readFileSync3(lockPath, "utf8");
|
|
14153
14357
|
const tok = String(raw).trim().split(/\s+/)[0];
|
|
14154
14358
|
const pid = Number.parseInt(tok, 10);
|
|
14155
14359
|
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
@@ -14169,7 +14373,7 @@ function _pidIsDead(pid) {
|
|
|
14169
14373
|
}
|
|
14170
14374
|
function _readLockOwner(lockPath) {
|
|
14171
14375
|
try {
|
|
14172
|
-
const raw =
|
|
14376
|
+
const raw = readFileSync3(lockPath, "utf8");
|
|
14173
14377
|
const parts = String(raw).trim().split(/\s+/);
|
|
14174
14378
|
const pid = Number.parseInt(parts[0], 10);
|
|
14175
14379
|
return {
|
|
@@ -14250,14 +14454,14 @@ function _reclaimGuardIsUnreadableAndStale(guardPath, staleMs) {
|
|
|
14250
14454
|
}
|
|
14251
14455
|
function _reclaimGuardMatchesToken(guardPath, token) {
|
|
14252
14456
|
try {
|
|
14253
|
-
return
|
|
14457
|
+
return readFileSync3(guardPath, "utf8") === token;
|
|
14254
14458
|
} catch {
|
|
14255
14459
|
return false;
|
|
14256
14460
|
}
|
|
14257
14461
|
}
|
|
14258
14462
|
function _readGuardContent(guardPath) {
|
|
14259
14463
|
try {
|
|
14260
|
-
return
|
|
14464
|
+
return readFileSync3(guardPath, "utf8");
|
|
14261
14465
|
} catch {
|
|
14262
14466
|
return null;
|
|
14263
14467
|
}
|
|
@@ -14309,7 +14513,7 @@ function _tryAcquireReclaimGuard(lockPath, staleMs) {
|
|
|
14309
14513
|
const token = `${process.pid} ${Date.now()} ${randomBytes2(8).toString("hex")}
|
|
14310
14514
|
`;
|
|
14311
14515
|
try {
|
|
14312
|
-
|
|
14516
|
+
writeFileSync3(fd, token, "utf8");
|
|
14313
14517
|
} catch {
|
|
14314
14518
|
}
|
|
14315
14519
|
return { fd, guardPath, token };
|
|
@@ -14342,7 +14546,7 @@ async function withFileLock(lockPath, fn, opts = {}) {
|
|
|
14342
14546
|
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : DEFAULT_LOCK_TIMEOUT_MS;
|
|
14343
14547
|
const staleMs = Number.isFinite(opts.staleMs) ? opts.staleMs : 3e4;
|
|
14344
14548
|
const deadline = Date.now() + timeoutMs;
|
|
14345
|
-
|
|
14549
|
+
mkdirSync3(dirname4(lockPath), { recursive: true });
|
|
14346
14550
|
let attempt = 0;
|
|
14347
14551
|
let lastErr = null;
|
|
14348
14552
|
while (true) {
|
|
@@ -14370,7 +14574,7 @@ async function withFileLock(lockPath, fn, opts = {}) {
|
|
|
14370
14574
|
continue;
|
|
14371
14575
|
}
|
|
14372
14576
|
try {
|
|
14373
|
-
|
|
14577
|
+
writeFileSync3(fd, `${process.pid} ${Date.now()} ${_OWNER_TOKEN}
|
|
14374
14578
|
`, "utf8");
|
|
14375
14579
|
} catch {
|
|
14376
14580
|
}
|
|
@@ -14397,8 +14601,8 @@ var _cachedUserSid = null;
|
|
|
14397
14601
|
function _resolveCurrentUserPrincipal() {
|
|
14398
14602
|
const systemRoot = process.env.SystemRoot || process.env.windir;
|
|
14399
14603
|
if (systemRoot) {
|
|
14400
|
-
const whoami =
|
|
14401
|
-
if (
|
|
14604
|
+
const whoami = join4(systemRoot, "System32", "whoami.exe");
|
|
14605
|
+
if (existsSync4(whoami)) {
|
|
14402
14606
|
try {
|
|
14403
14607
|
const out = execFileSync(whoami, ["/user", "/fo", "csv", "/nh"], {
|
|
14404
14608
|
encoding: "utf8",
|
|
@@ -14426,8 +14630,8 @@ function _enforceOwnerOnlyAclWin32(targetPath) {
|
|
|
14426
14630
|
err.code = "EACLNOROOT";
|
|
14427
14631
|
throw err;
|
|
14428
14632
|
}
|
|
14429
|
-
const icacls =
|
|
14430
|
-
if (!
|
|
14633
|
+
const icacls = join4(systemRoot, "System32", "icacls.exe");
|
|
14634
|
+
if (!existsSync4(icacls)) {
|
|
14431
14635
|
const err = new Error(`icacls.exe not found at ${icacls}; refusing to leave secret world-readable`);
|
|
14432
14636
|
err.code = "EACLNOICACLS";
|
|
14433
14637
|
throw err;
|
|
@@ -14453,8 +14657,8 @@ function _enforceOwnerOnlyAclWin32(targetPath) {
|
|
|
14453
14657
|
async function _resolveCurrentUserPrincipalAsync() {
|
|
14454
14658
|
const systemRoot = process.env.SystemRoot || process.env.windir;
|
|
14455
14659
|
if (systemRoot) {
|
|
14456
|
-
const whoami =
|
|
14457
|
-
if (
|
|
14660
|
+
const whoami = join4(systemRoot, "System32", "whoami.exe");
|
|
14661
|
+
if (existsSync4(whoami)) {
|
|
14458
14662
|
try {
|
|
14459
14663
|
const { stdout } = await _execFileAsync(whoami, ["/user", "/fo", "csv", "/nh"], {
|
|
14460
14664
|
encoding: "utf8",
|
|
@@ -14478,8 +14682,8 @@ async function _enforceOwnerOnlyAclWin32Async(targetPath) {
|
|
|
14478
14682
|
err.code = "EACLNOROOT";
|
|
14479
14683
|
throw err;
|
|
14480
14684
|
}
|
|
14481
|
-
const icacls =
|
|
14482
|
-
if (!
|
|
14685
|
+
const icacls = join4(systemRoot, "System32", "icacls.exe");
|
|
14686
|
+
if (!existsSync4(icacls)) {
|
|
14483
14687
|
const err = new Error(`icacls.exe not found at ${icacls}; refusing to leave secret world-readable`);
|
|
14484
14688
|
err.code = "EACLNOICACLS";
|
|
14485
14689
|
throw err;
|
|
@@ -14498,12 +14702,12 @@ async function _enforceOwnerOnlyAclWin32Async(targetPath) {
|
|
|
14498
14702
|
}
|
|
14499
14703
|
function writeFileAtomicSync(filePath, data, opts = {}) {
|
|
14500
14704
|
const run = () => {
|
|
14501
|
-
const dir =
|
|
14502
|
-
|
|
14503
|
-
const tmp =
|
|
14705
|
+
const dir = dirname4(filePath);
|
|
14706
|
+
mkdirSync3(dir, { recursive: true });
|
|
14707
|
+
const tmp = join4(dir, `.${basename3(filePath)}.${randomBytes2(12).toString("hex")}.tmp`);
|
|
14504
14708
|
try {
|
|
14505
14709
|
const writeOpts = { encoding: opts.encoding || "utf8", flag: "wx", mode: opts.mode !== void 0 ? opts.mode : 384 };
|
|
14506
|
-
|
|
14710
|
+
writeFileSync3(tmp, data, writeOpts);
|
|
14507
14711
|
if (opts.secret === true) _enforceOwnerOnlyAclWin32(tmp);
|
|
14508
14712
|
if (opts.fsync !== false) {
|
|
14509
14713
|
let fd = null;
|
|
@@ -14539,8 +14743,8 @@ function writeFileAtomicSync(filePath, data, opts = {}) {
|
|
|
14539
14743
|
renameWithRetrySync(tmp, filePath, opts);
|
|
14540
14744
|
} catch (err) {
|
|
14541
14745
|
if (opts.renameFallback === "truncate" && opts.secret !== true && process.platform === "win32" && RETRY_CODES.has(err?.code)) {
|
|
14542
|
-
const data2 =
|
|
14543
|
-
|
|
14746
|
+
const data2 = readFileSync3(tmp);
|
|
14747
|
+
writeFileSync3(filePath, data2, { mode: opts.mode !== void 0 ? opts.mode : 384 });
|
|
14544
14748
|
try {
|
|
14545
14749
|
unlinkSync2(tmp);
|
|
14546
14750
|
} catch {
|
|
@@ -14570,7 +14774,7 @@ function writeFileAtomicSync(filePath, data, opts = {}) {
|
|
|
14570
14774
|
return true;
|
|
14571
14775
|
} catch (err) {
|
|
14572
14776
|
try {
|
|
14573
|
-
if (
|
|
14777
|
+
if (existsSync4(tmp)) unlinkSync2(tmp);
|
|
14574
14778
|
} catch {
|
|
14575
14779
|
}
|
|
14576
14780
|
throw err;
|
|
@@ -14589,7 +14793,7 @@ async function updateJsonAtomic(filePath, mutator, opts = {}) {
|
|
|
14589
14793
|
return withFileLock(`${filePath}.lock`, () => {
|
|
14590
14794
|
let cur = null;
|
|
14591
14795
|
try {
|
|
14592
|
-
cur = JSON.parse(
|
|
14796
|
+
cur = JSON.parse(readFileSync3(filePath, "utf8"));
|
|
14593
14797
|
} catch {
|
|
14594
14798
|
cur = null;
|
|
14595
14799
|
}
|
|
@@ -14603,22 +14807,22 @@ async function updateJsonAtomic(filePath, mutator, opts = {}) {
|
|
|
14603
14807
|
// src/runtime/shared/user-data-guard.mjs
|
|
14604
14808
|
import {
|
|
14605
14809
|
copyFileSync,
|
|
14606
|
-
existsSync as
|
|
14607
|
-
mkdirSync as
|
|
14810
|
+
existsSync as existsSync5,
|
|
14811
|
+
mkdirSync as mkdirSync4,
|
|
14608
14812
|
readdirSync,
|
|
14609
|
-
readFileSync as
|
|
14813
|
+
readFileSync as readFileSync4,
|
|
14610
14814
|
rmSync,
|
|
14611
14815
|
statSync as statSync3,
|
|
14612
|
-
writeFileSync as
|
|
14816
|
+
writeFileSync as writeFileSync4
|
|
14613
14817
|
} from "fs";
|
|
14614
|
-
import { dirname as
|
|
14818
|
+
import { dirname as dirname5, join as join5, resolve as resolve3 } from "path";
|
|
14615
14819
|
import { homedir as homedir3 } from "os";
|
|
14616
14820
|
import { createHash } from "crypto";
|
|
14617
14821
|
function mixdogConfigBaseDir() {
|
|
14618
|
-
return process.env.MIXDOG_CONFIG_DIR ||
|
|
14822
|
+
return process.env.MIXDOG_CONFIG_DIR || join5(homedir3(), ".mixdog");
|
|
14619
14823
|
}
|
|
14620
14824
|
function getBackupRoot() {
|
|
14621
|
-
return process.env.MIXDOG_USER_DATA_BACKUP_ROOT ||
|
|
14825
|
+
return process.env.MIXDOG_USER_DATA_BACKUP_ROOT || join5(mixdogConfigBaseDir(), "backups", "user-data");
|
|
14622
14826
|
}
|
|
14623
14827
|
var USER_DATA_FILES = [
|
|
14624
14828
|
"mixdog-config.json",
|
|
@@ -14639,13 +14843,13 @@ function safeReason(reason) {
|
|
|
14639
14843
|
}
|
|
14640
14844
|
function initMarkerPath(dataDir) {
|
|
14641
14845
|
const id = createHash("sha256").update(String(dataDir || "unknown")).digest("hex").slice(0, 16);
|
|
14642
|
-
return
|
|
14846
|
+
return join5(getBackupRoot(), `.initialized-${id}.json`);
|
|
14643
14847
|
}
|
|
14644
14848
|
function isPlainObject(value) {
|
|
14645
14849
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
14646
14850
|
}
|
|
14647
14851
|
function hasUserDataInitMarker(dataDir) {
|
|
14648
|
-
return
|
|
14852
|
+
return existsSync5(initMarkerPath(dataDir));
|
|
14649
14853
|
}
|
|
14650
14854
|
function isStructurallyCompleteMixdogConfigBackup(parsed) {
|
|
14651
14855
|
if (!isPlainObject(parsed)) return false;
|
|
@@ -14662,10 +14866,10 @@ function loadLatestMixdogConfigFromBackup(_dataDir) {
|
|
|
14662
14866
|
return null;
|
|
14663
14867
|
}
|
|
14664
14868
|
for (const name of entries) {
|
|
14665
|
-
const cfgPath =
|
|
14666
|
-
if (!
|
|
14869
|
+
const cfgPath = join5(root, name, "mixdog-config.json");
|
|
14870
|
+
if (!existsSync5(cfgPath)) continue;
|
|
14667
14871
|
try {
|
|
14668
|
-
const parsed = JSON.parse(
|
|
14872
|
+
const parsed = JSON.parse(readFileSync4(cfgPath, "utf8"));
|
|
14669
14873
|
if (isStructurallyCompleteMixdogConfigBackup(parsed)) return parsed;
|
|
14670
14874
|
} catch {
|
|
14671
14875
|
continue;
|
|
@@ -14677,12 +14881,12 @@ function copyTree(src, dst, copied) {
|
|
|
14677
14881
|
const st = statSync3(src);
|
|
14678
14882
|
if (st.isDirectory()) {
|
|
14679
14883
|
for (const name of readdirSync(src)) {
|
|
14680
|
-
copyTree(
|
|
14884
|
+
copyTree(join5(src, name), join5(dst, name), copied);
|
|
14681
14885
|
}
|
|
14682
14886
|
return;
|
|
14683
14887
|
}
|
|
14684
14888
|
if (!st.isFile()) return;
|
|
14685
|
-
|
|
14889
|
+
mkdirSync4(dirname5(dst), { recursive: true });
|
|
14686
14890
|
copyFileSync(src, dst);
|
|
14687
14891
|
copied.push(dst);
|
|
14688
14892
|
}
|
|
@@ -14695,15 +14899,15 @@ function pruneBackups(keep = 40) {
|
|
|
14695
14899
|
}
|
|
14696
14900
|
for (const name of entries.slice(keep)) {
|
|
14697
14901
|
try {
|
|
14698
|
-
rmSync(
|
|
14902
|
+
rmSync(join5(getBackupRoot(), name), { recursive: true, force: true });
|
|
14699
14903
|
} catch {
|
|
14700
14904
|
}
|
|
14701
14905
|
}
|
|
14702
14906
|
}
|
|
14703
14907
|
function markUserDataInitialized(dataDir) {
|
|
14704
14908
|
try {
|
|
14705
|
-
|
|
14706
|
-
|
|
14909
|
+
mkdirSync4(getBackupRoot(), { recursive: true });
|
|
14910
|
+
writeFileSync4(initMarkerPath(dataDir), JSON.stringify({
|
|
14707
14911
|
dataDir,
|
|
14708
14912
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
14709
14913
|
}, null, 2) + "\n", "utf8");
|
|
@@ -14714,16 +14918,16 @@ function backupUserData(dataDir, reason = "snapshot") {
|
|
|
14714
14918
|
if (process.env.MIXDOG_SKIP_USER_DATA_BACKUP === "1" || process.env.MIXDOG_SKIP_USER_DATA_BACKUP === "true") {
|
|
14715
14919
|
return { dir: null, copied: [] };
|
|
14716
14920
|
}
|
|
14717
|
-
if (!dataDir || !
|
|
14718
|
-
const backupDir =
|
|
14921
|
+
if (!dataDir || !existsSync5(dataDir)) return { dir: null, copied: [] };
|
|
14922
|
+
const backupDir = join5(getBackupRoot(), `${stamp()}-${safeReason(reason)}`);
|
|
14719
14923
|
const copied = [];
|
|
14720
14924
|
for (const rel of USER_DATA_FILES) {
|
|
14721
|
-
const src =
|
|
14722
|
-
if (
|
|
14925
|
+
const src = join5(dataDir, rel);
|
|
14926
|
+
if (existsSync5(src)) copyTree(src, join5(backupDir, rel), copied);
|
|
14723
14927
|
}
|
|
14724
14928
|
for (const rel of USER_DATA_DIRS) {
|
|
14725
|
-
const src =
|
|
14726
|
-
if (
|
|
14929
|
+
const src = join5(dataDir, rel);
|
|
14930
|
+
if (existsSync5(src)) copyTree(src, join5(backupDir, rel), copied);
|
|
14727
14931
|
}
|
|
14728
14932
|
if (copied.length > 0) {
|
|
14729
14933
|
markUserDataInitialized(dataDir);
|
|
@@ -14741,7 +14945,7 @@ var CASE_INSENSITIVE = process.platform === "win32";
|
|
|
14741
14945
|
var _require = createRequire2(import.meta.url);
|
|
14742
14946
|
var { getSecret: _getSecret, setSecret: _setSecret, deleteSecret: _deleteSecret, hasSecret: _hasSecret } = _require("../../lib/keychain-cjs.cjs");
|
|
14743
14947
|
var DATA_DIR = resolvePluginData();
|
|
14744
|
-
var CONFIG_PATH =
|
|
14948
|
+
var CONFIG_PATH = join6(DATA_DIR, "mixdog-config.json");
|
|
14745
14949
|
var GENERATED_KEY = "_generated";
|
|
14746
14950
|
function isPlainObject2(value) {
|
|
14747
14951
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -14754,7 +14958,7 @@ function stripGeneratedMarker(data) {
|
|
|
14754
14958
|
function readJsonFile(path2) {
|
|
14755
14959
|
let raw;
|
|
14756
14960
|
try {
|
|
14757
|
-
raw =
|
|
14961
|
+
raw = readFileSync5(path2, "utf8");
|
|
14758
14962
|
} catch (err) {
|
|
14759
14963
|
if (err.code === "ENOENT") return null;
|
|
14760
14964
|
process.stderr.write(`[config] readJsonFile: unexpected read error for ${path2}: ${err.message}
|
|
@@ -14777,7 +14981,7 @@ function readJsonFile(path2) {
|
|
|
14777
14981
|
}
|
|
14778
14982
|
}
|
|
14779
14983
|
function writeJsonFile(path2, data) {
|
|
14780
|
-
|
|
14984
|
+
mkdirSync5(dirname6(path2), { recursive: true, mode: 448 });
|
|
14781
14985
|
if (path2 === CONFIG_PATH) {
|
|
14782
14986
|
try {
|
|
14783
14987
|
backupUserData(DATA_DIR, "pre-config-write");
|
|
@@ -14811,7 +15015,7 @@ function readAll() {
|
|
|
14811
15015
|
function quarantineMalformedConfig(parseErr) {
|
|
14812
15016
|
const corrupt = `${CONFIG_PATH}.corrupt-${Date.now()}`;
|
|
14813
15017
|
try {
|
|
14814
|
-
if (
|
|
15018
|
+
if (existsSync6(CONFIG_PATH)) renameWithRetrySync(CONFIG_PATH, corrupt);
|
|
14815
15019
|
} catch {
|
|
14816
15020
|
}
|
|
14817
15021
|
process.stderr.write(
|
|
@@ -14833,7 +15037,7 @@ function restoreAllForRmWOrThrow(reason) {
|
|
|
14833
15037
|
function readAllForRmW() {
|
|
14834
15038
|
let raw;
|
|
14835
15039
|
try {
|
|
14836
|
-
raw =
|
|
15040
|
+
raw = readFileSync5(CONFIG_PATH, "utf8");
|
|
14837
15041
|
} catch (err) {
|
|
14838
15042
|
if (err.code === "ENOENT") {
|
|
14839
15043
|
if (hasUserDataInitMarker(DATA_DIR)) {
|
|
@@ -17545,9 +17749,9 @@ import { useCallback as useCallback5 } from "react";
|
|
|
17545
17749
|
|
|
17546
17750
|
// src/tui/prompt-history-store.mjs
|
|
17547
17751
|
import { createHash as createHash2 } from "node:crypto";
|
|
17548
|
-
import { chmodSync, existsSync as
|
|
17752
|
+
import { chmodSync, existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
17549
17753
|
import { chmod, mkdir, rename, writeFile } from "node:fs/promises";
|
|
17550
|
-
import { dirname as
|
|
17754
|
+
import { dirname as dirname7, join as join7, resolve as resolve4 } from "node:path";
|
|
17551
17755
|
var PROMPT_HISTORY_LIMIT2 = 50;
|
|
17552
17756
|
function promptHistoryKey2(value) {
|
|
17553
17757
|
return String(value || "").trim().replace(/\s+/g, " ");
|
|
@@ -17562,12 +17766,12 @@ function historyFilePath(cwd) {
|
|
|
17562
17766
|
const key = promptHistoryCwdKey(cwd);
|
|
17563
17767
|
if (!key) return "";
|
|
17564
17768
|
const digest = createHash2("sha256").update(key, "utf8").digest("hex").slice(0, 32);
|
|
17565
|
-
return
|
|
17769
|
+
return join7(resolvePluginData(), "tui-prompt-history", `${digest}.json`);
|
|
17566
17770
|
}
|
|
17567
17771
|
function readEntries(filePath) {
|
|
17568
|
-
if (!filePath || !
|
|
17772
|
+
if (!filePath || !existsSync7(filePath)) return [];
|
|
17569
17773
|
try {
|
|
17570
|
-
const parsed = JSON.parse(
|
|
17774
|
+
const parsed = JSON.parse(readFileSync6(filePath, "utf8"));
|
|
17571
17775
|
const entries = Array.isArray(parsed?.entries) ? parsed.entries : [];
|
|
17572
17776
|
return entries.map((entry) => String(entry || "").trim()).filter((entry) => promptHistoryKey2(entry));
|
|
17573
17777
|
} catch {
|
|
@@ -17581,9 +17785,9 @@ function buildPayload(entries) {
|
|
|
17581
17785
|
function writeEntriesSync(filePath, entries) {
|
|
17582
17786
|
if (!filePath) return false;
|
|
17583
17787
|
try {
|
|
17584
|
-
|
|
17788
|
+
mkdirSync6(dirname7(filePath), { recursive: true, mode: 448 });
|
|
17585
17789
|
const tmp = `${filePath}.${process.pid}.tmp`;
|
|
17586
|
-
|
|
17790
|
+
writeFileSync5(tmp, buildPayload(entries), { encoding: "utf8", mode: 384 });
|
|
17587
17791
|
renameSync3(tmp, filePath);
|
|
17588
17792
|
try {
|
|
17589
17793
|
chmodSync(filePath, 384);
|
|
@@ -17597,7 +17801,7 @@ function writeEntriesSync(filePath, entries) {
|
|
|
17597
17801
|
async function writeEntriesAsync(filePath, entries) {
|
|
17598
17802
|
if (!filePath) return false;
|
|
17599
17803
|
try {
|
|
17600
|
-
await mkdir(
|
|
17804
|
+
await mkdir(dirname7(filePath), { recursive: true, mode: 448 });
|
|
17601
17805
|
const tmp = `${filePath}.${process.pid}.tmp`;
|
|
17602
17806
|
await writeFile(tmp, buildPayload(entries), { encoding: "utf8", mode: 384 });
|
|
17603
17807
|
await rename(tmp, filePath);
|
|
@@ -17635,16 +17839,16 @@ function reconcileWithDisk(filePath, pend) {
|
|
|
17635
17839
|
function scheduleWriteBehind(filePath) {
|
|
17636
17840
|
if (!filePath) return;
|
|
17637
17841
|
if (pendingTimers.has(filePath)) clearTimeout(pendingTimers.get(filePath));
|
|
17638
|
-
const
|
|
17842
|
+
const timer2 = setTimeout(() => {
|
|
17639
17843
|
void writeBehindFlush(filePath);
|
|
17640
17844
|
}, WRITE_BEHIND_MS);
|
|
17641
|
-
if (typeof
|
|
17642
|
-
pendingTimers.set(filePath,
|
|
17845
|
+
if (typeof timer2.unref === "function") timer2.unref();
|
|
17846
|
+
pendingTimers.set(filePath, timer2);
|
|
17643
17847
|
}
|
|
17644
17848
|
async function writeBehindFlush(filePath) {
|
|
17645
|
-
const
|
|
17646
|
-
if (
|
|
17647
|
-
clearTimeout(
|
|
17849
|
+
const timer2 = pendingTimers.get(filePath);
|
|
17850
|
+
if (timer2) {
|
|
17851
|
+
clearTimeout(timer2);
|
|
17648
17852
|
pendingTimers.delete(filePath);
|
|
17649
17853
|
}
|
|
17650
17854
|
const pend = pendingAppends.get(filePath);
|
|
@@ -17660,7 +17864,7 @@ async function writeBehindFlush(filePath) {
|
|
|
17660
17864
|
}
|
|
17661
17865
|
}
|
|
17662
17866
|
function flushPromptHistory() {
|
|
17663
|
-
for (const
|
|
17867
|
+
for (const timer2 of pendingTimers.values()) clearTimeout(timer2);
|
|
17664
17868
|
pendingTimers.clear();
|
|
17665
17869
|
for (const [filePath, pend] of pendingAppends) {
|
|
17666
17870
|
if (!pend.length) continue;
|
|
@@ -18170,7 +18374,7 @@ function NoticeMessage({ text, tone, columns = 80 }) {
|
|
|
18170
18374
|
}
|
|
18171
18375
|
|
|
18172
18376
|
// src/tui/components/ToolExecution.jsx
|
|
18173
|
-
import React16
|
|
18377
|
+
import React16 from "react";
|
|
18174
18378
|
import { Box as Box14, Text as Text16 } from "../../../vendor/ink/build/index.js";
|
|
18175
18379
|
import stringWidth9 from "string-width";
|
|
18176
18380
|
|
|
@@ -18641,15 +18845,12 @@ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
|
18641
18845
|
var TOOL_BLINK_MS = 500;
|
|
18642
18846
|
var TOOL_BLINK_LIMIT_MS = 3e3;
|
|
18643
18847
|
var TOOL_PENDING_SHOW_DELAY_MS = 1e3;
|
|
18848
|
+
var TOOL_ANIM_TICK_MS = TOOL_BLINK_MS;
|
|
18644
18849
|
function statusCopy(name, label, count, doneCount, pending, isError, args = {}) {
|
|
18645
18850
|
return formatToolActionHeader(name, args, { pending, count });
|
|
18646
18851
|
}
|
|
18647
18852
|
function ToolExecution({ name, args, result, rawResult, isError, errorCount, expanded, columns = 80, attached = false, count = 1, completedCount = 0, startedAt = 0, completedAt = 0, aggregate = false, categories = {}, doneCategories = null, headerFinalized = true, deferredDisplayReady = false }) {
|
|
18648
18853
|
const rowWidth = Math.max(1, Number(columns || 80));
|
|
18649
|
-
const [blinkOn, setBlinkOn] = useState7(true);
|
|
18650
|
-
const [blinkExpired, setBlinkExpired] = useState7(false);
|
|
18651
|
-
const [pendingDelayElapsed, setPendingDelayElapsed] = useState7(false);
|
|
18652
|
-
const [, setElapsedTick] = useState7(0);
|
|
18653
18854
|
const groupCount = Math.max(1, Number(count || 1));
|
|
18654
18855
|
const doneCount = Math.max(0, Math.min(groupCount, Number(completedCount || (result == null ? 0 : groupCount))));
|
|
18655
18856
|
const rt = result == null ? null : String(result).replace(/\s+$/, "");
|
|
@@ -18657,13 +18858,19 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, exp
|
|
|
18657
18858
|
const pending = doneCount < groupCount;
|
|
18658
18859
|
const startedAtMs = Number(startedAt || 0);
|
|
18659
18860
|
const completedAtMs = Number(completedAt || 0);
|
|
18660
|
-
const
|
|
18861
|
+
const nowMs = Date.now();
|
|
18862
|
+
useSharedTick(TOOL_ANIM_TICK_MS, pending);
|
|
18863
|
+
const pendingAgeMs = pending && startedAtMs ? Math.max(0, nowMs - startedAtMs) : 0;
|
|
18864
|
+
const pendingDelayElapsed = pending ? !startedAtMs || pendingAgeMs >= TOOL_PENDING_SHOW_DELAY_MS : false;
|
|
18661
18865
|
const hasVisibleProgress = doneCount > 0 || Boolean(String(rt || "").trim());
|
|
18662
18866
|
const pendingDisplayReady = !pending || !startedAtMs || pendingDelayElapsed || pendingAgeMs >= TOOL_PENDING_SHOW_DELAY_MS || hasVisibleProgress || deferredDisplayReady;
|
|
18867
|
+
const blinkActive = pending && pendingDisplayReady;
|
|
18868
|
+
const blinkExpired = blinkActive && startedAtMs > 0 && nowMs - startedAtMs >= TOOL_BLINK_LIMIT_MS;
|
|
18869
|
+
const blinkOn = !blinkActive || blinkExpired ? true : Math.floor(nowMs / TOOL_BLINK_MS) % 2 === 0;
|
|
18663
18870
|
const headerPending = pending || headerFinalized === false;
|
|
18664
18871
|
const hasResult = result != null && Boolean(String(rt || "").trim());
|
|
18665
18872
|
const hasRawResult = rawResult != null && Boolean(String(rawRt || "").trim());
|
|
18666
|
-
const elapsedMs = startedAtMs ? Math.max(0, (pending ?
|
|
18873
|
+
const elapsedMs = startedAtMs ? Math.max(0, (pending ? nowMs : completedAtMs || nowMs) - startedAtMs) : 0;
|
|
18667
18874
|
const elapsed = elapsedMs >= 1e3 ? formatElapsed(elapsedMs) : "";
|
|
18668
18875
|
const failedCount = clampFailureCount(errorCount, groupCount, isError);
|
|
18669
18876
|
const displayGroupCount = groupCount;
|
|
@@ -18673,53 +18880,6 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, exp
|
|
|
18673
18880
|
(v) => (v && typeof v === "object" ? Number(v.count || 0) : Number(v || 0)) > 0
|
|
18674
18881
|
);
|
|
18675
18882
|
const displayDoneCategories = hasDoneCounts ? normalizedDoneCategories : displayCategories;
|
|
18676
|
-
useEffect9(() => {
|
|
18677
|
-
if (!pending) {
|
|
18678
|
-
setPendingDelayElapsed(false);
|
|
18679
|
-
return void 0;
|
|
18680
|
-
}
|
|
18681
|
-
const started = Number(startedAt || 0);
|
|
18682
|
-
if (!started) {
|
|
18683
|
-
setPendingDelayElapsed(true);
|
|
18684
|
-
return void 0;
|
|
18685
|
-
}
|
|
18686
|
-
const remaining = TOOL_PENDING_SHOW_DELAY_MS - Math.max(0, Date.now() - started);
|
|
18687
|
-
if (remaining <= 0) {
|
|
18688
|
-
setPendingDelayElapsed(true);
|
|
18689
|
-
return void 0;
|
|
18690
|
-
}
|
|
18691
|
-
setPendingDelayElapsed(false);
|
|
18692
|
-
const timer = setTimeout(() => setPendingDelayElapsed(true), remaining);
|
|
18693
|
-
return () => clearTimeout(timer);
|
|
18694
|
-
}, [pending, startedAt]);
|
|
18695
|
-
useEffect9(() => {
|
|
18696
|
-
if (!pending || !pendingDisplayReady || blinkExpired) {
|
|
18697
|
-
setBlinkOn(true);
|
|
18698
|
-
return void 0;
|
|
18699
|
-
}
|
|
18700
|
-
const timer = setInterval(() => setBlinkOn((on) => !on), TOOL_BLINK_MS);
|
|
18701
|
-
return () => clearInterval(timer);
|
|
18702
|
-
}, [pending, pendingDisplayReady, blinkExpired]);
|
|
18703
|
-
useEffect9(() => {
|
|
18704
|
-
if (!pending || !pendingDisplayReady) {
|
|
18705
|
-
setBlinkExpired(false);
|
|
18706
|
-
return void 0;
|
|
18707
|
-
}
|
|
18708
|
-
const started = Number(startedAt || 0);
|
|
18709
|
-
const remaining = TOOL_BLINK_LIMIT_MS - (started ? Math.max(0, Date.now() - started) : 0);
|
|
18710
|
-
if (remaining <= 0) {
|
|
18711
|
-
setBlinkExpired(true);
|
|
18712
|
-
return void 0;
|
|
18713
|
-
}
|
|
18714
|
-
setBlinkExpired(false);
|
|
18715
|
-
const timer = setTimeout(() => setBlinkExpired(true), remaining);
|
|
18716
|
-
return () => clearTimeout(timer);
|
|
18717
|
-
}, [pending, pendingDisplayReady, startedAt]);
|
|
18718
|
-
useEffect9(() => {
|
|
18719
|
-
if (!pending || !pendingDisplayReady || !startedAtMs) return void 0;
|
|
18720
|
-
const timer = setInterval(() => setElapsedTick((tick) => (tick + 1) % 1e6), 1e3);
|
|
18721
|
-
return () => clearInterval(timer);
|
|
18722
|
-
}, [pending, pendingDisplayReady, startedAtMs]);
|
|
18723
18883
|
if (pending && !pendingDisplayReady) {
|
|
18724
18884
|
const placeholderNormalizedName = String(formatToolSurface(name, args)?.normalizedName || "").toLowerCase();
|
|
18725
18885
|
const placeholderSingleRow = !aggregate && (SKILL_SURFACE_NAMES2.has(placeholderNormalizedName) || isAgentTool(placeholderNormalizedName));
|
|
@@ -18841,7 +19001,9 @@ function ToolExecution({ name, args, result, rawResult, isError, errorCount, exp
|
|
|
18841
19001
|
const finalStatusColor = toolStatusColor({ pending, groupCount, failedCount, terminalStatus });
|
|
18842
19002
|
const dotColor = finalStatusColor;
|
|
18843
19003
|
const markerGlyph = isAgentResponse ? AGENT_RESPONSE_MARKER : isAgentSurfaceCard ? AGENT_CALL_MARKER : TURN_MARKER;
|
|
18844
|
-
const
|
|
19004
|
+
const isDirectionalMarker = isAgentResponse || isAgentSurfaceCard;
|
|
19005
|
+
const markerText = isDirectionalMarker ? `${markerGlyph} ` : markerGlyph;
|
|
19006
|
+
const dotText = pending && !blinkExpired && !blinkOn ? " " : markerText;
|
|
18845
19007
|
let labelText;
|
|
18846
19008
|
if (isAgentResponse) labelText = agentResponseTitle(parsedArgs);
|
|
18847
19009
|
else if (isBackgroundResponse) labelText = backgroundTaskResultTitle(normalizedName, backgroundMeta || parsedArgs);
|
|
@@ -19128,7 +19290,7 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19128
19290
|
const { stdout } = useStdout2();
|
|
19129
19291
|
const [exiting, setExiting] = useState8(false);
|
|
19130
19292
|
const [tuiReady, setTuiReady] = useState8(false);
|
|
19131
|
-
const exitRequestedRef =
|
|
19293
|
+
const exitRequestedRef = useRef10(false);
|
|
19132
19294
|
const [resizeState, setResizeState] = useState8(() => ({ ...terminalSize(stdout), epoch: 0 }));
|
|
19133
19295
|
const [panelTransitionEpoch, setPanelTransitionEpoch] = useState8(0);
|
|
19134
19296
|
const [panelInkMaskEpoch, setPanelInkMaskEpoch] = useState8(0);
|
|
@@ -19136,22 +19298,22 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19136
19298
|
const rightSafetyColumns = windowsLikeTerminal ? 1 : 0;
|
|
19137
19299
|
const frameColumns = Math.max(1, resizeState.columns - rightSafetyColumns);
|
|
19138
19300
|
const [scrollOffset, setScrollOffset] = useState8(0);
|
|
19139
|
-
const scrollPositionRef =
|
|
19140
|
-
const scrollTargetRef =
|
|
19141
|
-
const maxScrollRowsRef =
|
|
19142
|
-
const transcriptBottomSlackRowsRef =
|
|
19143
|
-
const transcriptAnchorRef =
|
|
19144
|
-
const transcriptAnchorDirtyRef =
|
|
19145
|
-
const transcriptGeomRef =
|
|
19301
|
+
const scrollPositionRef = useRef10(0);
|
|
19302
|
+
const scrollTargetRef = useRef10(0);
|
|
19303
|
+
const maxScrollRowsRef = useRef10(0);
|
|
19304
|
+
const transcriptBottomSlackRowsRef = useRef10(0);
|
|
19305
|
+
const transcriptAnchorRef = useRef10(null);
|
|
19306
|
+
const transcriptAnchorDirtyRef = useRef10(false);
|
|
19307
|
+
const transcriptGeomRef = useRef10({ prefixRows: null, totalRows: 0, viewRows: 1 });
|
|
19146
19308
|
const [measuredRowsVersion, setMeasuredRowsVersion] = useState8(0);
|
|
19147
|
-
const followingRef =
|
|
19148
|
-
const lastItemsCountRef =
|
|
19149
|
-
const pickerOpenedFromEnterRef =
|
|
19150
|
-
const pickerOpenedFromEnterTimerRef =
|
|
19151
|
-
const projectPickerRef =
|
|
19309
|
+
const followingRef = useRef10(false);
|
|
19310
|
+
const lastItemsCountRef = useRef10(0);
|
|
19311
|
+
const pickerOpenedFromEnterRef = useRef10(false);
|
|
19312
|
+
const pickerOpenedFromEnterTimerRef = useRef10(null);
|
|
19313
|
+
const projectPickerRef = useRef10(null);
|
|
19152
19314
|
const buildProjectPickerState = (opts) => projectPickerRef.current.buildProjectPickerState(opts);
|
|
19153
19315
|
const [picker, setPickerState] = useState8(null);
|
|
19154
|
-
const livePickerRef =
|
|
19316
|
+
const livePickerRef = useRef10(null);
|
|
19155
19317
|
const setPicker = useCallback6((next) => {
|
|
19156
19318
|
livePickerRef.current = typeof next === "function" ? next(livePickerRef.current) : next;
|
|
19157
19319
|
setPickerState((prev) => {
|
|
@@ -19173,14 +19335,14 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19173
19335
|
livePickerRef.current = picker;
|
|
19174
19336
|
const [contextPanel, setContextPanel] = useState8(null);
|
|
19175
19337
|
const [usagePanel, setUsagePanel] = useState8(null);
|
|
19176
|
-
const usageRequestRef =
|
|
19177
|
-
const settingsHeavyCacheRef =
|
|
19338
|
+
const usageRequestRef = useRef10(0);
|
|
19339
|
+
const settingsHeavyCacheRef = useRef10(null);
|
|
19178
19340
|
const closeUsagePanel = useCallback6(() => {
|
|
19179
19341
|
usageRequestRef.current += 1;
|
|
19180
19342
|
setUsagePanel(null);
|
|
19181
19343
|
}, []);
|
|
19182
19344
|
const [providerPrompt, setProviderPrompt] = useState8(null);
|
|
19183
|
-
const oauthSubmitRef =
|
|
19345
|
+
const oauthSubmitRef = useRef10(false);
|
|
19184
19346
|
const [channelPrompt, setChannelPrompt] = useState8(null);
|
|
19185
19347
|
const [hookPrompt, setHookPrompt] = useState8(null);
|
|
19186
19348
|
const [settingsPrompt, setSettingsPrompt] = useState8(null);
|
|
@@ -19202,7 +19364,7 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19202
19364
|
pickFolder
|
|
19203
19365
|
});
|
|
19204
19366
|
projectPickerRef.current = projectPicker;
|
|
19205
|
-
const initialPickerBuiltRef =
|
|
19367
|
+
const initialPickerBuiltRef = useRef10(false);
|
|
19206
19368
|
if (!initialPickerBuiltRef.current) {
|
|
19207
19369
|
initialPickerBuiltRef.current = true;
|
|
19208
19370
|
let onboardingOwnsScreen = false;
|
|
@@ -19310,30 +19472,30 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19310
19472
|
const toolApproval = state.toolApproval || null;
|
|
19311
19473
|
const [promptDraft, setPromptDraft] = useState8("");
|
|
19312
19474
|
const [promptDraftOverride, setPromptDraftOverride] = useState8(null);
|
|
19313
|
-
const promptLayoutValueRef =
|
|
19475
|
+
const promptLayoutValueRef = useRef10("");
|
|
19314
19476
|
const [, setPromptLayoutRows] = useState8(1);
|
|
19315
19477
|
const [textEntryLayoutRows, setTextEntryLayoutRows] = useState8(1);
|
|
19316
19478
|
const [, setPastedImages] = useState8({});
|
|
19317
|
-
const pastedImagesRef =
|
|
19318
|
-
const nextPastedImageIdRef =
|
|
19479
|
+
const pastedImagesRef = useRef10({});
|
|
19480
|
+
const nextPastedImageIdRef = useRef10(1);
|
|
19319
19481
|
const [, setPastedTexts] = useState8({});
|
|
19320
|
-
const pastedTextsRef =
|
|
19321
|
-
const nextPastedTextIdRef =
|
|
19322
|
-
const promptValueRef =
|
|
19323
|
-
const promptSelectionRef =
|
|
19324
|
-
const promptBoxRectRef =
|
|
19325
|
-
const promptMouseSelectionRef =
|
|
19326
|
-
const promptHistoryNavRef =
|
|
19327
|
-
const promptHistoryDraftChangeRef =
|
|
19482
|
+
const pastedTextsRef = useRef10({});
|
|
19483
|
+
const nextPastedTextIdRef = useRef10(1);
|
|
19484
|
+
const promptValueRef = useRef10("");
|
|
19485
|
+
const promptSelectionRef = useRef10(null);
|
|
19486
|
+
const promptBoxRectRef = useRef10(null);
|
|
19487
|
+
const promptMouseSelectionRef = useRef10(null);
|
|
19488
|
+
const promptHistoryNavRef = useRef10({ active: false, index: -1, seed: "", lastValue: "" });
|
|
19489
|
+
const promptHistoryDraftChangeRef = useRef10(false);
|
|
19328
19490
|
const [promptHint, setPromptHint] = useState8("");
|
|
19329
19491
|
const [promptHintTone, setPromptHintTone] = useState8("info");
|
|
19330
19492
|
const [welcomePromptHintDismissed, setWelcomePromptHintDismissed] = useState8(false);
|
|
19331
19493
|
const [conditionalWelcomePromptHint, setConditionalWelcomePromptHint] = useState8("");
|
|
19332
|
-
const welcomePromptHintRef =
|
|
19494
|
+
const welcomePromptHintRef = useRef10(null);
|
|
19333
19495
|
if (welcomePromptHintRef.current === null) {
|
|
19334
19496
|
welcomePromptHintRef.current = randomWelcomePromptHint();
|
|
19335
19497
|
}
|
|
19336
|
-
const welcomePromptHintVisibleRef =
|
|
19498
|
+
const welcomePromptHintVisibleRef = useRef10(false);
|
|
19337
19499
|
const dismissWelcomePromptHint = useCallback6(() => {
|
|
19338
19500
|
if (!welcomePromptHintVisibleRef.current) return;
|
|
19339
19501
|
setWelcomePromptHintDismissed((dismissed) => dismissed || true);
|
|
@@ -19341,15 +19503,15 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19341
19503
|
const toastErrorSignature = useMemo2(() => (state.toasts || []).filter((toast) => toast?.tone === "error").map((toast) => `${toast.id || ""}:${toast.text || ""}`).join("|"), [state.toasts]);
|
|
19342
19504
|
const [slashIndex, setSlashIndex] = useState8(0);
|
|
19343
19505
|
const [slashDismissedFor, setSlashDismissedFor] = useState8("");
|
|
19344
|
-
const slashPaletteRef =
|
|
19345
|
-
const workflowTabCycleRef =
|
|
19346
|
-
const scrollFocusRef =
|
|
19347
|
-
const onboardingStartedRef =
|
|
19348
|
-
const onboardingRef =
|
|
19349
|
-
const providerModelsCacheRef =
|
|
19350
|
-
const searchModelsCacheRef =
|
|
19351
|
-
const modelPickerRequestRef =
|
|
19352
|
-
const onboardingPrefetchSeqRef =
|
|
19506
|
+
const slashPaletteRef = useRef10({ open: false, count: 0 });
|
|
19507
|
+
const workflowTabCycleRef = useRef10({ pending: false, lastAt: 0 });
|
|
19508
|
+
const scrollFocusRef = useRef10({});
|
|
19509
|
+
const onboardingStartedRef = useRef10(false);
|
|
19510
|
+
const onboardingRef = useRef10({ defaultRoute: null, searchRoute: null, agentRoutes: {}, agents: [], providerModels: [] });
|
|
19511
|
+
const providerModelsCacheRef = useRef10({ models: null, at: 0 });
|
|
19512
|
+
const searchModelsCacheRef = useRef10({ models: null, at: 0 });
|
|
19513
|
+
const modelPickerRequestRef = useRef10(0);
|
|
19514
|
+
const onboardingPrefetchSeqRef = useRef10(0);
|
|
19353
19515
|
const clearModelCaches = useCallback6((scope = "all") => {
|
|
19354
19516
|
if (scope === "all" || scope === "provider") {
|
|
19355
19517
|
providerModelsCacheRef.current = { models: null, at: 0 };
|
|
@@ -19514,14 +19676,14 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19514
19676
|
runDoctor: (...a) => store.runDoctor?.(...a),
|
|
19515
19677
|
requestExit: (...a) => requestExit(...a)
|
|
19516
19678
|
});
|
|
19517
|
-
const promptHintTimerRef =
|
|
19518
|
-
const promptHintActiveRef =
|
|
19519
|
-
const dragRef =
|
|
19520
|
-
const transcriptViewportRef =
|
|
19521
|
-
const panelTransitionRef =
|
|
19522
|
-
const panelCloseInkMaskRowsRef =
|
|
19523
|
-
const projectBootInputLatchRef =
|
|
19524
|
-
const frameRowsRef =
|
|
19679
|
+
const promptHintTimerRef = useRef10(null);
|
|
19680
|
+
const promptHintActiveRef = useRef10(false);
|
|
19681
|
+
const dragRef = useRef10({ anchor: null, anchorScroll: 0, last: null, active: false, rect: null, region: null, anchorSpan: null });
|
|
19682
|
+
const transcriptViewportRef = useRef10({ top: 0, bottom: 0 });
|
|
19683
|
+
const panelTransitionRef = useRef10({ signature: "", reserve: 0, clearRows: 0, guardRows: 0, epoch: 0 });
|
|
19684
|
+
const panelCloseInkMaskRowsRef = useRef10(0);
|
|
19685
|
+
const projectBootInputLatchRef = useRef10(false);
|
|
19686
|
+
const frameRowsRef = useRef10(24);
|
|
19525
19687
|
const STATUSLINE_BAND_ROWS = 3;
|
|
19526
19688
|
const promptContentColumns = Math.max(1, frameColumns - 4);
|
|
19527
19689
|
const syncPromptLayoutRows = useCallback6((value) => {
|
|
@@ -19598,9 +19760,9 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19598
19760
|
alive = false;
|
|
19599
19761
|
};
|
|
19600
19762
|
}, [store, state.provider, state.model, state.workflow?.id, toastErrorSignature]);
|
|
19601
|
-
const selectionLayoutRef =
|
|
19602
|
-
const selectionTextRef =
|
|
19603
|
-
const lastClickRef =
|
|
19763
|
+
const selectionLayoutRef = useRef10(null);
|
|
19764
|
+
const selectionTextRef = useRef10("");
|
|
19765
|
+
const lastClickRef = useRef10({ x: -1, y: -1, t: 0, count: 0 });
|
|
19604
19766
|
const showSelectionCopyHint = useCallback6((text, tone = "plain") => {
|
|
19605
19767
|
if (promptHintTimerRef.current) clearTimeout(promptHintTimerRef.current);
|
|
19606
19768
|
promptHintActiveRef.current = true;
|
|
@@ -19614,8 +19776,8 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19614
19776
|
}, 2200);
|
|
19615
19777
|
}, []);
|
|
19616
19778
|
useEffect10(() => {
|
|
19617
|
-
const
|
|
19618
|
-
return () => clearTimeout(
|
|
19779
|
+
const timer2 = setTimeout(() => setTuiReady(true), 0);
|
|
19780
|
+
return () => clearTimeout(timer2);
|
|
19619
19781
|
}, []);
|
|
19620
19782
|
useEffect10(() => {
|
|
19621
19783
|
if (!stdout) return void 0;
|
|
@@ -19868,14 +20030,14 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
19868
20030
|
}, 2e3);
|
|
19869
20031
|
hardExitTimer.unref?.();
|
|
19870
20032
|
setTimeout(() => {
|
|
19871
|
-
let
|
|
20033
|
+
let timer2 = null;
|
|
19872
20034
|
Promise.race([
|
|
19873
20035
|
Promise.resolve(store.dispose?.("cli-react-exit", { detach: true })),
|
|
19874
20036
|
new Promise((resolve5) => {
|
|
19875
|
-
|
|
20037
|
+
timer2 = setTimeout(resolve5, 350);
|
|
19876
20038
|
})
|
|
19877
20039
|
]).finally(() => {
|
|
19878
|
-
if (
|
|
20040
|
+
if (timer2) clearTimeout(timer2);
|
|
19879
20041
|
exit();
|
|
19880
20042
|
});
|
|
19881
20043
|
}, 60);
|
|
@@ -21106,8 +21268,8 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
21106
21268
|
return void 0;
|
|
21107
21269
|
}
|
|
21108
21270
|
if (!hadTransitionClearance) return void 0;
|
|
21109
|
-
const
|
|
21110
|
-
return () => clearTimeout(
|
|
21271
|
+
const timer2 = setTimeout(() => setPanelTransitionEpoch((epoch) => epoch + 1), 0);
|
|
21272
|
+
return () => clearTimeout(timer2);
|
|
21111
21273
|
}, [panelLayoutSignature, bottomClusterRows, panelTransitionClearRows, panelTransitionGuardRows]);
|
|
21112
21274
|
useEffect10(() => {
|
|
21113
21275
|
panelTransitionRef.current.tailId = latestTranscriptItem?.id ?? null;
|
|
@@ -21244,7 +21406,7 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
21244
21406
|
/* @__PURE__ */ jsx20(Text20, { color: theme.logo ?? theme.claude, bold: true, children: centerLine("\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551", frameColumns) }),
|
|
21245
21407
|
/* @__PURE__ */ jsx20(Text20, { color: theme.logo ?? theme.claude, bold: true, children: centerLine("\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", frameColumns) }),
|
|
21246
21408
|
/* @__PURE__ */ jsx20(Box18, { height: 1, flexShrink: 0 }),
|
|
21247
|
-
/* @__PURE__ */ jsx20(Text20, { color: theme.inactive, children: centerLine(`mixdog coding agent \xB7 ${state.cwd}`, frameColumns, 4) })
|
|
21409
|
+
/* @__PURE__ */ jsx20(Text20, { color: theme.inactive, children: centerLine(`mixdog coding agent \xB7 v${localPackageVersion()} \xB7 ${state.cwd}`, frameColumns, 4) })
|
|
21248
21410
|
] }) : null,
|
|
21249
21411
|
/* @__PURE__ */ jsxs16(
|
|
21250
21412
|
Box18,
|
|
@@ -22470,7 +22632,9 @@ function resolveTuiRuntimeNotificationDelivery(event, text) {
|
|
|
22470
22632
|
const parsed = parseAgentJob(trimmed);
|
|
22471
22633
|
const meta = event?.meta && typeof event.meta === "object" ? event.meta : {};
|
|
22472
22634
|
if (meta.kind === "update-notice") {
|
|
22473
|
-
|
|
22635
|
+
const ver = String(meta.version || "").trim();
|
|
22636
|
+
const displayText = ver ? `mixdog v${ver} ready \u2014 restart to apply.` : trimmed;
|
|
22637
|
+
return { action: "notice", displayText, tone: meta.tone === "warn" ? "warn" : "info" };
|
|
22474
22638
|
}
|
|
22475
22639
|
if (!isExecutionNotification(event, trimmed, parsed)) {
|
|
22476
22640
|
return { action: "enqueue", displayText: trimmed, modelContent: trimmed };
|
|
@@ -23011,7 +23175,7 @@ function createAgentJobFeed({
|
|
|
23011
23175
|
|
|
23012
23176
|
// src/tui/engine/tui-steering-persist.mjs
|
|
23013
23177
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
23014
|
-
import { join as
|
|
23178
|
+
import { join as join8 } from "path";
|
|
23015
23179
|
var PENDING_MESSAGES_FILE = "session-pending-messages.json";
|
|
23016
23180
|
var PENDING_MESSAGES_MODE = 384;
|
|
23017
23181
|
var _persistChain = Promise.resolve();
|
|
@@ -23022,7 +23186,7 @@ function _serialize(task) {
|
|
|
23022
23186
|
return run;
|
|
23023
23187
|
}
|
|
23024
23188
|
function pendingMessagesPath() {
|
|
23025
|
-
return
|
|
23189
|
+
return join8(resolvePluginData(), PENDING_MESSAGES_FILE);
|
|
23026
23190
|
}
|
|
23027
23191
|
function tuiSteeringSessionKey(leadSessionId) {
|
|
23028
23192
|
if (typeof leadSessionId !== "string" || !/^[A-Za-z0-9_-]+$/.test(leadSessionId)) return null;
|
|
@@ -23581,9 +23745,9 @@ function createSessionFlow(bag) {
|
|
|
23581
23745
|
}
|
|
23582
23746
|
if (compactType) {
|
|
23583
23747
|
const clearPromise = runtime.clear({ compactType, requireCompactSuccess: true });
|
|
23584
|
-
let
|
|
23748
|
+
let timer2 = null;
|
|
23585
23749
|
const timeout = new Promise((_, reject) => {
|
|
23586
|
-
|
|
23750
|
+
timer2 = setTimeout(
|
|
23587
23751
|
() => reject(new Error(`compaction timed out after ${AUTO_CLEAR_COMPACT_TIMEOUT_MS}ms; auto-clear deferred to next idle`)),
|
|
23588
23752
|
AUTO_CLEAR_COMPACT_TIMEOUT_MS
|
|
23589
23753
|
);
|
|
@@ -23608,7 +23772,7 @@ function createSessionFlow(bag) {
|
|
|
23608
23772
|
});
|
|
23609
23773
|
throw raceError;
|
|
23610
23774
|
} finally {
|
|
23611
|
-
if (
|
|
23775
|
+
if (timer2) clearTimeout(timer2);
|
|
23612
23776
|
}
|
|
23613
23777
|
} else {
|
|
23614
23778
|
await runtime.clear({});
|
|
@@ -25052,52 +25216,8 @@ function createEngineApiB(bag) {
|
|
|
25052
25216
|
};
|
|
25053
25217
|
}
|
|
25054
25218
|
|
|
25055
|
-
// src/runtime/shared/update-checker.mjs
|
|
25056
|
-
import { dirname as dirname7, join as join8 } from "node:path";
|
|
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
|
|
25070
|
-
var PACKAGE_NAME = "mixdog";
|
|
25071
|
-
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
25072
|
-
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
25073
|
-
var _MODULE_DIR = dirname7(fileURLToPath2(import.meta.url));
|
|
25074
|
-
var _PACKAGE_JSON_PATH = join8(_MODULE_DIR, "..", "..", "..", "package.json");
|
|
25075
|
-
var _PACKAGE_ROOT = dirname7(_PACKAGE_JSON_PATH);
|
|
25076
|
-
function parseSemver(value) {
|
|
25077
|
-
const text = String(value || "").trim().replace(/^v/i, "");
|
|
25078
|
-
const [core, ...preParts] = text.split("-");
|
|
25079
|
-
const parts = core.split(".").map((n) => {
|
|
25080
|
-
const num2 = Number.parseInt(n, 10);
|
|
25081
|
-
return Number.isFinite(num2) ? num2 : 0;
|
|
25082
|
-
});
|
|
25083
|
-
while (parts.length < 3) parts.push(0);
|
|
25084
|
-
return { parts, prerelease: preParts.join("-") };
|
|
25085
|
-
}
|
|
25086
|
-
function compareSemver(a, b) {
|
|
25087
|
-
const pa = parseSemver(a);
|
|
25088
|
-
const pb = parseSemver(b);
|
|
25089
|
-
for (let i = 0; i < 3; i++) {
|
|
25090
|
-
const diff = (pa.parts[i] || 0) - (pb.parts[i] || 0);
|
|
25091
|
-
if (diff !== 0) return diff;
|
|
25092
|
-
}
|
|
25093
|
-
if (pa.prerelease && !pb.prerelease) return -1;
|
|
25094
|
-
if (!pa.prerelease && pb.prerelease) return 1;
|
|
25095
|
-
if (pa.prerelease !== pb.prerelease) return pa.prerelease < pb.prerelease ? -1 : 1;
|
|
25096
|
-
return 0;
|
|
25097
|
-
}
|
|
25098
|
-
|
|
25099
25219
|
// src/tui/app/doctor.mjs
|
|
25100
|
-
import { readFileSync as
|
|
25220
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
25101
25221
|
import { dirname as dirname8, join as join9 } from "node:path";
|
|
25102
25222
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
25103
25223
|
var GLYPH = { ok: "\u2713", warn: "\u26A0", fail: "\u2717" };
|
|
@@ -25124,7 +25244,7 @@ function median(nums) {
|
|
|
25124
25244
|
function readPackageJson() {
|
|
25125
25245
|
try {
|
|
25126
25246
|
const dir = dirname8(fileURLToPath3(import.meta.url));
|
|
25127
|
-
const raw = JSON.parse(
|
|
25247
|
+
const raw = JSON.parse(readFileSync7(join9(dir, "..", "..", "..", "package.json"), "utf8"));
|
|
25128
25248
|
return raw && typeof raw === "object" ? raw : null;
|
|
25129
25249
|
} catch {
|
|
25130
25250
|
return null;
|
|
@@ -25260,7 +25380,7 @@ async function buildDoctorReport(runtime = {}, getState = () => ({})) {
|
|
|
25260
25380
|
const pgdata = join9(dataDir, "pgdata");
|
|
25261
25381
|
let writes;
|
|
25262
25382
|
try {
|
|
25263
|
-
writes = parseCheckpointWriteSeconds(
|
|
25383
|
+
writes = parseCheckpointWriteSeconds(readFileSync7(join9(dataDir, "pg.log"), "utf8"));
|
|
25264
25384
|
} catch {
|
|
25265
25385
|
row("ok", "pg.log unavailable \xB7 check skipped");
|
|
25266
25386
|
return;
|
|
@@ -26062,13 +26182,13 @@ async function createEngineSession({
|
|
|
26062
26182
|
const value = String(text ?? "").trim();
|
|
26063
26183
|
if (!value) return null;
|
|
26064
26184
|
set({ toasts: [...state.toasts.filter((toast) => toast.id !== id), { id, text: value, tone }] });
|
|
26065
|
-
const
|
|
26066
|
-
toastTimers.delete(
|
|
26185
|
+
const timer2 = setTimeout(() => {
|
|
26186
|
+
toastTimers.delete(timer2);
|
|
26067
26187
|
if (flags.disposed) return;
|
|
26068
26188
|
set({ toasts: state.toasts.filter((toast) => toast.id !== id) });
|
|
26069
26189
|
}, ttlMs);
|
|
26070
|
-
toastTimers.add(
|
|
26071
|
-
|
|
26190
|
+
toastTimers.add(timer2);
|
|
26191
|
+
timer2.unref?.();
|
|
26072
26192
|
return id;
|
|
26073
26193
|
};
|
|
26074
26194
|
const pushNotice = (text, tone = "info", options = {}) => {
|
|
@@ -26137,8 +26257,8 @@ async function createEngineSession({
|
|
|
26137
26257
|
}, 2e3);
|
|
26138
26258
|
lifecycle.runtimePulseTimer.unref?.();
|
|
26139
26259
|
function clearToastTimers() {
|
|
26140
|
-
for (const
|
|
26141
|
-
clearTimeout(
|
|
26260
|
+
for (const timer2 of toastTimers) {
|
|
26261
|
+
clearTimeout(timer2);
|
|
26142
26262
|
}
|
|
26143
26263
|
toastTimers.clear();
|
|
26144
26264
|
}
|
|
@@ -26255,21 +26375,21 @@ function waitWithTimeout(promise, timeoutMs, label = "cleanup") {
|
|
|
26255
26375
|
const ms = Math.max(1, Math.floor(Number(timeoutMs) || 1));
|
|
26256
26376
|
return new Promise((resolve5, reject) => {
|
|
26257
26377
|
let settled = false;
|
|
26258
|
-
const
|
|
26378
|
+
const timer2 = setTimeout(() => {
|
|
26259
26379
|
if (settled) return;
|
|
26260
26380
|
settled = true;
|
|
26261
26381
|
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
26262
26382
|
}, ms);
|
|
26263
|
-
if (typeof
|
|
26383
|
+
if (typeof timer2.unref === "function") timer2.unref();
|
|
26264
26384
|
Promise.resolve(promise).then((value) => {
|
|
26265
26385
|
if (settled) return;
|
|
26266
26386
|
settled = true;
|
|
26267
|
-
clearTimeout(
|
|
26387
|
+
clearTimeout(timer2);
|
|
26268
26388
|
resolve5(value);
|
|
26269
26389
|
}).catch((error) => {
|
|
26270
26390
|
if (settled) return;
|
|
26271
26391
|
settled = true;
|
|
26272
|
-
clearTimeout(
|
|
26392
|
+
clearTimeout(timer2);
|
|
26273
26393
|
reject(error);
|
|
26274
26394
|
});
|
|
26275
26395
|
});
|
|
@@ -26406,7 +26526,7 @@ function installTuiLoopProbe() {
|
|
|
26406
26526
|
if (!LOOP_PROBE_ENABLED) return () => {
|
|
26407
26527
|
};
|
|
26408
26528
|
let last = performance3.now();
|
|
26409
|
-
const
|
|
26529
|
+
const timer2 = setInterval(() => {
|
|
26410
26530
|
const now = performance3.now();
|
|
26411
26531
|
const drift = now - last - LOOP_PROBE_INTERVAL_MS;
|
|
26412
26532
|
last = now;
|
|
@@ -26418,10 +26538,10 @@ function installTuiLoopProbe() {
|
|
|
26418
26538
|
}
|
|
26419
26539
|
}
|
|
26420
26540
|
}, LOOP_PROBE_INTERVAL_MS);
|
|
26421
|
-
|
|
26541
|
+
timer2.unref?.();
|
|
26422
26542
|
return () => {
|
|
26423
26543
|
try {
|
|
26424
|
-
clearInterval(
|
|
26544
|
+
clearInterval(timer2);
|
|
26425
26545
|
} catch {
|
|
26426
26546
|
}
|
|
26427
26547
|
};
|
|
@@ -26454,7 +26574,7 @@ function installTuiPerfProbe() {
|
|
|
26454
26574
|
stallMs: PERF_STALL_THRESHOLD_MS,
|
|
26455
26575
|
renderGapMs: PERF_RENDER_GAP_MS
|
|
26456
26576
|
});
|
|
26457
|
-
const
|
|
26577
|
+
const timer2 = setInterval(() => {
|
|
26458
26578
|
const now = performance3.now();
|
|
26459
26579
|
const elapsed = now - last;
|
|
26460
26580
|
const lagMs = elapsed - PERF_STALL_INTERVAL_MS;
|
|
@@ -26472,10 +26592,10 @@ function installTuiPerfProbe() {
|
|
|
26472
26592
|
heapMb: (mem.heapUsed / 1048576).toFixed(1)
|
|
26473
26593
|
});
|
|
26474
26594
|
}, PERF_STALL_INTERVAL_MS);
|
|
26475
|
-
|
|
26595
|
+
timer2.unref?.();
|
|
26476
26596
|
return () => {
|
|
26477
26597
|
try {
|
|
26478
|
-
clearInterval(
|
|
26598
|
+
clearInterval(timer2);
|
|
26479
26599
|
} catch {
|
|
26480
26600
|
}
|
|
26481
26601
|
};
|
|
@@ -26573,19 +26693,19 @@ function dumpActiveHandles(label) {
|
|
|
26573
26693
|
}
|
|
26574
26694
|
}
|
|
26575
26695
|
function waitWithTimeout2(promise, ms) {
|
|
26576
|
-
let
|
|
26696
|
+
let timer2 = null;
|
|
26577
26697
|
return Promise.race([
|
|
26578
26698
|
Promise.resolve(promise).then(() => true),
|
|
26579
26699
|
new Promise((resolve5) => {
|
|
26580
|
-
|
|
26700
|
+
timer2 = setTimeout(() => resolve5(false), ms);
|
|
26581
26701
|
})
|
|
26582
26702
|
]).finally(() => {
|
|
26583
|
-
if (
|
|
26703
|
+
if (timer2) clearTimeout(timer2);
|
|
26584
26704
|
});
|
|
26585
26705
|
}
|
|
26586
26706
|
function scheduleHardExit(code = 0) {
|
|
26587
26707
|
if (!EXIT_HARD_ENABLED) return;
|
|
26588
|
-
const
|
|
26708
|
+
const timer2 = setTimeout(() => {
|
|
26589
26709
|
dumpActiveHandles("hard-exit");
|
|
26590
26710
|
try {
|
|
26591
26711
|
process.stdout.write(`${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`);
|
|
@@ -26593,7 +26713,7 @@ function scheduleHardExit(code = 0) {
|
|
|
26593
26713
|
}
|
|
26594
26714
|
process.exit(code);
|
|
26595
26715
|
}, EXIT_HARD_DELAY_MS);
|
|
26596
|
-
|
|
26716
|
+
timer2.unref?.();
|
|
26597
26717
|
}
|
|
26598
26718
|
function resolveTuiStderrLogPath() {
|
|
26599
26719
|
return process.env.MIXDOG_TUI_STDERR_LOG || join10(process.env.MIXDOG_RUNTIME_ROOT || join10(tmpdir2(), "mixdog"), "mixdog-tui.stderr.log");
|
|
@@ -26628,7 +26748,7 @@ function paintBootSplash() {
|
|
|
26628
26748
|
`;
|
|
26629
26749
|
}
|
|
26630
26750
|
out += "\r\n";
|
|
26631
|
-
out += `${subtleFg}${center(`mixdog coding agent \xB7 ${process.cwd()}`)}${reset}`;
|
|
26751
|
+
out += `${subtleFg}${center(`mixdog coding agent \xB7 v${localPackageVersion()} \xB7 ${process.cwd()}`)}${reset}`;
|
|
26632
26752
|
out += "\x1B[H";
|
|
26633
26753
|
process.stdout.write(out);
|
|
26634
26754
|
return { stop: () => {
|
|
@@ -26678,7 +26798,7 @@ function installTuiStderrGuard() {
|
|
|
26678
26798
|
const originalWrite = process.stderr.write.bind(process.stderr);
|
|
26679
26799
|
const logPath = resolveTuiStderrLogPath();
|
|
26680
26800
|
try {
|
|
26681
|
-
|
|
26801
|
+
mkdirSync7(dirname9(logPath), { recursive: true });
|
|
26682
26802
|
} catch {
|
|
26683
26803
|
}
|
|
26684
26804
|
(0, import_mixdog_debug.rotateBoundedLog)(logPath, import_mixdog_debug.PLUGIN_LOG_MAX_BYTES, import_mixdog_debug.PLUGIN_LOG_KEEP_BYTES);
|