mixdog 0.9.122 → 0.9.123
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 +1 -1
- package/src/rules/shared/01-tool.md +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +60 -34
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +10 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +11 -11
package/package.json
CHANGED
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
evidence unavailable to file tools — an independent facet, batched with
|
|
62
62
|
the rest; independent probes are parallel shell calls, never one serial
|
|
63
63
|
script per round.
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
- Run long/uncertain commands async—never nohup—and omit timeout unless a real
|
|
65
|
+
total deadline is required; explicit timeout kills even async jobs. Do not
|
|
66
|
+
poll a notified `task_id`; completion resumes. Else poll only when requested
|
|
67
|
+
or no notification exists, with cadence/stop condition; task control only
|
|
68
|
+
serves recovery/blocking.
|
|
@@ -83,7 +83,7 @@ export const BUILTIN_TOOLS = [
|
|
|
83
83
|
cwd: { type: 'string', description: 'Omit to use the current Project root; use a project-relative subdir or explicit external path for this call only.' },
|
|
84
84
|
timeout: {
|
|
85
85
|
type: 'number',
|
|
86
|
-
description: `
|
|
86
|
+
description: `Total deadline ms. Omit for sync default ${_shellDefaultTimeoutMs()}; omit for unlimited async. Explicit values kill at deadline; sync may return task_id.`,
|
|
87
87
|
},
|
|
88
88
|
mode: { type: 'string', enum: ['sync', 'async'], description: executionModeSchemaDescription('sync') },
|
|
89
89
|
shell: { type: 'string', enum: ['bash', 'powershell'], description: 'Force shell.' },
|
|
@@ -447,6 +447,29 @@ function invalidateFindEnumerationRoot(root) {
|
|
|
447
447
|
if (findEnumerationRootFromKey(key) === root) FIND_ENUM_INFLIGHT.delete(key);
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
|
+
// Trailing-edge prewarm throttle: sustained write bursts (builds, installs)
|
|
451
|
+
// fire the watcher continuously; re-running the two full sweeps on every
|
|
452
|
+
// flush kept the serve bulk queue permanently busy. Invalidation stays
|
|
453
|
+
// immediate — only the warm rebuild is coalesced to one run per interval
|
|
454
|
+
// per root, scheduled at the trailing edge so the cache re-arms after the
|
|
455
|
+
// burst settles.
|
|
456
|
+
const FIND_ENUM_PREWARM_STATE = new Map(); // root -> { lastAt, timer }
|
|
457
|
+
const FIND_ENUM_PREWARM_MIN_INTERVAL_MS = 15_000;
|
|
458
|
+
function scheduleFindEnumerationPrewarm(root, delayMs = 100) {
|
|
459
|
+
let state = FIND_ENUM_PREWARM_STATE.get(root);
|
|
460
|
+
if (!state) {
|
|
461
|
+
state = { lastAt: 0, timer: null };
|
|
462
|
+
FIND_ENUM_PREWARM_STATE.set(root, state);
|
|
463
|
+
}
|
|
464
|
+
if (state.timer) return;
|
|
465
|
+
const wait = Math.max(delayMs, state.lastAt + FIND_ENUM_PREWARM_MIN_INTERVAL_MS - Date.now());
|
|
466
|
+
state.timer = setTimeout(() => {
|
|
467
|
+
state.timer = null;
|
|
468
|
+
state.lastAt = Date.now();
|
|
469
|
+
void prewarmFindEnumeration(root);
|
|
470
|
+
}, wait);
|
|
471
|
+
state.timer.unref?.();
|
|
472
|
+
}
|
|
450
473
|
function ensureFindEnumerationWatcher(root) {
|
|
451
474
|
const existing = FIND_ENUM_WATCHERS.get(root);
|
|
452
475
|
if (existing) {
|
|
@@ -461,8 +484,7 @@ function ensureFindEnumerationWatcher(root) {
|
|
|
461
484
|
const paths = [...pending];
|
|
462
485
|
pending.clear();
|
|
463
486
|
invalidateBuiltinResultCache(paths.length ? paths : [root]);
|
|
464
|
-
|
|
465
|
-
warm.unref?.();
|
|
487
|
+
scheduleFindEnumerationPrewarm(root);
|
|
466
488
|
};
|
|
467
489
|
record.watcher = watch(root, { recursive: true, persistent: false }, (_event, filename) => {
|
|
468
490
|
const rel = filename == null ? '' : String(filename);
|
|
@@ -649,6 +671,21 @@ async function getBroadEnumeration({ root, hidden, depth, includeNoise, ignoreMo
|
|
|
649
671
|
return subscribeToFindEnumeration(key, entry, signal);
|
|
650
672
|
}
|
|
651
673
|
|
|
674
|
+
// Cache-only peek: returns the SHARED files array of a still-valid broad
|
|
675
|
+
// sweep for these dimensions, or null. Never spawns, joins, or waits — the
|
|
676
|
+
// targeted find path below must not block behind a full-tree enumeration.
|
|
677
|
+
function peekBroadEnumeration({ root, hidden, depth, includeNoise, ignoreMode }) {
|
|
678
|
+
if (findEnumTtlMs() <= 0) return null;
|
|
679
|
+
const key = findEnumKey({ root, hidden, depth, includeNoise, ignoreMode });
|
|
680
|
+
const hit = FIND_ENUM_CACHE.get(key);
|
|
681
|
+
if (hit && hit.gen === FIND_ENUM_GEN
|
|
682
|
+
&& hit.rootGen === findEnumerationRootGeneration(root)
|
|
683
|
+
&& hit.expiresAt > Date.now()) {
|
|
684
|
+
return hit.files;
|
|
685
|
+
}
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
|
|
652
689
|
// Best-effort warm of the broad enumeration for a root using the `find` tool's
|
|
653
690
|
// DEFAULT flags (hidden:true, includeNoise:false, depth:unbounded). Swallows
|
|
654
691
|
// all errors — a failed prewarm must never surface or block the caller.
|
|
@@ -695,38 +732,27 @@ async function getTargetedFindEnumeration({
|
|
|
695
732
|
const key = JSON.stringify([root, hidden, depth ?? '', includeNoise, terms]);
|
|
696
733
|
const runs = context?.targetedRuns;
|
|
697
734
|
if (runs?.has(key)) return runs.get(key);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
return {
|
|
720
|
-
files: inventory.files.filter((path) => {
|
|
721
|
-
const lower = path.toLowerCase();
|
|
722
|
-
return lowerTerms.some((term) => lower.includes(term));
|
|
723
|
-
}),
|
|
724
|
-
truncated: false,
|
|
725
|
-
partial: false,
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
} catch {
|
|
729
|
-
if (signal?.aborted) throw findEnumerationAbortError(signal);
|
|
735
|
+
// Reuse a WARM broad inventory only (cache peek). A cold cache goes
|
|
736
|
+
// straight to the cheap targeted --iglob batch below: front-running the
|
|
737
|
+
// full `--no-ignore` sweep made cold finds stall behind the serve bulk
|
|
738
|
+
// queue for tens of seconds.
|
|
739
|
+
const inventory = peekBroadEnumeration({
|
|
740
|
+
root: normalizeOutputPath(root),
|
|
741
|
+
hidden,
|
|
742
|
+
depth,
|
|
743
|
+
includeNoise,
|
|
744
|
+
ignoreMode: 'targeted-all',
|
|
745
|
+
});
|
|
746
|
+
if (inventory) {
|
|
747
|
+
const lowerTerms = terms.map((term) => term.toLowerCase());
|
|
748
|
+
return {
|
|
749
|
+
files: inventory.filter((path) => {
|
|
750
|
+
const lower = path.toLowerCase();
|
|
751
|
+
return lowerTerms.some((term) => lower.includes(term));
|
|
752
|
+
}),
|
|
753
|
+
truncated: false,
|
|
754
|
+
partial: false,
|
|
755
|
+
};
|
|
730
756
|
}
|
|
731
757
|
let batches = FIND_TARGETED_BATCHES_BY_RUNNER.get(runRgImpl);
|
|
732
758
|
if (!batches) {
|
|
@@ -154,6 +154,15 @@ export async function tryServeSearch(argsList, execOptions = {}, opts = {}) {
|
|
|
154
154
|
const server = _ensureServer();
|
|
155
155
|
if (!server) return null;
|
|
156
156
|
const id = ++server.sequence;
|
|
157
|
+
// Honor the caller's rg deadline: the resident server must never wait
|
|
158
|
+
// LONGER than the spawn fallback it replaces (glob passes 10s while the
|
|
159
|
+
// serve ceiling is 20s), otherwise a queued/stuck serve request delays the
|
|
160
|
+
// fallback instead of accelerating it. The fixed ceiling still bounds
|
|
161
|
+
// callers that pass no timeout.
|
|
162
|
+
const callerTimeoutMs = Number(execOptions.timeout);
|
|
163
|
+
const deadlineMs = Number.isFinite(callerTimeoutMs) && callerTimeoutMs > 0
|
|
164
|
+
? Math.min(callerTimeoutMs, REQUEST_TIMEOUT_MS)
|
|
165
|
+
: REQUEST_TIMEOUT_MS;
|
|
157
166
|
_setServerReferenced(server, true);
|
|
158
167
|
const request = {
|
|
159
168
|
id,
|
|
@@ -185,7 +194,7 @@ export async function tryServeSearch(argsList, execOptions = {}, opts = {}) {
|
|
|
185
194
|
const timer = setTimeout(() => {
|
|
186
195
|
server.pending.delete(id);
|
|
187
196
|
settle(null, true);
|
|
188
|
-
},
|
|
197
|
+
}, deadlineMs);
|
|
189
198
|
timer.unref?.();
|
|
190
199
|
server.pending.set(id, { resolve: settle, reject: () => settle(null) });
|
|
191
200
|
onAbort = () => {
|
|
@@ -76,6 +76,12 @@ export async function windowsPidDescendants(pid) {
|
|
|
76
76
|
if (process.platform !== 'win32') return new Map();
|
|
77
77
|
let rows = null;
|
|
78
78
|
try { rows = await windowsProcessSnapshot({ fresh: true }); } catch { rows = null; }
|
|
79
|
+
if (!rows) {
|
|
80
|
+
// One retry before giving up: a single missed 750ms native-snapshot
|
|
81
|
+
// deadline (server busy with a bulk enumeration) otherwise marks
|
|
82
|
+
// every standby dirty and collapses the pool into cold spawns.
|
|
83
|
+
try { rows = await windowsProcessSnapshot({ fresh: true }); } catch { rows = null; }
|
|
84
|
+
}
|
|
79
85
|
if (!rows) return null;
|
|
80
86
|
const owned = new Set([pid]);
|
|
81
87
|
const descendants = new Map();
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.7",
|
|
3
3
|
"_comment": "Synced from immutable graph-v release assets.",
|
|
4
4
|
"assets": {
|
|
5
5
|
"darwin-arm64": {
|
|
6
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
7
|
-
"sha256": "
|
|
6
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.7/mixdog-graph-darwin-arm64",
|
|
7
|
+
"sha256": "a8d95602fd2beb2901dded0b1fe728adfde8075d73557442e4c540b39e64fe8d"
|
|
8
8
|
},
|
|
9
9
|
"darwin-x64": {
|
|
10
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
11
|
-
"sha256": "
|
|
10
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.7/mixdog-graph-darwin-x64",
|
|
11
|
+
"sha256": "788e6e0fb32d8d8ba3b4c22e31492dc99bba039a3186a5b3f2420df3778f45d6"
|
|
12
12
|
},
|
|
13
13
|
"linux-arm64": {
|
|
14
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
15
|
-
"sha256": "
|
|
14
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.7/mixdog-graph-linux-arm64",
|
|
15
|
+
"sha256": "43f723df7b452e75bde9839c2ce027982fa329c08560f6888442c65ac0ef7ddf"
|
|
16
16
|
},
|
|
17
17
|
"linux-x64": {
|
|
18
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
19
|
-
"sha256": "
|
|
18
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.7/mixdog-graph-linux-x64",
|
|
19
|
+
"sha256": "a7a390fb2e446fb7a9d16ac68c42c1989622beab0d6711b610a16e43360e7e84"
|
|
20
20
|
},
|
|
21
21
|
"win32-x64": {
|
|
22
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
23
|
-
"sha256": "
|
|
22
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.7/mixdog-graph-win32-x64.exe",
|
|
23
|
+
"sha256": "75e7dafd4df2f56c889b3c77643cfe95526c8ada1c1ffd1711539677737950c2"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|