@adhdev/daemon-core 0.9.82-rc.187 → 0.9.82-rc.189
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/dist/boot/daemon-lifecycle.d.ts +1 -0
- package/dist/commands/cli-manager.d.ts +2 -1
- package/dist/commands/router.d.ts +5 -1
- package/dist/git/git-commands.d.ts +2 -0
- package/dist/git/git-types.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +459 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +458 -38
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +4 -0
- package/dist/providers/contracts.d.ts +31 -0
- package/dist/providers/sdk/v1/types/common/index.d.ts +35 -1
- package/dist/providers/spec/adapter.d.ts +4 -0
- package/dist/providers/spec/driver.d.ts +10 -1
- package/dist/providers/spec/evaluator.d.ts +9 -1
- package/dist/providers/spec/schema.gen.d.ts +38 -0
- package/dist/providers/spec/types.d.ts +25 -0
- package/dist/repo-mesh-types.d.ts +6 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +2 -0
- package/src/commands/chat-commands.ts +26 -0
- package/src/commands/cli-manager.ts +52 -14
- package/src/commands/router.ts +35 -4
- package/src/git/git-commands.ts +20 -2
- package/src/git/git-status.ts +35 -6
- package/src/git/git-types.ts +2 -0
- package/src/index.ts +1 -1
- package/src/mesh/mesh-events.ts +7 -0
- package/src/providers/cli-provider-instance.ts +110 -9
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +35 -0
- package/src/providers/provider-schema.ts +56 -1
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +46 -0
- package/src/providers/sdk/v1/types/common/index.ts +19 -0
- package/src/providers/spec/adapter.ts +8 -0
- package/src/providers/spec/driver.ts +74 -2
- package/src/providers/spec/evaluator.ts +39 -3
- package/src/providers/spec/schema.gen.ts +28 -1
- package/src/providers/spec/schema.json +26 -2
- package/src/providers/spec/types.ts +25 -0
- package/src/repo-mesh-types.ts +6 -0
package/dist/index.mjs
CHANGED
|
@@ -270,6 +270,8 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
270
270
|
if (includeSubmodules) {
|
|
271
271
|
submodules = await getSubmoduleStatuses(repo, options);
|
|
272
272
|
}
|
|
273
|
+
const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
|
|
274
|
+
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
|
|
273
275
|
return {
|
|
274
276
|
workspace: repo.workspace,
|
|
275
277
|
repoRoot: repo.repoRoot,
|
|
@@ -288,6 +290,7 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
288
290
|
untracked: parsed.untracked,
|
|
289
291
|
deleted: parsed.deleted,
|
|
290
292
|
renamed: parsed.renamed,
|
|
293
|
+
dirty,
|
|
291
294
|
hasConflicts: parsed.conflictFiles.length > 0,
|
|
292
295
|
conflictFiles: parsed.conflictFiles,
|
|
293
296
|
stashCount,
|
|
@@ -461,6 +464,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
|
|
|
461
464
|
untracked: 0,
|
|
462
465
|
deleted: 0,
|
|
463
466
|
renamed: 0,
|
|
467
|
+
dirty: false,
|
|
464
468
|
hasConflicts: false,
|
|
465
469
|
conflictFiles: [],
|
|
466
470
|
stashCount: 0,
|
|
@@ -473,17 +477,33 @@ async function getSubmoduleStatuses(repo, options) {
|
|
|
473
477
|
if (!repo.repoRoot) return [];
|
|
474
478
|
try {
|
|
475
479
|
const result = await runGit(repo, ["submodule", "status", "--recursive"], options);
|
|
476
|
-
|
|
480
|
+
const submodules = parseSubmoduleStatusOutput(result.stdout, repo.repoRoot, options.submoduleIgnorePaths);
|
|
481
|
+
await Promise.all(submodules.map((submodule) => enrichSubmoduleWorktreeStatus(repo, submodule, options)));
|
|
482
|
+
return submodules;
|
|
477
483
|
} catch {
|
|
478
484
|
return [];
|
|
479
485
|
}
|
|
480
486
|
}
|
|
487
|
+
async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
|
|
488
|
+
try {
|
|
489
|
+
const result = await runGit(repo, ["status", "--porcelain=v2", "--branch"], {
|
|
490
|
+
...options,
|
|
491
|
+
cwd: submodule.repoPath
|
|
492
|
+
});
|
|
493
|
+
const parsed = parsePorcelainV2Status(result.stdout);
|
|
494
|
+
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0;
|
|
495
|
+
submodule.dirty = submodule.dirty || dirty;
|
|
496
|
+
} catch (error) {
|
|
497
|
+
submodule.dirty = true;
|
|
498
|
+
submodule.error = formatGitError(error);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
481
501
|
function parseSubmoduleStatusOutput(output, repoRoot, ignorePaths) {
|
|
482
502
|
const submodules = [];
|
|
483
503
|
const ignoreSet = new Set(ignorePaths || []);
|
|
484
504
|
for (const line of output.split("\n")) {
|
|
485
505
|
if (!line.trim()) continue;
|
|
486
|
-
const match = line.match(/^([
|
|
506
|
+
const match = line.match(/^([\-+U\s])([0-9a-f]{40})\s+(\S+)(?:\s+\(([^)]+)\))?/);
|
|
487
507
|
if (!match) continue;
|
|
488
508
|
const prefix = match[1];
|
|
489
509
|
const commit = match[2];
|
|
@@ -493,8 +513,8 @@ function parseSubmoduleStatusOutput(output, repoRoot, ignorePaths) {
|
|
|
493
513
|
path: path40,
|
|
494
514
|
commit,
|
|
495
515
|
repoPath: repoRoot + "/" + path40,
|
|
496
|
-
dirty: prefix === "
|
|
497
|
-
outOfSync: prefix === "-",
|
|
516
|
+
dirty: prefix === "U",
|
|
517
|
+
outOfSync: prefix === "-" || prefix === "+",
|
|
498
518
|
lastCheckedAt: Date.now()
|
|
499
519
|
});
|
|
500
520
|
}
|
|
@@ -5584,6 +5604,8 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
5584
5604
|
const nodeId = readNonEmptyString2(payload.nodeId);
|
|
5585
5605
|
const workspace = readNonEmptyString2(payload.workspace);
|
|
5586
5606
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
5607
|
+
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
5608
|
+
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
5587
5609
|
return injectMeshSystemMessage(components, {
|
|
5588
5610
|
meshId,
|
|
5589
5611
|
nodeId,
|
|
@@ -5601,6 +5623,8 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
5601
5623
|
startedAt: readNonEmptyString2(payload.startedAt),
|
|
5602
5624
|
completedAt: readNonEmptyString2(payload.completedAt),
|
|
5603
5625
|
retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
|
|
5626
|
+
...relayModalMessage ? { modalMessage: relayModalMessage } : {},
|
|
5627
|
+
...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
|
|
5604
5628
|
...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
|
|
5605
5629
|
...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
|
|
5606
5630
|
...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
|
|
@@ -6150,6 +6174,52 @@ var init_provider_schema = __esm({
|
|
|
6150
6174
|
properties: { mode: { const: "env_var" }, name: { type: "string" } }
|
|
6151
6175
|
}
|
|
6152
6176
|
]
|
|
6177
|
+
},
|
|
6178
|
+
delegatedWorkerIsolation: {
|
|
6179
|
+
description: "Provider-declared launch isolation for coordinator-spawned worker sessions. Keeps worker-only sessions from inheriting coordinator MCP/tools/config.",
|
|
6180
|
+
type: "object",
|
|
6181
|
+
additionalProperties: false,
|
|
6182
|
+
properties: {
|
|
6183
|
+
env: {
|
|
6184
|
+
type: "object",
|
|
6185
|
+
additionalProperties: false,
|
|
6186
|
+
properties: {
|
|
6187
|
+
unset: {
|
|
6188
|
+
type: "array",
|
|
6189
|
+
items: { type: "string", minLength: 1 }
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
},
|
|
6193
|
+
args: {
|
|
6194
|
+
type: "array",
|
|
6195
|
+
items: {
|
|
6196
|
+
oneOf: [
|
|
6197
|
+
{
|
|
6198
|
+
type: "object",
|
|
6199
|
+
additionalProperties: false,
|
|
6200
|
+
required: ["mode", "flag"],
|
|
6201
|
+
properties: {
|
|
6202
|
+
mode: { const: "empty_mcp_config" },
|
|
6203
|
+
flag: { type: "string", minLength: 1 },
|
|
6204
|
+
strictFlag: { type: "string", minLength: 1 }
|
|
6205
|
+
}
|
|
6206
|
+
},
|
|
6207
|
+
{
|
|
6208
|
+
type: "object",
|
|
6209
|
+
additionalProperties: false,
|
|
6210
|
+
required: ["mode", "flag", "key", "value"],
|
|
6211
|
+
properties: {
|
|
6212
|
+
mode: { const: "config_override" },
|
|
6213
|
+
flag: { type: "string", minLength: 1 },
|
|
6214
|
+
key: { type: "string", minLength: 1 },
|
|
6215
|
+
value: { type: "string", minLength: 1 },
|
|
6216
|
+
dedupeKey: { type: "string", minLength: 1 }
|
|
6217
|
+
}
|
|
6218
|
+
}
|
|
6219
|
+
]
|
|
6220
|
+
}
|
|
6221
|
+
}
|
|
6222
|
+
}
|
|
6153
6223
|
}
|
|
6154
6224
|
}
|
|
6155
6225
|
},
|
|
@@ -12025,7 +12095,14 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
|
|
|
12025
12095
|
switch (command) {
|
|
12026
12096
|
case "git_status": {
|
|
12027
12097
|
if (!services.getStatus) return serviceNotImplemented(command);
|
|
12028
|
-
const
|
|
12098
|
+
const submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string" && value.trim().length > 0) : void 0;
|
|
12099
|
+
const statusParams = { workspace };
|
|
12100
|
+
const refreshUpstream = optionalBoolean(args?.refreshUpstream);
|
|
12101
|
+
const includeSubmodules = optionalBoolean(args?.includeSubmodules);
|
|
12102
|
+
if (refreshUpstream !== void 0) statusParams.refreshUpstream = refreshUpstream;
|
|
12103
|
+
if (includeSubmodules !== void 0) statusParams.includeSubmodules = includeSubmodules;
|
|
12104
|
+
if (submoduleIgnorePaths && submoduleIgnorePaths.length > 0) statusParams.submoduleIgnorePaths = submoduleIgnorePaths;
|
|
12105
|
+
const status = await runService(() => services.getStatus(statusParams));
|
|
12029
12106
|
return "success" in status ? status : { success: true, status };
|
|
12030
12107
|
}
|
|
12031
12108
|
case "git_diff_summary": {
|
|
@@ -12158,6 +12235,14 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
|
|
|
12158
12235
|
if (statusResult.hasConflicts) {
|
|
12159
12236
|
throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
|
|
12160
12237
|
}
|
|
12238
|
+
const dirtySubmodules = (statusResult.submodules || []).filter((submodule) => submodule.dirty);
|
|
12239
|
+
if (dirtySubmodules.length > 0) {
|
|
12240
|
+
const paths = dirtySubmodules.map((submodule) => submodule.path).join(", ");
|
|
12241
|
+
throw new GitCommandError(
|
|
12242
|
+
"dirty_index_required",
|
|
12243
|
+
`Repository has dirty submodules that must be checkpointed first: ${paths}. Checkpoint or commit each dirty submodule, then checkpoint this repository to record gitlink changes.`
|
|
12244
|
+
);
|
|
12245
|
+
}
|
|
12161
12246
|
const addArgs = includeUntracked ? ["-A"] : ["-u"];
|
|
12162
12247
|
await runGit(repo, ["add", ...addArgs], { cwd: repoRoot });
|
|
12163
12248
|
const fullMsg = `adhdev: checkpoint ${message}`;
|
|
@@ -21479,6 +21564,14 @@ function hasVisibleAssistantMessage(messages) {
|
|
|
21479
21564
|
return String(message.content || "").trim().length > 0;
|
|
21480
21565
|
});
|
|
21481
21566
|
}
|
|
21567
|
+
function hasFinalVisibleAssistantMessage(messages) {
|
|
21568
|
+
if (!Array.isArray(messages)) return false;
|
|
21569
|
+
const visible = filterUserFacingChatMessages(messages);
|
|
21570
|
+
const last = visible[visible.length - 1];
|
|
21571
|
+
const role = typeof last?.role === "string" ? last.role.trim().toLowerCase() : "";
|
|
21572
|
+
const content = last ? flattenContent(last.content).trim() : "";
|
|
21573
|
+
return (role === "assistant" || role === "model") && content.length > 0;
|
|
21574
|
+
}
|
|
21482
21575
|
function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
21483
21576
|
if (!isGeneratingLikeStatus(parsedStatus)) return false;
|
|
21484
21577
|
if (hasNonEmptyModalButtons(activeModal)) return false;
|
|
@@ -22333,6 +22426,18 @@ async function handleReadChat(h, args) {
|
|
|
22333
22426
|
});
|
|
22334
22427
|
}
|
|
22335
22428
|
}
|
|
22429
|
+
if (isGeneratingLikeStatus(selectedStatus) && selectedTranscriptAuthority === "provider" && !hasNonEmptyModalButtons(activeModal) && hasFinalVisibleAssistantMessage(selectedMessages)) {
|
|
22430
|
+
selectedStatus = "idle";
|
|
22431
|
+
selectedMessages = finalizeStreamingMessagesWhenIdle(selectedMessages, selectedStatus);
|
|
22432
|
+
messageSource = {
|
|
22433
|
+
...messageSource,
|
|
22434
|
+
statusReconciled: {
|
|
22435
|
+
from: returnedStatus,
|
|
22436
|
+
to: "idle",
|
|
22437
|
+
reason: "provider_native_final_assistant"
|
|
22438
|
+
}
|
|
22439
|
+
};
|
|
22440
|
+
}
|
|
22336
22441
|
LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length} returnedMsgCount=${returnedMessages.length}`);
|
|
22337
22442
|
return buildReadChatCommandResult({
|
|
22338
22443
|
messages: selectedMessages,
|
|
@@ -25549,6 +25654,13 @@ var TerminalAdapter = class {
|
|
|
25549
25654
|
snapshot() {
|
|
25550
25655
|
return this.lastScreen || this.computeScreen();
|
|
25551
25656
|
}
|
|
25657
|
+
getCursorPosition() {
|
|
25658
|
+
const buf = this.term.buffer.active;
|
|
25659
|
+
return {
|
|
25660
|
+
row: Math.max(0, buf.cursorY ?? 0),
|
|
25661
|
+
col: Math.max(0, buf.cursorX ?? 0)
|
|
25662
|
+
};
|
|
25663
|
+
}
|
|
25552
25664
|
kill() {
|
|
25553
25665
|
this.stopTimers();
|
|
25554
25666
|
try {
|
|
@@ -25653,14 +25765,33 @@ function compileLinePattern(ref) {
|
|
|
25653
25765
|
const flags = (ref.flags ?? "m").replace(/g/g, "");
|
|
25654
25766
|
return new RegExp(ref.pattern, flags);
|
|
25655
25767
|
}
|
|
25656
|
-
function matchState(state, sections, fullScreen, trace) {
|
|
25768
|
+
function matchState(state, sections, fullScreen, trace, cursor) {
|
|
25657
25769
|
const haystack = sectionText(sections, state.when.section, fullScreen);
|
|
25658
25770
|
const re = compileRegex(state.when);
|
|
25659
25771
|
if (!re.test(haystack)) {
|
|
25660
25772
|
trace.push({ kind: "state_skip", text: `state[${state.id}] when ${state.when.section ?? "*"}~/${state.when.regex}/ no match` });
|
|
25661
25773
|
return { matched: false, title: null };
|
|
25662
25774
|
}
|
|
25663
|
-
|
|
25775
|
+
if (cursor !== void 0) {
|
|
25776
|
+
const w = state.when;
|
|
25777
|
+
if (w.cursor_row_min !== void 0 && cursor.row < w.cursor_row_min) {
|
|
25778
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor row ${cursor.row} < cursor_row_min ${w.cursor_row_min}` });
|
|
25779
|
+
return { matched: false, title: null };
|
|
25780
|
+
}
|
|
25781
|
+
if (w.cursor_row_max !== void 0 && cursor.row > w.cursor_row_max) {
|
|
25782
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor row ${cursor.row} > cursor_row_max ${w.cursor_row_max}` });
|
|
25783
|
+
return { matched: false, title: null };
|
|
25784
|
+
}
|
|
25785
|
+
if (w.cursor_col_min !== void 0 && cursor.col < w.cursor_col_min) {
|
|
25786
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor col ${cursor.col} < cursor_col_min ${w.cursor_col_min}` });
|
|
25787
|
+
return { matched: false, title: null };
|
|
25788
|
+
}
|
|
25789
|
+
if (w.cursor_col_max !== void 0 && cursor.col > w.cursor_col_max) {
|
|
25790
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor col ${cursor.col} > cursor_col_max ${w.cursor_col_max}` });
|
|
25791
|
+
return { matched: false, title: null };
|
|
25792
|
+
}
|
|
25793
|
+
}
|
|
25794
|
+
trace.push({ kind: "state_match", text: `state[${state.id}] matched via ${state.when.section ?? "*"}~/${state.when.regex}/${cursor !== void 0 ? ` cursor=(${cursor.row},${cursor.col})` : ""}` });
|
|
25664
25795
|
let title = null;
|
|
25665
25796
|
if (state.extract_title) {
|
|
25666
25797
|
const titleHay = sectionText(sections, state.extract_title.section, fullScreen);
|
|
@@ -25718,17 +25849,20 @@ function extractModal(state, sections, fullScreen, title, trace) {
|
|
|
25718
25849
|
trace.push({ kind: "modal", text: `modal_buttons matched ${buttons.length} choices` });
|
|
25719
25850
|
return { title, buttons };
|
|
25720
25851
|
}
|
|
25721
|
-
function evaluate(spec, screenText) {
|
|
25852
|
+
function evaluate(spec, screenText, cursor) {
|
|
25722
25853
|
const trace = [];
|
|
25723
25854
|
const lines = screenText.split("\n");
|
|
25724
25855
|
const sections = resolveSections(spec, lines);
|
|
25725
25856
|
for (const s of sections) {
|
|
25726
25857
|
trace.push({ kind: "section", text: `section[${s.id}] lines [${s.fromLine}, ${s.toLine}) (${s.toLine - s.fromLine} lines)` });
|
|
25727
25858
|
}
|
|
25859
|
+
if (cursor !== void 0) {
|
|
25860
|
+
trace.push({ kind: "section", text: `cursor (${cursor.row}, ${cursor.col})` });
|
|
25861
|
+
}
|
|
25728
25862
|
let activeState = null;
|
|
25729
25863
|
let modal = null;
|
|
25730
25864
|
for (const st of spec.states) {
|
|
25731
|
-
const { matched, title } = matchState(st, sections, screenText, trace);
|
|
25865
|
+
const { matched, title } = matchState(st, sections, screenText, trace, cursor);
|
|
25732
25866
|
if (!matched) continue;
|
|
25733
25867
|
const extractedModal = extractModal(st, sections, screenText, title, trace);
|
|
25734
25868
|
if (st.modal_buttons && !extractedModal) {
|
|
@@ -25919,7 +26053,18 @@ var SCHEMA = {
|
|
|
25919
26053
|
"additionalProperties": false,
|
|
25920
26054
|
"properties": {
|
|
25921
26055
|
"busy_hold_ms": { "type": "integer", "minimum": 0 },
|
|
25922
|
-
"startup_grace_ms": { "type": "integer", "minimum": 0 }
|
|
26056
|
+
"startup_grace_ms": { "type": "integer", "minimum": 0 },
|
|
26057
|
+
"completion_idle_after": {
|
|
26058
|
+
"type": "object",
|
|
26059
|
+
"additionalProperties": false,
|
|
26060
|
+
"required": ["regex", "hold_ms"],
|
|
26061
|
+
"properties": {
|
|
26062
|
+
"section": { "type": "string", "minLength": 1 },
|
|
26063
|
+
"regex": { "type": "string", "minLength": 1 },
|
|
26064
|
+
"flags": { "type": "string" },
|
|
26065
|
+
"hold_ms": { "type": "integer", "minimum": 0 }
|
|
26066
|
+
}
|
|
26067
|
+
}
|
|
25923
26068
|
}
|
|
25924
26069
|
}
|
|
25925
26070
|
},
|
|
@@ -25985,6 +26130,22 @@ var SCHEMA = {
|
|
|
25985
26130
|
"flags": {
|
|
25986
26131
|
"type": "string",
|
|
25987
26132
|
"default": "i"
|
|
26133
|
+
},
|
|
26134
|
+
"cursor_row_min": {
|
|
26135
|
+
"type": "integer",
|
|
26136
|
+
"minimum": 0
|
|
26137
|
+
},
|
|
26138
|
+
"cursor_row_max": {
|
|
26139
|
+
"type": "integer",
|
|
26140
|
+
"minimum": 0
|
|
26141
|
+
},
|
|
26142
|
+
"cursor_col_min": {
|
|
26143
|
+
"type": "integer",
|
|
26144
|
+
"minimum": 0
|
|
26145
|
+
},
|
|
26146
|
+
"cursor_col_max": {
|
|
26147
|
+
"type": "integer",
|
|
26148
|
+
"minimum": 0
|
|
25988
26149
|
}
|
|
25989
26150
|
}
|
|
25990
26151
|
},
|
|
@@ -26399,6 +26560,30 @@ function resolveSubmitDelayMs(specBeforeSubmit, text) {
|
|
|
26399
26560
|
const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
|
|
26400
26561
|
return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
|
|
26401
26562
|
}
|
|
26563
|
+
function matchesCompletionIdleRule(spec, ev, screen) {
|
|
26564
|
+
const rule = spec.debounce?.completion_idle_after;
|
|
26565
|
+
if (!rule?.regex) return null;
|
|
26566
|
+
const haystack = rule.section ? ev.sections.find((section) => section.id === rule.section)?.text ?? "" : screen;
|
|
26567
|
+
if (!haystack) return null;
|
|
26568
|
+
try {
|
|
26569
|
+
const regex = new RegExp(rule.regex, rule.flags || "");
|
|
26570
|
+
const match = haystack.match(regex);
|
|
26571
|
+
return match?.[0] || null;
|
|
26572
|
+
} catch {
|
|
26573
|
+
return null;
|
|
26574
|
+
}
|
|
26575
|
+
}
|
|
26576
|
+
function matchesCompletionIdleTargetState(spec, ev, screen) {
|
|
26577
|
+
const target = spec.states.find((state) => state.id === spec.default_state) ?? spec.states.find((state) => state.id === "idle");
|
|
26578
|
+
if (!target?.when?.regex) return false;
|
|
26579
|
+
const haystack = target.when.section ? ev.sections.find((section) => section.id === target.when.section)?.text ?? "" : screen;
|
|
26580
|
+
if (!haystack) return false;
|
|
26581
|
+
try {
|
|
26582
|
+
return new RegExp(target.when.regex, target.when.flags || "i").test(haystack);
|
|
26583
|
+
} catch {
|
|
26584
|
+
return false;
|
|
26585
|
+
}
|
|
26586
|
+
}
|
|
26402
26587
|
var SpecDriver = class {
|
|
26403
26588
|
constructor(opts) {
|
|
26404
26589
|
this.opts = opts;
|
|
@@ -26438,6 +26623,8 @@ var SpecDriver = class {
|
|
|
26438
26623
|
* because the evaluator already moved past busy by the time the hold
|
|
26439
26624
|
* kicks in. */
|
|
26440
26625
|
lastBusyState = null;
|
|
26626
|
+
completionIdleFirstSeenAt = 0;
|
|
26627
|
+
completionIdleKey = "";
|
|
26441
26628
|
/** Timer that re-runs evaluate() once the hold window expires. Needed
|
|
26442
26629
|
* because the PTY stops emitting once the agent finishes; without an
|
|
26443
26630
|
* explicit wake-up there's nothing to trigger the busy → idle
|
|
@@ -26488,6 +26675,9 @@ var SpecDriver = class {
|
|
|
26488
26675
|
snapshot() {
|
|
26489
26676
|
return this.adapter.snapshot();
|
|
26490
26677
|
}
|
|
26678
|
+
getCursorPosition() {
|
|
26679
|
+
return this.adapter.getCursorPosition();
|
|
26680
|
+
}
|
|
26491
26681
|
shutdown() {
|
|
26492
26682
|
for (const t of this.delegateTimers.values()) clearTimeout(t);
|
|
26493
26683
|
this.delegateTimers.clear();
|
|
@@ -26552,7 +26742,8 @@ var SpecDriver = class {
|
|
|
26552
26742
|
}
|
|
26553
26743
|
reevaluate(forceEmit = false) {
|
|
26554
26744
|
const screen = this.adapter.snapshot();
|
|
26555
|
-
const
|
|
26745
|
+
const cursor = this.adapter.getCursorPosition();
|
|
26746
|
+
const ev = evaluate(this.spec, screen, cursor);
|
|
26556
26747
|
let evState = ev.state;
|
|
26557
26748
|
const busyHoldMs = this.spec.debounce?.busy_hold_ms ?? BUSY_HOLD_MS;
|
|
26558
26749
|
if (this.currentStateId === "busy" && evState.id === "idle") {
|
|
@@ -26561,10 +26752,40 @@ var SpecDriver = class {
|
|
|
26561
26752
|
evState = this.lastBusyState ?? evState;
|
|
26562
26753
|
}
|
|
26563
26754
|
}
|
|
26755
|
+
const completionIdleRule = this.spec.debounce?.completion_idle_after;
|
|
26756
|
+
let busyWakeMs = busyHoldMs;
|
|
26757
|
+
if (evState.id === "busy" && completionIdleRule) {
|
|
26758
|
+
const completionKey = matchesCompletionIdleRule(this.spec, ev, screen);
|
|
26759
|
+
if (completionKey) {
|
|
26760
|
+
const now = Date.now();
|
|
26761
|
+
if (completionKey !== this.completionIdleKey) {
|
|
26762
|
+
this.completionIdleKey = completionKey;
|
|
26763
|
+
this.completionIdleFirstSeenAt = now;
|
|
26764
|
+
}
|
|
26765
|
+
const holdMs = Math.max(0, completionIdleRule.hold_ms || 0);
|
|
26766
|
+
const ageMs = now - this.completionIdleFirstSeenAt;
|
|
26767
|
+
if (ageMs >= holdMs) {
|
|
26768
|
+
if (matchesCompletionIdleTargetState(this.spec, ev, screen)) {
|
|
26769
|
+
const idle = this.spec.states.find((state) => state.id === this.spec.default_state) ?? this.spec.states.find((state) => state.id === "idle");
|
|
26770
|
+
evState = idle ? { id: idle.id, label: idle.label, title: null } : { id: "idle", label: "Ready", title: null };
|
|
26771
|
+
} else {
|
|
26772
|
+
busyWakeMs = Math.min(busyWakeMs, 1e3);
|
|
26773
|
+
}
|
|
26774
|
+
} else {
|
|
26775
|
+
busyWakeMs = Math.min(busyWakeMs, Math.max(holdMs - ageMs, 0));
|
|
26776
|
+
}
|
|
26777
|
+
} else {
|
|
26778
|
+
this.completionIdleKey = "";
|
|
26779
|
+
this.completionIdleFirstSeenAt = 0;
|
|
26780
|
+
}
|
|
26781
|
+
} else if (evState.id !== "busy") {
|
|
26782
|
+
this.completionIdleKey = "";
|
|
26783
|
+
this.completionIdleFirstSeenAt = 0;
|
|
26784
|
+
}
|
|
26564
26785
|
if (evState.id === "busy") {
|
|
26565
26786
|
this.lastBusyAt = Date.now();
|
|
26566
26787
|
this.lastBusyState = evState;
|
|
26567
|
-
this.scheduleBusyExpiry(
|
|
26788
|
+
this.scheduleBusyExpiry(busyWakeMs);
|
|
26568
26789
|
}
|
|
26569
26790
|
const changed = forceEmit || evState.id !== this.currentStateId || !shallowSameModal(ev, this.currentEval) || !shallowSameControls(ev, this.currentEval);
|
|
26570
26791
|
if (this.pickerInProgress) this.tryAdvancePicker(screen);
|
|
@@ -27467,6 +27688,8 @@ var CliProviderInstance = class {
|
|
|
27467
27688
|
historyWriter;
|
|
27468
27689
|
runtimeMessages = [];
|
|
27469
27690
|
lastPersistedHistoryMessages = [];
|
|
27691
|
+
lastAcknowledgedUserInputAt = 0;
|
|
27692
|
+
externalBusyIdleFingerprint = "";
|
|
27470
27693
|
lastNativeSourceCanonicalCheckAt = 0;
|
|
27471
27694
|
lastNativeSourceCanonicalCacheKey = void 0;
|
|
27472
27695
|
cachedSqliteDb = null;
|
|
@@ -27595,7 +27818,11 @@ var CliProviderInstance = class {
|
|
|
27595
27818
|
typeof adapterStatus?.providerSessionId === "string" ? adapterStatus.providerSessionId : ""
|
|
27596
27819
|
);
|
|
27597
27820
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, Date.now());
|
|
27598
|
-
|
|
27821
|
+
let visibleStatus = parseErrorMessage || parsedStatus?.status === "error" ? "error" : autoApproveActive ? "generating" : adapterStatus.status;
|
|
27822
|
+
const externalNativeFinal = this.getExternalNativeFinalReconciliation(parsedStatus?.messages, adapterStatus);
|
|
27823
|
+
if (externalNativeFinal && isCliGeneratingLikeStatus(visibleStatus)) {
|
|
27824
|
+
visibleStatus = "idle";
|
|
27825
|
+
}
|
|
27599
27826
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
27600
27827
|
this.maybeAppendRuntimeRecoveryMessage(runtime);
|
|
27601
27828
|
let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
@@ -27757,7 +27984,22 @@ var CliProviderInstance = class {
|
|
|
27757
27984
|
};
|
|
27758
27985
|
}
|
|
27759
27986
|
updateSettings(newSettings) {
|
|
27760
|
-
|
|
27987
|
+
const runtimeMeshSettings = {};
|
|
27988
|
+
for (const key of [
|
|
27989
|
+
"meshNodeFor",
|
|
27990
|
+
"meshNodeId",
|
|
27991
|
+
"meshActiveTaskId",
|
|
27992
|
+
"meshCoordinatorFor",
|
|
27993
|
+
"meshCoordinatorDaemonId",
|
|
27994
|
+
"meshCoordinatorNodeId",
|
|
27995
|
+
"spawnedSessionVisibility",
|
|
27996
|
+
"launchedByCoordinator"
|
|
27997
|
+
]) {
|
|
27998
|
+
if (this.settings[key] !== void 0 && newSettings[key] === void 0) {
|
|
27999
|
+
runtimeMeshSettings[key] = this.settings[key];
|
|
28000
|
+
}
|
|
28001
|
+
}
|
|
28002
|
+
this.settings = { ...newSettings, ...runtimeMeshSettings };
|
|
27761
28003
|
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
27762
28004
|
this.monitor.updateConfig({
|
|
27763
28005
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
@@ -27848,6 +28090,8 @@ var CliProviderInstance = class {
|
|
|
27848
28090
|
const content = typeof input === "string" ? input.trim() : buildCliStructuredInputPrompt(input).trim();
|
|
27849
28091
|
if (!content) return;
|
|
27850
28092
|
const receivedAt = Date.now();
|
|
28093
|
+
this.lastAcknowledgedUserInputAt = receivedAt;
|
|
28094
|
+
this.externalBusyIdleFingerprint = "";
|
|
27851
28095
|
const dedupKey = `user_input_ack:${crypto4.createHash("sha256").update(`${this.instanceId}:${content}:${receivedAt}`).digest("hex").slice(0, 24)}`;
|
|
27852
28096
|
this.appendRuntimeMessage(buildChatMessage({
|
|
27853
28097
|
role: "user",
|
|
@@ -27996,6 +28240,50 @@ var CliProviderInstance = class {
|
|
|
27996
28240
|
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
27997
28241
|
return extractFinalSummaryFromMessages(evidence.messages);
|
|
27998
28242
|
}
|
|
28243
|
+
externalNativeFinalFingerprint(evidence) {
|
|
28244
|
+
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
28245
|
+
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
28246
|
+
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
28247
|
+
const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
|
|
28248
|
+
const receivedAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
28249
|
+
const probe = this.lastExternalCompletionProbe;
|
|
28250
|
+
return crypto4.createHash("sha256").update([
|
|
28251
|
+
this.type,
|
|
28252
|
+
this.providerSessionId || "",
|
|
28253
|
+
probe?.sourcePath || "",
|
|
28254
|
+
String(probe?.sourceMtimeMs || 0),
|
|
28255
|
+
String(receivedAt || 0),
|
|
28256
|
+
content.slice(-500)
|
|
28257
|
+
].join("\0")).digest("hex").slice(0, 24);
|
|
28258
|
+
}
|
|
28259
|
+
getExternalNativeFinalReconciliation(parsedMessages, adapterStatus) {
|
|
28260
|
+
const rawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
28261
|
+
if (!isCliGeneratingLikeStatus(rawStatus)) return null;
|
|
28262
|
+
if (hasNonEmptyCliModalButtons(adapterStatus?.activeModal ?? adapterStatus?.modal)) return null;
|
|
28263
|
+
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
28264
|
+
if (evidence.source !== "external-native" || !evidence.present) return null;
|
|
28265
|
+
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
28266
|
+
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
28267
|
+
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
28268
|
+
const lastMessageAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
28269
|
+
const sourceMtimeMs = Number(this.lastExternalCompletionProbe?.sourceMtimeMs || 0);
|
|
28270
|
+
const minEvidenceAt = Math.max(
|
|
28271
|
+
this.startedAt > 0 ? this.startedAt - 5e3 : 0,
|
|
28272
|
+
this.generatingStartedAt > 0 ? this.generatingStartedAt - 5e3 : 0,
|
|
28273
|
+
this.lastAcknowledgedUserInputAt > 0 ? this.lastAcknowledgedUserInputAt - 1e3 : 0
|
|
28274
|
+
);
|
|
28275
|
+
if (minEvidenceAt > 0 && lastMessageAt > 0 && lastMessageAt < minEvidenceAt && sourceMtimeMs < minEvidenceAt) {
|
|
28276
|
+
return null;
|
|
28277
|
+
}
|
|
28278
|
+
const finalSummary = extractFinalSummaryFromMessages(evidence.messages);
|
|
28279
|
+
if (!finalSummary) return null;
|
|
28280
|
+
const fingerprint = this.externalNativeFinalFingerprint(evidence);
|
|
28281
|
+
if (fingerprint === this.externalBusyIdleFingerprint) {
|
|
28282
|
+
return { fingerprint, finalSummary, evidence };
|
|
28283
|
+
}
|
|
28284
|
+
this.externalBusyIdleFingerprint = fingerprint;
|
|
28285
|
+
return { fingerprint, finalSummary, evidence };
|
|
28286
|
+
}
|
|
27999
28287
|
buildCompletedFinalizationDiagnostic(args) {
|
|
28000
28288
|
let parsed = null;
|
|
28001
28289
|
let parseError;
|
|
@@ -28066,17 +28354,18 @@ var CliProviderInstance = class {
|
|
|
28066
28354
|
if (typeof adapterAny?.responseBuffer === "string" && adapterAny.responseBuffer.trim()) return false;
|
|
28067
28355
|
return true;
|
|
28068
28356
|
}
|
|
28069
|
-
getCompletedFinalizationBlock(latestVisibleStatus, pending) {
|
|
28357
|
+
getCompletedFinalizationBlock(latestVisibleStatus, pending, opts) {
|
|
28070
28358
|
if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
|
|
28071
28359
|
const adapterAny = this.adapter;
|
|
28072
28360
|
const approvalResolvedIdle = pending.previousStatus === "waiting_approval";
|
|
28073
|
-
|
|
28361
|
+
const externalNativeFinal = opts?.externalNativeFinal || null;
|
|
28362
|
+
if (!approvalResolvedIdle && !externalNativeFinal) {
|
|
28074
28363
|
if (adapterAny?.isWaitingForResponse === true) return { reason: "adapter_waiting_for_response", terminal: true };
|
|
28075
28364
|
if (adapterAny?.currentTurnScope) return { reason: "adapter_turn_scope_active", terminal: true };
|
|
28076
28365
|
if (this.hasAdapterPendingResponse()) return { reason: "adapter_pending_response", terminal: true };
|
|
28077
28366
|
}
|
|
28078
28367
|
const partial = typeof this.adapter.getPartialResponse === "function" ? this.adapter.getPartialResponse() : "";
|
|
28079
|
-
if (typeof partial === "string" && partial.trim()) return { reason: "partial_response_pending", terminal: true };
|
|
28368
|
+
if (!externalNativeFinal && typeof partial === "string" && partial.trim()) return { reason: "partial_response_pending", terminal: true };
|
|
28080
28369
|
let parsed;
|
|
28081
28370
|
try {
|
|
28082
28371
|
parsed = this.adapter.getScriptParsedStatus();
|
|
@@ -28086,6 +28375,7 @@ var CliProviderInstance = class {
|
|
|
28086
28375
|
const parsedStatus = typeof parsed?.status === "string" ? parsed.status : "unknown";
|
|
28087
28376
|
if (parsedStatus !== "idle") {
|
|
28088
28377
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
28378
|
+
if (externalNativeFinal && isCliGeneratingLikeStatus(parsedStatus)) return null;
|
|
28089
28379
|
if (this.shouldSuppressStaleParsedBusyStatus(parsed, adapterStatus)) return null;
|
|
28090
28380
|
return { reason: `parsed_status:${parsedStatus}`, terminal: isCliGeneratingLikeStatus(parsedStatus) };
|
|
28091
28381
|
}
|
|
@@ -28138,14 +28428,15 @@ var CliProviderInstance = class {
|
|
|
28138
28428
|
}
|
|
28139
28429
|
const latestStatus = this.adapter.getStatus({ allowParse: false });
|
|
28140
28430
|
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
28141
|
-
const
|
|
28431
|
+
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, latestStatus);
|
|
28432
|
+
const latestVisibleStatus = externalNativeFinal && isCliGeneratingLikeStatus(latestStatus.status) ? "idle" : latestAutoApproveActive ? "generating" : latestStatus.status;
|
|
28142
28433
|
if (latestVisibleStatus !== "idle") {
|
|
28143
28434
|
LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
|
|
28144
28435
|
this.completedDebouncePending = null;
|
|
28145
28436
|
this.completedDebounceTimer = null;
|
|
28146
28437
|
return;
|
|
28147
28438
|
}
|
|
28148
|
-
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
28439
|
+
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending, { externalNativeFinal });
|
|
28149
28440
|
if (block2) {
|
|
28150
28441
|
const blockReason = block2.reason;
|
|
28151
28442
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
@@ -28186,7 +28477,18 @@ var CliProviderInstance = class {
|
|
|
28186
28477
|
chatTitle: pending.chatTitle,
|
|
28187
28478
|
duration: pending.duration,
|
|
28188
28479
|
timestamp: pending.timestamp,
|
|
28189
|
-
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
|
|
28480
|
+
finalSummary: externalNativeFinal?.finalSummary || this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages),
|
|
28481
|
+
...externalNativeFinal ? {
|
|
28482
|
+
completionDiagnostic: {
|
|
28483
|
+
providerType: this.type,
|
|
28484
|
+
sessionId: this.instanceId,
|
|
28485
|
+
providerSessionId: this.providerSessionId || null,
|
|
28486
|
+
reconciliationReason: "external_native_final_assistant_while_adapter_busy",
|
|
28487
|
+
finalAssistantPresent: true,
|
|
28488
|
+
finalAssistantEvidenceSource: externalNativeFinal.evidence.source,
|
|
28489
|
+
externalFinalFingerprint: externalNativeFinal.fingerprint
|
|
28490
|
+
}
|
|
28491
|
+
} : {}
|
|
28190
28492
|
});
|
|
28191
28493
|
this.completedDebouncePending = null;
|
|
28192
28494
|
this.completedDebounceTimer = null;
|
|
@@ -28242,7 +28544,8 @@ var CliProviderInstance = class {
|
|
|
28242
28544
|
const parsedStatus = null;
|
|
28243
28545
|
const rawStatus = adapterStatus.status;
|
|
28244
28546
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
|
|
28245
|
-
const
|
|
28547
|
+
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
|
|
28548
|
+
const newStatus = externalNativeFinal && isCliGeneratingLikeStatus(rawStatus) ? "idle" : autoApproveActive ? "generating" : rawStatus;
|
|
28246
28549
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
28247
28550
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
28248
28551
|
const partial = this.adapter.getPartialResponse();
|
|
@@ -30248,15 +30551,29 @@ function colorize(color, text) {
|
|
|
30248
30551
|
const fn = chalkApi?.[color];
|
|
30249
30552
|
return typeof fn === "function" ? fn(text) : text;
|
|
30250
30553
|
}
|
|
30251
|
-
var
|
|
30252
|
-
ADHDEV_INLINE_MESH
|
|
30253
|
-
ADHDEV_MCP_TRANSPORT
|
|
30254
|
-
ADHDEV_MESH_ID
|
|
30255
|
-
HERMES_EPHEMERAL_SYSTEM_PROMPT
|
|
30256
|
-
|
|
30554
|
+
var DEFAULT_COORDINATOR_DELEGATED_ENV_UNSETS = [
|
|
30555
|
+
"ADHDEV_INLINE_MESH",
|
|
30556
|
+
"ADHDEV_MCP_TRANSPORT",
|
|
30557
|
+
"ADHDEV_MESH_ID",
|
|
30558
|
+
"HERMES_EPHEMERAL_SYSTEM_PROMPT"
|
|
30559
|
+
];
|
|
30257
30560
|
function hasCliArg(args, flag) {
|
|
30258
30561
|
return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
30259
30562
|
}
|
|
30563
|
+
function hasConfigOverride(args, key) {
|
|
30564
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
30565
|
+
const arg = args[index];
|
|
30566
|
+
const next = args[index + 1];
|
|
30567
|
+
if ((arg === "-c" || arg === "--config") && typeof next === "string") {
|
|
30568
|
+
if (next === key || next.startsWith(`${key}=`) || next.startsWith(`${key}.`)) return true;
|
|
30569
|
+
}
|
|
30570
|
+
if (arg.startsWith("--config=")) {
|
|
30571
|
+
const value = arg.slice("--config=".length);
|
|
30572
|
+
if (value === key || value.startsWith(`${key}=`) || value.startsWith(`${key}.`)) return true;
|
|
30573
|
+
}
|
|
30574
|
+
}
|
|
30575
|
+
return false;
|
|
30576
|
+
}
|
|
30260
30577
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
30261
30578
|
const baseDir = path23.join(os17.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
30262
30579
|
mkdirSync11(baseDir, { recursive: true });
|
|
@@ -30266,11 +30583,30 @@ function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
|
30266
30583
|
return filePath;
|
|
30267
30584
|
}
|
|
30268
30585
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
30269
|
-
const cliType = String(input.cliType || "").trim();
|
|
30270
30586
|
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
30271
|
-
const env = { ...input.env || {}
|
|
30272
|
-
|
|
30273
|
-
|
|
30587
|
+
const env = { ...input.env || {} };
|
|
30588
|
+
const envUnsets = new Set(DEFAULT_COORDINATOR_DELEGATED_ENV_UNSETS);
|
|
30589
|
+
for (const key of input.isolation?.env?.unset || []) {
|
|
30590
|
+
if (typeof key === "string" && key.trim()) envUnsets.add(key.trim());
|
|
30591
|
+
}
|
|
30592
|
+
for (const key of envUnsets) env[key] = "";
|
|
30593
|
+
for (const rule of input.isolation?.args || []) {
|
|
30594
|
+
if (!rule || typeof rule !== "object") continue;
|
|
30595
|
+
if (rule.mode === "empty_mcp_config") {
|
|
30596
|
+
if (rule.flag && !hasCliArg(cliArgs, rule.flag)) {
|
|
30597
|
+
cliArgs.unshift(rule.flag, ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
30598
|
+
}
|
|
30599
|
+
if (rule.strictFlag && !hasCliArg(cliArgs, rule.strictFlag)) {
|
|
30600
|
+
cliArgs.unshift(rule.strictFlag);
|
|
30601
|
+
}
|
|
30602
|
+
continue;
|
|
30603
|
+
}
|
|
30604
|
+
if (rule.mode === "config_override") {
|
|
30605
|
+
const key = String(rule.dedupeKey || rule.key || "").trim();
|
|
30606
|
+
const flag = String(rule.flag || "").trim();
|
|
30607
|
+
if (!key || !flag || hasConfigOverride(cliArgs, key)) continue;
|
|
30608
|
+
cliArgs.unshift(flag, `${rule.key}=${rule.value}`);
|
|
30609
|
+
}
|
|
30274
30610
|
}
|
|
30275
30611
|
return { cliArgs, env };
|
|
30276
30612
|
}
|
|
@@ -30933,22 +31269,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
30933
31269
|
const dir = resolved.path;
|
|
30934
31270
|
const launchSource = resolved.source;
|
|
30935
31271
|
if (!cliType) throw new Error("cliType required");
|
|
31272
|
+
const providerType = this.providerLoader.resolveAlias(cliType);
|
|
31273
|
+
const provLookup = this.providerLoader.getMeta(providerType);
|
|
30936
31274
|
const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
30937
31275
|
const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
|
|
30938
31276
|
cliType,
|
|
30939
31277
|
workspace: dir,
|
|
30940
31278
|
cliArgs: args?.cliArgs,
|
|
30941
|
-
env: args?.env
|
|
31279
|
+
env: args?.env,
|
|
31280
|
+
isolation: provLookup?.meshCoordinator?.delegatedWorkerIsolation
|
|
30942
31281
|
}) : null;
|
|
30943
|
-
const
|
|
30944
|
-
const provTrust =
|
|
31282
|
+
const provMeta = provLookup;
|
|
31283
|
+
const provTrust = provMeta?._sourceTrust;
|
|
30945
31284
|
if (provTrust === "external-untrusted" && args?.confirmExternalUntrusted !== true) {
|
|
30946
31285
|
return {
|
|
30947
31286
|
success: false,
|
|
30948
31287
|
error: "untrusted_external_provider",
|
|
30949
31288
|
provider: {
|
|
30950
31289
|
type: provLookup?.type ?? cliType,
|
|
30951
|
-
sourceName:
|
|
31290
|
+
sourceName: provMeta?._sourceName ?? null,
|
|
30952
31291
|
trust: provTrust
|
|
30953
31292
|
},
|
|
30954
31293
|
hint: "Resend launch_cli with confirmExternalUntrusted=true after the user explicitly approves running JavaScript from this 3rd-party source."
|
|
@@ -31420,7 +31759,10 @@ function validateMeshCoordinator(raw, errors) {
|
|
|
31420
31759
|
if (meshCoordinator.reason !== void 0 && (typeof meshCoordinator.reason !== "string" || !meshCoordinator.reason.trim())) {
|
|
31421
31760
|
errors.push("meshCoordinator.reason must be a non-empty string when provided");
|
|
31422
31761
|
}
|
|
31423
|
-
|
|
31762
|
+
validateMeshCoordinatorMcpConfig(meshCoordinator.mcpConfig, errors);
|
|
31763
|
+
validateMeshCoordinatorDelegatedWorkerIsolation(meshCoordinator.delegatedWorkerIsolation, errors);
|
|
31764
|
+
}
|
|
31765
|
+
function validateMeshCoordinatorMcpConfig(mcpConfig, errors) {
|
|
31424
31766
|
if (mcpConfig === void 0) return;
|
|
31425
31767
|
if (!mcpConfig || typeof mcpConfig !== "object" || Array.isArray(mcpConfig)) {
|
|
31426
31768
|
errors.push("meshCoordinator.mcpConfig must be an object");
|
|
@@ -31461,6 +31803,56 @@ function validateMeshCoordinator(raw, errors) {
|
|
|
31461
31803
|
}
|
|
31462
31804
|
}
|
|
31463
31805
|
}
|
|
31806
|
+
function validateMeshCoordinatorDelegatedWorkerIsolation(raw, errors) {
|
|
31807
|
+
if (raw === void 0) return;
|
|
31808
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
31809
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation must be an object");
|
|
31810
|
+
return;
|
|
31811
|
+
}
|
|
31812
|
+
const isolation = raw;
|
|
31813
|
+
const env = isolation.env;
|
|
31814
|
+
if (env !== void 0) {
|
|
31815
|
+
if (!env || typeof env !== "object" || Array.isArray(env)) {
|
|
31816
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation.env must be an object");
|
|
31817
|
+
} else {
|
|
31818
|
+
const unset = env.unset;
|
|
31819
|
+
if (unset !== void 0 && (!Array.isArray(unset) || unset.some((key) => typeof key !== "string" || !key.trim()))) {
|
|
31820
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation.env.unset must be an array of non-empty strings");
|
|
31821
|
+
}
|
|
31822
|
+
}
|
|
31823
|
+
}
|
|
31824
|
+
const args = isolation.args;
|
|
31825
|
+
if (args === void 0) return;
|
|
31826
|
+
if (!Array.isArray(args)) {
|
|
31827
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation.args must be an array");
|
|
31828
|
+
return;
|
|
31829
|
+
}
|
|
31830
|
+
for (const [index, rule] of args.entries()) {
|
|
31831
|
+
const prefix = `meshCoordinator.delegatedWorkerIsolation.args[${index}]`;
|
|
31832
|
+
if (!rule || typeof rule !== "object" || Array.isArray(rule)) {
|
|
31833
|
+
errors.push(`${prefix} must be an object`);
|
|
31834
|
+
continue;
|
|
31835
|
+
}
|
|
31836
|
+
const item = rule;
|
|
31837
|
+
const mode = item.mode;
|
|
31838
|
+
if (mode !== "empty_mcp_config" && mode !== "config_override") {
|
|
31839
|
+
errors.push(`${prefix}.mode must be one of: empty_mcp_config, config_override`);
|
|
31840
|
+
continue;
|
|
31841
|
+
}
|
|
31842
|
+
for (const key of mode === "empty_mcp_config" ? ["flag"] : ["flag", "key", "value"]) {
|
|
31843
|
+
const value = item[key];
|
|
31844
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
31845
|
+
errors.push(`${prefix}.${key} must be a non-empty string`);
|
|
31846
|
+
}
|
|
31847
|
+
}
|
|
31848
|
+
for (const key of ["strictFlag", "dedupeKey"]) {
|
|
31849
|
+
const value = item[key];
|
|
31850
|
+
if (value !== void 0 && (typeof value !== "string" || !value.trim())) {
|
|
31851
|
+
errors.push(`${prefix}.${key} must be a non-empty string when provided`);
|
|
31852
|
+
}
|
|
31853
|
+
}
|
|
31854
|
+
}
|
|
31855
|
+
}
|
|
31464
31856
|
function validateControl(control, errors) {
|
|
31465
31857
|
if (!control || typeof control !== "object") {
|
|
31466
31858
|
errors.push("controls: each control must be an object");
|
|
@@ -37122,9 +37514,14 @@ function readCachedInlineMeshActiveSessionDetails(node) {
|
|
|
37122
37514
|
node?.provider_type
|
|
37123
37515
|
),
|
|
37124
37516
|
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
37517
|
+
chatStatus: readStringValue(fallbackSession.chatStatus, fallbackSession.chat_status),
|
|
37125
37518
|
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
37126
37519
|
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
37127
37520
|
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
37521
|
+
role: readStringValue(fallbackSession.role) ?? null,
|
|
37522
|
+
isSelfCoordinator: fallbackSession.isSelfCoordinator === true || fallbackSession.is_self_coordinator === true,
|
|
37523
|
+
createdAt: readStringValue(fallbackSession.createdAt, fallbackSession.created_at) ?? null,
|
|
37524
|
+
startedAt: readStringValue(fallbackSession.startedAt, fallbackSession.started_at) ?? null,
|
|
37128
37525
|
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
37129
37526
|
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
37130
37527
|
isCached: true
|
|
@@ -37265,15 +37662,26 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
37265
37662
|
};
|
|
37266
37663
|
}
|
|
37267
37664
|
function summarizeMeshSessionRecord(record) {
|
|
37665
|
+
const meta = readObjectRecord(record?.meta);
|
|
37666
|
+
const isSelfCoordinator = Boolean(readStringValue(meta.meshCoordinatorFor));
|
|
37667
|
+
const chatStatus = readStringValue(record?.chatStatus, record?.activeChat?.status, meta.chatStatus, meta.sessionStatus);
|
|
37668
|
+
const state = readLiveMeshSessionState(record);
|
|
37669
|
+
const statusNote = isSelfCoordinator && (!chatStatus || chatStatus === "idle" || state === "idle") ? "Coordinator self status is sampled from the session host and may read idle while the coordinator is generating this response." : null;
|
|
37268
37670
|
return {
|
|
37269
37671
|
sessionId: readStringValue(record?.sessionId) || "unknown",
|
|
37270
37672
|
providerType: readStringValue(record?.providerType),
|
|
37271
|
-
state
|
|
37673
|
+
state,
|
|
37674
|
+
chatStatus,
|
|
37272
37675
|
lifecycle: readStringValue(record?.lifecycle),
|
|
37273
37676
|
surfaceKind: getSessionHostSurfaceKind(record),
|
|
37274
|
-
recoveryState: readStringValue(
|
|
37677
|
+
recoveryState: readStringValue(meta.runtimeRecoveryState) ?? null,
|
|
37275
37678
|
workspace: readStringValue(record?.workspace) ?? null,
|
|
37276
37679
|
title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
|
|
37680
|
+
role: isSelfCoordinator ? "coordinator" : readStringValue(meta.meshRole, meta.role) ?? null,
|
|
37681
|
+
isSelfCoordinator,
|
|
37682
|
+
statusNote,
|
|
37683
|
+
createdAt: toIsoTimestamp(record?.createdAt ?? record?.created_at),
|
|
37684
|
+
startedAt: toIsoTimestamp(record?.startedAt ?? record?.started_at ?? record?.spawnedAtMs ?? record?.spawned_at_ms),
|
|
37277
37685
|
lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
|
|
37278
37686
|
isCached: false
|
|
37279
37687
|
};
|
|
@@ -38297,6 +38705,15 @@ var DaemonCommandRouter = class {
|
|
|
38297
38705
|
this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next), queueRevision: getMeshQueueRevision(meshId) });
|
|
38298
38706
|
return next;
|
|
38299
38707
|
}
|
|
38708
|
+
getCachedInlineMeshNodes() {
|
|
38709
|
+
const nodes = [];
|
|
38710
|
+
for (const mesh of this.inlineMeshCache.values()) {
|
|
38711
|
+
if (Array.isArray(mesh?.nodes)) {
|
|
38712
|
+
nodes.push(...mesh.nodes);
|
|
38713
|
+
}
|
|
38714
|
+
}
|
|
38715
|
+
return nodes;
|
|
38716
|
+
}
|
|
38300
38717
|
getCachedInlineMesh(meshId, inlineMesh) {
|
|
38301
38718
|
if (inlineMesh && typeof inlineMesh === "object") {
|
|
38302
38719
|
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
@@ -38345,6 +38762,7 @@ var DaemonCommandRouter = class {
|
|
|
38345
38762
|
}
|
|
38346
38763
|
invalidateAggregateMeshStatus(meshId) {
|
|
38347
38764
|
this.aggregateMeshStatusCache.delete(meshId);
|
|
38765
|
+
this.deps.onMeshStateChange?.(meshId);
|
|
38348
38766
|
}
|
|
38349
38767
|
async requireMeshHostMutationOwner(meshId, inlineMesh, operation) {
|
|
38350
38768
|
const meshRecord = await this.getMeshForCommand(meshId, inlineMesh, { preferInline: true });
|
|
@@ -49837,6 +50255,7 @@ async function initDaemonComponents(config) {
|
|
|
49837
50255
|
},
|
|
49838
50256
|
onIdeConnected: () => poller?.start(),
|
|
49839
50257
|
onStatusChange: config.onStatusChange,
|
|
50258
|
+
onMeshStateChange: config.onMeshStateChange,
|
|
49840
50259
|
onPostChatCommand: config.onPostChatCommand,
|
|
49841
50260
|
sessionHostControl: config.sessionHostControl,
|
|
49842
50261
|
statusInstanceId: config.statusInstanceId,
|
|
@@ -50429,6 +50848,7 @@ export {
|
|
|
50429
50848
|
probeCdpPort,
|
|
50430
50849
|
queuePendingMeshCoordinatorEvent,
|
|
50431
50850
|
readSession3 as readAntigravityCliSession,
|
|
50851
|
+
readCachedInlineMeshActiveSessionDetails,
|
|
50432
50852
|
readChatHistory,
|
|
50433
50853
|
readSession as readClaudeCliSession,
|
|
50434
50854
|
readSession2 as readCodexCliSession,
|