mixdog 0.9.51 → 0.9.53

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.
Files changed (178) hide show
  1. package/package.json +5 -3
  2. package/scripts/abort-recovery-test.mjs +17 -1
  3. package/scripts/agent-model-liveness-test.mjs +79 -2
  4. package/scripts/anthropic-admission-retry-integration-test.mjs +119 -0
  5. package/scripts/anthropic-transport-policy-test.mjs +466 -0
  6. package/scripts/atomic-lock-tryonce-test.mjs +60 -1
  7. package/scripts/bench-run.mjs +2 -2
  8. package/scripts/build-tui.mjs +13 -1
  9. package/scripts/channel-daemon-smoke.mjs +630 -10
  10. package/scripts/code-graph-aggregate-cwd-test.mjs +41 -37
  11. package/scripts/code-graph-disk-hit-test.mjs +11 -0
  12. package/scripts/code-graph-root-federation-test.mjs +273 -0
  13. package/scripts/compact-pressure-test.mjs +159 -1
  14. package/scripts/compact-smoke.mjs +80 -0
  15. package/scripts/context-mcp-metering-test.mjs +1350 -19
  16. package/scripts/deferred-tool-loading-test.mjs +17 -0
  17. package/scripts/desktop-session-bridge-test.mjs +704 -0
  18. package/scripts/freevar-smoke.mjs +7 -4
  19. package/scripts/gemini-provider-test.mjs +1053 -0
  20. package/scripts/interrupted-turn-history-test.mjs +371 -0
  21. package/scripts/lifecycle-api-test.mjs +137 -0
  22. package/scripts/max-output-recovery-test.mjs +86 -0
  23. package/scripts/mcp-grace-deferred-test.mjs +89 -13
  24. package/scripts/memory-core-input-test.mjs +10 -0
  25. package/scripts/memory-pg-recovery-test.mjs +59 -0
  26. package/scripts/openai-oauth-ws-1006-retry-test.mjs +387 -6
  27. package/scripts/openai-ws-early-settle-test.mjs +40 -0
  28. package/scripts/parent-abort-link-test.mjs +24 -0
  29. package/scripts/process-lifecycle-test.mjs +447 -0
  30. package/scripts/provider-admission-scheduler-test.mjs +582 -0
  31. package/scripts/provider-contract-test.mjs +525 -0
  32. package/scripts/provider-toolcall-test.mjs +492 -11
  33. package/scripts/reactive-compact-persist-smoke.mjs +59 -0
  34. package/scripts/resource-admission-test.mjs +789 -0
  35. package/scripts/session-orphan-sweep-test.mjs +27 -1
  36. package/scripts/shell-jobs-windows-hide-test.mjs +1 -1
  37. package/scripts/steering-drain-buckets-test.mjs +18 -0
  38. package/scripts/toolcall-args-test.mjs +14 -6
  39. package/scripts/tui-transcript-perf-test.mjs +5 -7
  40. package/src/cli.mjs +15 -2
  41. package/src/lib/keychain-cjs.cjs +36 -23
  42. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +27 -13
  43. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +4 -1
  44. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +7 -8
  45. package/src/runtime/agent/orchestrator/agent-trace.mjs +33 -9
  46. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +331 -0
  47. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +7 -2
  48. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +114 -308
  49. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +31 -21
  50. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +136 -286
  51. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +42 -5
  52. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +554 -42
  53. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +67 -18
  54. package/src/runtime/agent/orchestrator/providers/gemini.mjs +84 -150
  55. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +17 -119
  56. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +224 -0
  57. package/src/runtime/agent/orchestrator/providers/lib/env-utils.mjs +6 -0
  58. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +119 -0
  59. package/src/runtime/agent/orchestrator/providers/lib/grok-tool-schema.mjs +109 -0
  60. package/src/runtime/agent/orchestrator/providers/lib/openai-tool-args.mjs +70 -0
  61. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +54 -14
  62. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +28 -74
  64. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +10 -80
  65. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +136 -20
  66. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +94 -33
  67. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +201 -123
  68. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +37 -28
  69. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +10 -10
  70. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +30 -3
  71. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +36 -3
  72. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +50 -45
  73. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +78 -12
  74. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +44 -5
  75. package/src/runtime/agent/orchestrator/providers/registry.mjs +49 -8
  76. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +229 -111
  77. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +130 -63
  78. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +99 -32
  79. package/src/runtime/agent/orchestrator/session/context-compaction-policy.mjs +170 -0
  80. package/src/runtime/agent/orchestrator/session/context-utils.mjs +37 -224
  81. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +11 -17
  82. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +81 -42
  83. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +10 -1
  84. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +21 -5
  85. package/src/runtime/agent/orchestrator/session/manager/message-sanitize.mjs +8 -28
  86. package/src/runtime/agent/orchestrator/session/manager/prefetch-bridge.mjs +3 -58
  87. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +30 -7
  88. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  89. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +10 -1
  90. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +42 -1
  91. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +220 -0
  92. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +57 -16
  93. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +20 -4
  94. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +2 -2
  95. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +12 -1
  96. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +52 -0
  97. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +62 -0
  98. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +17 -0
  99. package/src/runtime/agent/orchestrator/session/store.mjs +353 -108
  100. package/src/runtime/agent/orchestrator/stall-policy.mjs +2 -12
  101. package/src/runtime/agent/orchestrator/tools/bash-session.mjs +42 -4
  102. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +74 -37
  103. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +46 -0
  104. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-grep-chunks.mjs +173 -0
  105. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +117 -0
  106. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-insights.mjs +199 -0
  107. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-spawn-helpers.mjs +107 -0
  108. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +1 -40
  109. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +19 -277
  110. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +223 -2
  111. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +317 -250
  112. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +176 -21
  113. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +14 -0
  114. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +108 -2
  115. package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +93 -0
  116. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +12 -3
  117. package/src/runtime/agent/orchestrator/tools/lib/shell-spawn-retry.mjs +67 -0
  118. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +125 -85
  119. package/src/runtime/channels/backends/discord-gateway.mjs +1 -1
  120. package/src/runtime/channels/backends/discord.mjs +6 -6
  121. package/src/runtime/channels/lib/config.mjs +15 -2
  122. package/src/runtime/channels/lib/memory-client.mjs +20 -3
  123. package/src/runtime/channels/lib/owned-runtime.mjs +19 -12
  124. package/src/runtime/channels/lib/status-snapshot.mjs +9 -0
  125. package/src/runtime/channels/lib/tool-dispatch.mjs +9 -5
  126. package/src/runtime/channels/lib/worker-main.mjs +16 -5
  127. package/src/runtime/memory/index.mjs +46 -202
  128. package/src/runtime/memory/lib/memory-action-handlers.mjs +2 -53
  129. package/src/runtime/memory/lib/memory-daemon-lifecycle.mjs +115 -0
  130. package/src/runtime/memory/lib/memory-port-advertiser.mjs +105 -0
  131. package/src/runtime/memory/lib/pg/adapter.mjs +84 -10
  132. package/src/runtime/memory/lib/pg/process.mjs +91 -47
  133. package/src/runtime/memory/lib/pg/supervisor.mjs +50 -17
  134. package/src/runtime/memory/lib/query-handlers.mjs +2 -122
  135. package/src/runtime/memory/lib/query-maintenance-handlers.mjs +126 -0
  136. package/src/runtime/memory/lib/tool-call-handler.mjs +57 -0
  137. package/src/runtime/search/lib/http-fetch.mjs +1 -1
  138. package/src/runtime/shared/atomic-file.mjs +28 -150
  139. package/src/runtime/shared/config.mjs +58 -13
  140. package/src/runtime/shared/llm/cost.mjs +14 -4
  141. package/src/runtime/shared/memory-snapshot.mjs +236 -0
  142. package/src/runtime/shared/process-lifecycle.mjs +436 -0
  143. package/src/runtime/shared/process-shutdown.mjs +33 -4
  144. package/src/runtime/shared/resource-admission.mjs +364 -0
  145. package/src/runtime/shared/staged-child-result.mjs +19 -0
  146. package/src/session-runtime/channel-config-api.mjs +7 -7
  147. package/src/session-runtime/config-lifecycle.mjs +20 -17
  148. package/src/session-runtime/context-status.mjs +38 -27
  149. package/src/session-runtime/cwd-plugins.mjs +9 -7
  150. package/src/session-runtime/env.mjs +1 -2
  151. package/src/session-runtime/hitch-profile.mjs +45 -0
  152. package/src/session-runtime/lifecycle-api.mjs +60 -13
  153. package/src/session-runtime/mcp-glue.mjs +6 -11
  154. package/src/session-runtime/provider-init-key.mjs +17 -0
  155. package/src/session-runtime/provider-request-tools.mjs +72 -0
  156. package/src/session-runtime/runtime-core.mjs +49 -105
  157. package/src/session-runtime/runtime-paths.mjs +20 -0
  158. package/src/session-runtime/runtime-tool-routing.mjs +55 -0
  159. package/src/session-runtime/session-turn-api.mjs +5 -4
  160. package/src/session-runtime/tool-catalog-data.mjs +51 -0
  161. package/src/session-runtime/tool-catalog.mjs +390 -104
  162. package/src/standalone/agent-tool/spawn-preset.mjs +73 -0
  163. package/src/standalone/agent-tool/worker-rows.mjs +93 -0
  164. package/src/standalone/agent-tool.mjs +29 -200
  165. package/src/standalone/channel-admin.mjs +29 -0
  166. package/src/standalone/channel-daemon-client.mjs +200 -38
  167. package/src/standalone/channel-daemon-transport.mjs +136 -9
  168. package/src/standalone/channel-worker.mjs +79 -12
  169. package/src/tui/App.jsx +11 -5
  170. package/src/tui/dist/index.mjs +275 -343
  171. package/src/tui/engine/session-api-ext.mjs +50 -6
  172. package/src/tui/engine/session-api.mjs +1 -1
  173. package/src/tui/engine/turn.mjs +10 -6
  174. package/src/tui/engine.mjs +13 -4
  175. package/src/tui/index.jsx +5 -1
  176. package/src/tui/lib/voice-setup.mjs +21 -5
  177. package/scripts/_devtools-stub.mjs +0 -1
  178. package/src/runtime/lib/keychain-cjs.cjs +0 -288
@@ -10,9 +10,230 @@ export function isPidAlive(pid) {
10
10
  try {
11
11
  process.kill(pid, 0);
12
12
  return true;
13
- } catch {
14
- return false;
13
+ } catch (error) {
14
+ return error?.code === 'EPERM';
15
+ }
16
+ }
17
+
18
+ // Admission follows the owned process group on POSIX, not just the spawned
19
+ // shell. A shell can exit after launching a descendant which remains in its
20
+ // detached group. Windows has no process-group probe in Node; the root PID is
21
+ // the strongest non-invasive lifecycle signal available here (tree-kill still
22
+ // uses taskkill /T).
23
+ export function isProcessTreeAlive(pid) {
24
+ if (!Number.isFinite(pid) || pid <= 0) return false;
25
+ if (process.platform === 'win32') return isPidAlive(pid);
26
+ try {
27
+ process.kill(-pid, 0);
28
+ return true;
29
+ } catch (error) {
30
+ return error?.code === 'EPERM';
31
+ }
32
+ }
33
+
34
+ const windowsSnapshotCaches = new WeakMap();
35
+ function windowsProcessSnapshot({ fresh = false, spawnFn = spawn } = {}) {
36
+ let windowsSnapshotCache = windowsSnapshotCaches.get(spawnFn);
37
+ if (!windowsSnapshotCache) {
38
+ windowsSnapshotCache = { at: 0, rows: null, inFlight: null };
39
+ windowsSnapshotCaches.set(spawnFn, windowsSnapshotCache);
40
+ }
41
+ const now = Date.now();
42
+ if (!fresh && windowsSnapshotCache.rows && now - windowsSnapshotCache.at < 750) {
43
+ return Promise.resolve(windowsSnapshotCache.rows);
44
+ }
45
+ if (windowsSnapshotCache.inFlight) return windowsSnapshotCache.inFlight;
46
+ const command = [
47
+ "$ErrorActionPreference='Stop'",
48
+ 'Get-CimInstance Win32_Process -Property ProcessId,ParentProcessId,CreationDate | ForEach-Object {',
49
+ ' [Console]::Out.WriteLine(("{0}`t{1}`t{2}" -f $_.ProcessId,$_.ParentProcessId,$_.CreationDate))',
50
+ '}',
51
+ ].join('; ');
52
+ windowsSnapshotCache.inFlight = new Promise((resolve) => {
53
+ let child;
54
+ let stdout = '';
55
+ let settled = false;
56
+ let timeout = null;
57
+ const finish = (rows) => {
58
+ if (settled) return;
59
+ settled = true;
60
+ if (timeout) clearTimeout(timeout);
61
+ windowsSnapshotCache.inFlight = null;
62
+ if (rows) {
63
+ windowsSnapshotCache.at = Date.now();
64
+ windowsSnapshotCache.rows = rows;
65
+ }
66
+ resolve(rows);
67
+ };
68
+ try {
69
+ child = spawnFn('powershell.exe', [
70
+ '-NoLogo', '-NoProfile', '-NonInteractive', '-Command', command,
71
+ ], {
72
+ windowsHide: true,
73
+ stdio: ['ignore', 'pipe', 'ignore'],
74
+ });
75
+ child.stdout.setEncoding('utf8');
76
+ child.stdout.on('data', (chunk) => {
77
+ if (stdout.length <= 4 * 1024 * 1024) stdout += chunk;
78
+ });
79
+ child.once('error', () => finish(null));
80
+ child.once('close', (code) => {
81
+ if (code !== 0 || !stdout) {
82
+ finish(null);
83
+ return;
84
+ }
85
+ const rows = new Map();
86
+ for (const line of stdout.split(/\r?\n/)) {
87
+ const [pidText, parentText, identity = ''] = line.split('\t');
88
+ const rowPid = Number(pidText);
89
+ const parentPid = Number(parentText);
90
+ if (!Number.isFinite(rowPid) || rowPid <= 0 || !Number.isFinite(parentPid)) continue;
91
+ rows.set(rowPid, { pid: rowPid, parentPid, identity });
92
+ }
93
+ finish(rows);
94
+ });
95
+ timeout = setTimeout(() => {
96
+ try { child.kill(); } catch {}
97
+ finish(null);
98
+ }, 2000);
99
+ if (typeof timeout.unref === 'function') timeout.unref();
100
+ } catch {
101
+ finish(null);
102
+ }
103
+ });
104
+ return windowsSnapshotCache.inFlight;
105
+ }
106
+
107
+ function normalizeWindowsSnapshot(snapshot) {
108
+ if (snapshot instanceof Map) return snapshot;
109
+ if (!Array.isArray(snapshot)) return null;
110
+ const rows = new Map();
111
+ for (const row of snapshot) {
112
+ const rowPid = Number(row?.pid);
113
+ const parentPid = Number(row?.parentPid);
114
+ if (!Number.isFinite(rowPid) || rowPid <= 0 || !Number.isFinite(parentPid)) continue;
115
+ rows.set(rowPid, { pid: rowPid, parentPid, identity: String(row?.identity ?? '') });
116
+ }
117
+ return rows;
118
+ }
119
+
120
+ // Invoke onQuiescent exactly once, synchronously when already quiescent or
121
+ // after positive liveness probes stop observing the owned tree/group.
122
+ export function trackProcessTreeQuiescence(
123
+ pid,
124
+ onQuiescent,
125
+ {
126
+ pollMs = process.platform === 'win32' ? 250 : 25,
127
+ probe = null,
128
+ platform = process.platform,
129
+ windowsSnapshot = windowsProcessSnapshot,
130
+ windowsSnapshotSpawn = spawn,
131
+ waitForRootExit = false,
132
+ } = {},
133
+ ) {
134
+ let settled = false;
135
+ let timer = null;
136
+ let rootExitConfirmed = !waitForRootExit;
137
+ const rootExitCheck = Promise.withResolvers();
138
+ let rootExitCheckComplete = false;
139
+ const ownedWindowsProcesses = new Map();
140
+ if (platform === 'win32') {
141
+ // The PID returned by spawn is durable pre-exit ownership evidence.
142
+ // Seed it before the first asynchronous snapshot so a child whose
143
+ // parent is this PID remains attributable even if the root is already
144
+ // absent when CIM returns.
145
+ ownedWindowsProcesses.set(pid, null);
146
+ }
147
+ const finish = () => {
148
+ if (settled) return;
149
+ settled = true;
150
+ if (timer) clearInterval(timer);
151
+ try {
152
+ Promise.resolve(onQuiescent?.()).catch(() => {});
153
+ } catch { /* lifecycle cleanup must not throw */ }
154
+ };
155
+ const markRootExitChecked = () => {
156
+ if (!rootExitConfirmed || rootExitCheckComplete) return;
157
+ rootExitCheckComplete = true;
158
+ rootExitCheck.resolve();
159
+ };
160
+ const applyWindowsSnapshot = (snapshot) => {
161
+ if (settled) return;
162
+ const rows = normalizeWindowsSnapshot(snapshot);
163
+ let alive = true;
164
+ if (!rows) {
165
+ const candidates = [...ownedWindowsProcesses.keys()];
166
+ alive = candidates.some((candidatePid) => isPidAlive(candidatePid));
167
+ } else {
168
+ const root = rows.get(pid);
169
+ if (root && ownedWindowsProcesses.get(pid) == null) {
170
+ ownedWindowsProcesses.set(pid, root.identity);
171
+ }
172
+ let discovered = true;
173
+ while (discovered) {
174
+ discovered = false;
175
+ for (const row of rows.values()) {
176
+ if (
177
+ !ownedWindowsProcesses.has(row.pid)
178
+ && ownedWindowsProcesses.has(row.parentPid)
179
+ ) {
180
+ ownedWindowsProcesses.set(row.pid, row.identity);
181
+ discovered = true;
182
+ }
183
+ }
184
+ }
185
+ for (const [ownedPid, identity] of ownedWindowsProcesses) {
186
+ const current = rows.get(ownedPid);
187
+ if (!current || (identity != null && current.identity !== identity)) {
188
+ ownedWindowsProcesses.delete(ownedPid);
189
+ }
190
+ }
191
+ alive = ownedWindowsProcesses.size > 0;
192
+ }
193
+ markRootExitChecked();
194
+ if (rootExitConfirmed && !alive) finish();
195
+ };
196
+ const check = (fresh = false) => {
197
+ let alive = true;
198
+ try {
199
+ if (typeof probe === 'function') {
200
+ alive = probe(pid) === true;
201
+ } else if (platform !== 'win32') {
202
+ // The negative PID is the ownership boundary: never substitute
203
+ // a root-only probe on POSIX.
204
+ alive = isProcessTreeAlive(pid);
205
+ } else {
206
+ Promise.resolve(windowsSnapshot({ fresh, spawnFn: windowsSnapshotSpawn })).then(applyWindowsSnapshot, () => {});
207
+ return;
208
+ }
209
+ } catch {
210
+ return;
211
+ }
212
+ markRootExitChecked();
213
+ if (rootExitConfirmed && !alive) finish();
214
+ };
215
+ check();
216
+ if (!settled) {
217
+ timer = setInterval(check, Math.max(1, Number(pollMs) || 25));
218
+ if (typeof timer.unref === 'function') timer.unref();
15
219
  }
220
+ return {
221
+ get pending() { return !settled; },
222
+ afterRootExitCheck() { return rootExitCheck.promise; },
223
+ rootExited() {
224
+ if (settled || rootExitConfirmed) return false;
225
+ rootExitConfirmed = true;
226
+ check(true);
227
+ return true;
228
+ },
229
+ cancel() {
230
+ if (settled) return false;
231
+ settled = true;
232
+ if (timer) clearInterval(timer);
233
+ markRootExitChecked();
234
+ return true;
235
+ },
236
+ };
16
237
  }
17
238
 
18
239
  export function killProcessTree(pid, signal = 'SIGTERM') {