@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.js
CHANGED
|
@@ -275,6 +275,8 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
275
275
|
if (includeSubmodules) {
|
|
276
276
|
submodules = await getSubmoduleStatuses(repo, options);
|
|
277
277
|
}
|
|
278
|
+
const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
|
|
279
|
+
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
|
|
278
280
|
return {
|
|
279
281
|
workspace: repo.workspace,
|
|
280
282
|
repoRoot: repo.repoRoot,
|
|
@@ -293,6 +295,7 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
293
295
|
untracked: parsed.untracked,
|
|
294
296
|
deleted: parsed.deleted,
|
|
295
297
|
renamed: parsed.renamed,
|
|
298
|
+
dirty,
|
|
296
299
|
hasConflicts: parsed.conflictFiles.length > 0,
|
|
297
300
|
conflictFiles: parsed.conflictFiles,
|
|
298
301
|
stashCount,
|
|
@@ -466,6 +469,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
|
|
|
466
469
|
untracked: 0,
|
|
467
470
|
deleted: 0,
|
|
468
471
|
renamed: 0,
|
|
472
|
+
dirty: false,
|
|
469
473
|
hasConflicts: false,
|
|
470
474
|
conflictFiles: [],
|
|
471
475
|
stashCount: 0,
|
|
@@ -478,17 +482,33 @@ async function getSubmoduleStatuses(repo, options) {
|
|
|
478
482
|
if (!repo.repoRoot) return [];
|
|
479
483
|
try {
|
|
480
484
|
const result = await runGit(repo, ["submodule", "status", "--recursive"], options);
|
|
481
|
-
|
|
485
|
+
const submodules = parseSubmoduleStatusOutput(result.stdout, repo.repoRoot, options.submoduleIgnorePaths);
|
|
486
|
+
await Promise.all(submodules.map((submodule) => enrichSubmoduleWorktreeStatus(repo, submodule, options)));
|
|
487
|
+
return submodules;
|
|
482
488
|
} catch {
|
|
483
489
|
return [];
|
|
484
490
|
}
|
|
485
491
|
}
|
|
492
|
+
async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
|
|
493
|
+
try {
|
|
494
|
+
const result = await runGit(repo, ["status", "--porcelain=v2", "--branch"], {
|
|
495
|
+
...options,
|
|
496
|
+
cwd: submodule.repoPath
|
|
497
|
+
});
|
|
498
|
+
const parsed = parsePorcelainV2Status(result.stdout);
|
|
499
|
+
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0;
|
|
500
|
+
submodule.dirty = submodule.dirty || dirty;
|
|
501
|
+
} catch (error) {
|
|
502
|
+
submodule.dirty = true;
|
|
503
|
+
submodule.error = formatGitError(error);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
486
506
|
function parseSubmoduleStatusOutput(output, repoRoot, ignorePaths) {
|
|
487
507
|
const submodules = [];
|
|
488
508
|
const ignoreSet = new Set(ignorePaths || []);
|
|
489
509
|
for (const line of output.split("\n")) {
|
|
490
510
|
if (!line.trim()) continue;
|
|
491
|
-
const match = line.match(/^([
|
|
511
|
+
const match = line.match(/^([\-+U\s])([0-9a-f]{40})\s+(\S+)(?:\s+\(([^)]+)\))?/);
|
|
492
512
|
if (!match) continue;
|
|
493
513
|
const prefix = match[1];
|
|
494
514
|
const commit = match[2];
|
|
@@ -498,8 +518,8 @@ function parseSubmoduleStatusOutput(output, repoRoot, ignorePaths) {
|
|
|
498
518
|
path: path40,
|
|
499
519
|
commit,
|
|
500
520
|
repoPath: repoRoot + "/" + path40,
|
|
501
|
-
dirty: prefix === "
|
|
502
|
-
outOfSync: prefix === "-",
|
|
521
|
+
dirty: prefix === "U",
|
|
522
|
+
outOfSync: prefix === "-" || prefix === "+",
|
|
503
523
|
lastCheckedAt: Date.now()
|
|
504
524
|
});
|
|
505
525
|
}
|
|
@@ -5589,6 +5609,8 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
5589
5609
|
const nodeId = readNonEmptyString2(payload.nodeId);
|
|
5590
5610
|
const workspace = readNonEmptyString2(payload.workspace);
|
|
5591
5611
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
5612
|
+
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
5613
|
+
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
5592
5614
|
return injectMeshSystemMessage(components, {
|
|
5593
5615
|
meshId,
|
|
5594
5616
|
nodeId,
|
|
@@ -5606,6 +5628,8 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
5606
5628
|
startedAt: readNonEmptyString2(payload.startedAt),
|
|
5607
5629
|
completedAt: readNonEmptyString2(payload.completedAt),
|
|
5608
5630
|
retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
|
|
5631
|
+
...relayModalMessage ? { modalMessage: relayModalMessage } : {},
|
|
5632
|
+
...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
|
|
5609
5633
|
...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
|
|
5610
5634
|
...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
|
|
5611
5635
|
...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
|
|
@@ -6157,6 +6181,52 @@ var init_provider_schema = __esm({
|
|
|
6157
6181
|
properties: { mode: { const: "env_var" }, name: { type: "string" } }
|
|
6158
6182
|
}
|
|
6159
6183
|
]
|
|
6184
|
+
},
|
|
6185
|
+
delegatedWorkerIsolation: {
|
|
6186
|
+
description: "Provider-declared launch isolation for coordinator-spawned worker sessions. Keeps worker-only sessions from inheriting coordinator MCP/tools/config.",
|
|
6187
|
+
type: "object",
|
|
6188
|
+
additionalProperties: false,
|
|
6189
|
+
properties: {
|
|
6190
|
+
env: {
|
|
6191
|
+
type: "object",
|
|
6192
|
+
additionalProperties: false,
|
|
6193
|
+
properties: {
|
|
6194
|
+
unset: {
|
|
6195
|
+
type: "array",
|
|
6196
|
+
items: { type: "string", minLength: 1 }
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
},
|
|
6200
|
+
args: {
|
|
6201
|
+
type: "array",
|
|
6202
|
+
items: {
|
|
6203
|
+
oneOf: [
|
|
6204
|
+
{
|
|
6205
|
+
type: "object",
|
|
6206
|
+
additionalProperties: false,
|
|
6207
|
+
required: ["mode", "flag"],
|
|
6208
|
+
properties: {
|
|
6209
|
+
mode: { const: "empty_mcp_config" },
|
|
6210
|
+
flag: { type: "string", minLength: 1 },
|
|
6211
|
+
strictFlag: { type: "string", minLength: 1 }
|
|
6212
|
+
}
|
|
6213
|
+
},
|
|
6214
|
+
{
|
|
6215
|
+
type: "object",
|
|
6216
|
+
additionalProperties: false,
|
|
6217
|
+
required: ["mode", "flag", "key", "value"],
|
|
6218
|
+
properties: {
|
|
6219
|
+
mode: { const: "config_override" },
|
|
6220
|
+
flag: { type: "string", minLength: 1 },
|
|
6221
|
+
key: { type: "string", minLength: 1 },
|
|
6222
|
+
value: { type: "string", minLength: 1 },
|
|
6223
|
+
dedupeKey: { type: "string", minLength: 1 }
|
|
6224
|
+
}
|
|
6225
|
+
}
|
|
6226
|
+
]
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
6229
|
+
}
|
|
6160
6230
|
}
|
|
6161
6231
|
}
|
|
6162
6232
|
},
|
|
@@ -11290,6 +11360,7 @@ __export(index_exports, {
|
|
|
11290
11360
|
probeCdpPort: () => probeCdpPort,
|
|
11291
11361
|
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
11292
11362
|
readAntigravityCliSession: () => readSession3,
|
|
11363
|
+
readCachedInlineMeshActiveSessionDetails: () => readCachedInlineMeshActiveSessionDetails,
|
|
11293
11364
|
readChatHistory: () => readChatHistory,
|
|
11294
11365
|
readClaudeCliSession: () => readSession,
|
|
11295
11366
|
readCodexCliSession: () => readSession2,
|
|
@@ -12334,7 +12405,14 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
|
|
|
12334
12405
|
switch (command) {
|
|
12335
12406
|
case "git_status": {
|
|
12336
12407
|
if (!services.getStatus) return serviceNotImplemented(command);
|
|
12337
|
-
const
|
|
12408
|
+
const submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string" && value.trim().length > 0) : void 0;
|
|
12409
|
+
const statusParams = { workspace };
|
|
12410
|
+
const refreshUpstream = optionalBoolean(args?.refreshUpstream);
|
|
12411
|
+
const includeSubmodules = optionalBoolean(args?.includeSubmodules);
|
|
12412
|
+
if (refreshUpstream !== void 0) statusParams.refreshUpstream = refreshUpstream;
|
|
12413
|
+
if (includeSubmodules !== void 0) statusParams.includeSubmodules = includeSubmodules;
|
|
12414
|
+
if (submoduleIgnorePaths && submoduleIgnorePaths.length > 0) statusParams.submoduleIgnorePaths = submoduleIgnorePaths;
|
|
12415
|
+
const status = await runService(() => services.getStatus(statusParams));
|
|
12338
12416
|
return "success" in status ? status : { success: true, status };
|
|
12339
12417
|
}
|
|
12340
12418
|
case "git_diff_summary": {
|
|
@@ -12467,6 +12545,14 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
|
|
|
12467
12545
|
if (statusResult.hasConflicts) {
|
|
12468
12546
|
throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
|
|
12469
12547
|
}
|
|
12548
|
+
const dirtySubmodules = (statusResult.submodules || []).filter((submodule) => submodule.dirty);
|
|
12549
|
+
if (dirtySubmodules.length > 0) {
|
|
12550
|
+
const paths = dirtySubmodules.map((submodule) => submodule.path).join(", ");
|
|
12551
|
+
throw new GitCommandError(
|
|
12552
|
+
"dirty_index_required",
|
|
12553
|
+
`Repository has dirty submodules that must be checkpointed first: ${paths}. Checkpoint or commit each dirty submodule, then checkpoint this repository to record gitlink changes.`
|
|
12554
|
+
);
|
|
12555
|
+
}
|
|
12470
12556
|
const addArgs = includeUntracked ? ["-A"] : ["-u"];
|
|
12471
12557
|
await runGit(repo, ["add", ...addArgs], { cwd: repoRoot });
|
|
12472
12558
|
const fullMsg = `adhdev: checkpoint ${message}`;
|
|
@@ -21788,6 +21874,14 @@ function hasVisibleAssistantMessage(messages) {
|
|
|
21788
21874
|
return String(message.content || "").trim().length > 0;
|
|
21789
21875
|
});
|
|
21790
21876
|
}
|
|
21877
|
+
function hasFinalVisibleAssistantMessage(messages) {
|
|
21878
|
+
if (!Array.isArray(messages)) return false;
|
|
21879
|
+
const visible = filterUserFacingChatMessages(messages);
|
|
21880
|
+
const last = visible[visible.length - 1];
|
|
21881
|
+
const role = typeof last?.role === "string" ? last.role.trim().toLowerCase() : "";
|
|
21882
|
+
const content = last ? flattenContent(last.content).trim() : "";
|
|
21883
|
+
return (role === "assistant" || role === "model") && content.length > 0;
|
|
21884
|
+
}
|
|
21791
21885
|
function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
21792
21886
|
if (!isGeneratingLikeStatus(parsedStatus)) return false;
|
|
21793
21887
|
if (hasNonEmptyModalButtons(activeModal)) return false;
|
|
@@ -22642,6 +22736,18 @@ async function handleReadChat(h, args) {
|
|
|
22642
22736
|
});
|
|
22643
22737
|
}
|
|
22644
22738
|
}
|
|
22739
|
+
if (isGeneratingLikeStatus(selectedStatus) && selectedTranscriptAuthority === "provider" && !hasNonEmptyModalButtons(activeModal) && hasFinalVisibleAssistantMessage(selectedMessages)) {
|
|
22740
|
+
selectedStatus = "idle";
|
|
22741
|
+
selectedMessages = finalizeStreamingMessagesWhenIdle(selectedMessages, selectedStatus);
|
|
22742
|
+
messageSource = {
|
|
22743
|
+
...messageSource,
|
|
22744
|
+
statusReconciled: {
|
|
22745
|
+
from: returnedStatus,
|
|
22746
|
+
to: "idle",
|
|
22747
|
+
reason: "provider_native_final_assistant"
|
|
22748
|
+
}
|
|
22749
|
+
};
|
|
22750
|
+
}
|
|
22645
22751
|
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}`);
|
|
22646
22752
|
return buildReadChatCommandResult({
|
|
22647
22753
|
messages: selectedMessages,
|
|
@@ -25858,6 +25964,13 @@ var TerminalAdapter = class {
|
|
|
25858
25964
|
snapshot() {
|
|
25859
25965
|
return this.lastScreen || this.computeScreen();
|
|
25860
25966
|
}
|
|
25967
|
+
getCursorPosition() {
|
|
25968
|
+
const buf = this.term.buffer.active;
|
|
25969
|
+
return {
|
|
25970
|
+
row: Math.max(0, buf.cursorY ?? 0),
|
|
25971
|
+
col: Math.max(0, buf.cursorX ?? 0)
|
|
25972
|
+
};
|
|
25973
|
+
}
|
|
25861
25974
|
kill() {
|
|
25862
25975
|
this.stopTimers();
|
|
25863
25976
|
try {
|
|
@@ -25962,14 +26075,33 @@ function compileLinePattern(ref) {
|
|
|
25962
26075
|
const flags = (ref.flags ?? "m").replace(/g/g, "");
|
|
25963
26076
|
return new RegExp(ref.pattern, flags);
|
|
25964
26077
|
}
|
|
25965
|
-
function matchState(state, sections, fullScreen, trace) {
|
|
26078
|
+
function matchState(state, sections, fullScreen, trace, cursor) {
|
|
25966
26079
|
const haystack = sectionText(sections, state.when.section, fullScreen);
|
|
25967
26080
|
const re = compileRegex(state.when);
|
|
25968
26081
|
if (!re.test(haystack)) {
|
|
25969
26082
|
trace.push({ kind: "state_skip", text: `state[${state.id}] when ${state.when.section ?? "*"}~/${state.when.regex}/ no match` });
|
|
25970
26083
|
return { matched: false, title: null };
|
|
25971
26084
|
}
|
|
25972
|
-
|
|
26085
|
+
if (cursor !== void 0) {
|
|
26086
|
+
const w = state.when;
|
|
26087
|
+
if (w.cursor_row_min !== void 0 && cursor.row < w.cursor_row_min) {
|
|
26088
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor row ${cursor.row} < cursor_row_min ${w.cursor_row_min}` });
|
|
26089
|
+
return { matched: false, title: null };
|
|
26090
|
+
}
|
|
26091
|
+
if (w.cursor_row_max !== void 0 && cursor.row > w.cursor_row_max) {
|
|
26092
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor row ${cursor.row} > cursor_row_max ${w.cursor_row_max}` });
|
|
26093
|
+
return { matched: false, title: null };
|
|
26094
|
+
}
|
|
26095
|
+
if (w.cursor_col_min !== void 0 && cursor.col < w.cursor_col_min) {
|
|
26096
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor col ${cursor.col} < cursor_col_min ${w.cursor_col_min}` });
|
|
26097
|
+
return { matched: false, title: null };
|
|
26098
|
+
}
|
|
26099
|
+
if (w.cursor_col_max !== void 0 && cursor.col > w.cursor_col_max) {
|
|
26100
|
+
trace.push({ kind: "state_skip", text: `state[${state.id}] cursor col ${cursor.col} > cursor_col_max ${w.cursor_col_max}` });
|
|
26101
|
+
return { matched: false, title: null };
|
|
26102
|
+
}
|
|
26103
|
+
}
|
|
26104
|
+
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})` : ""}` });
|
|
25973
26105
|
let title = null;
|
|
25974
26106
|
if (state.extract_title) {
|
|
25975
26107
|
const titleHay = sectionText(sections, state.extract_title.section, fullScreen);
|
|
@@ -26027,17 +26159,20 @@ function extractModal(state, sections, fullScreen, title, trace) {
|
|
|
26027
26159
|
trace.push({ kind: "modal", text: `modal_buttons matched ${buttons.length} choices` });
|
|
26028
26160
|
return { title, buttons };
|
|
26029
26161
|
}
|
|
26030
|
-
function evaluate(spec, screenText) {
|
|
26162
|
+
function evaluate(spec, screenText, cursor) {
|
|
26031
26163
|
const trace = [];
|
|
26032
26164
|
const lines = screenText.split("\n");
|
|
26033
26165
|
const sections = resolveSections(spec, lines);
|
|
26034
26166
|
for (const s of sections) {
|
|
26035
26167
|
trace.push({ kind: "section", text: `section[${s.id}] lines [${s.fromLine}, ${s.toLine}) (${s.toLine - s.fromLine} lines)` });
|
|
26036
26168
|
}
|
|
26169
|
+
if (cursor !== void 0) {
|
|
26170
|
+
trace.push({ kind: "section", text: `cursor (${cursor.row}, ${cursor.col})` });
|
|
26171
|
+
}
|
|
26037
26172
|
let activeState = null;
|
|
26038
26173
|
let modal = null;
|
|
26039
26174
|
for (const st of spec.states) {
|
|
26040
|
-
const { matched, title } = matchState(st, sections, screenText, trace);
|
|
26175
|
+
const { matched, title } = matchState(st, sections, screenText, trace, cursor);
|
|
26041
26176
|
if (!matched) continue;
|
|
26042
26177
|
const extractedModal = extractModal(st, sections, screenText, title, trace);
|
|
26043
26178
|
if (st.modal_buttons && !extractedModal) {
|
|
@@ -26228,7 +26363,18 @@ var SCHEMA = {
|
|
|
26228
26363
|
"additionalProperties": false,
|
|
26229
26364
|
"properties": {
|
|
26230
26365
|
"busy_hold_ms": { "type": "integer", "minimum": 0 },
|
|
26231
|
-
"startup_grace_ms": { "type": "integer", "minimum": 0 }
|
|
26366
|
+
"startup_grace_ms": { "type": "integer", "minimum": 0 },
|
|
26367
|
+
"completion_idle_after": {
|
|
26368
|
+
"type": "object",
|
|
26369
|
+
"additionalProperties": false,
|
|
26370
|
+
"required": ["regex", "hold_ms"],
|
|
26371
|
+
"properties": {
|
|
26372
|
+
"section": { "type": "string", "minLength": 1 },
|
|
26373
|
+
"regex": { "type": "string", "minLength": 1 },
|
|
26374
|
+
"flags": { "type": "string" },
|
|
26375
|
+
"hold_ms": { "type": "integer", "minimum": 0 }
|
|
26376
|
+
}
|
|
26377
|
+
}
|
|
26232
26378
|
}
|
|
26233
26379
|
}
|
|
26234
26380
|
},
|
|
@@ -26294,6 +26440,22 @@ var SCHEMA = {
|
|
|
26294
26440
|
"flags": {
|
|
26295
26441
|
"type": "string",
|
|
26296
26442
|
"default": "i"
|
|
26443
|
+
},
|
|
26444
|
+
"cursor_row_min": {
|
|
26445
|
+
"type": "integer",
|
|
26446
|
+
"minimum": 0
|
|
26447
|
+
},
|
|
26448
|
+
"cursor_row_max": {
|
|
26449
|
+
"type": "integer",
|
|
26450
|
+
"minimum": 0
|
|
26451
|
+
},
|
|
26452
|
+
"cursor_col_min": {
|
|
26453
|
+
"type": "integer",
|
|
26454
|
+
"minimum": 0
|
|
26455
|
+
},
|
|
26456
|
+
"cursor_col_max": {
|
|
26457
|
+
"type": "integer",
|
|
26458
|
+
"minimum": 0
|
|
26297
26459
|
}
|
|
26298
26460
|
}
|
|
26299
26461
|
},
|
|
@@ -26708,6 +26870,30 @@ function resolveSubmitDelayMs(specBeforeSubmit, text) {
|
|
|
26708
26870
|
const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
|
|
26709
26871
|
return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
|
|
26710
26872
|
}
|
|
26873
|
+
function matchesCompletionIdleRule(spec, ev, screen) {
|
|
26874
|
+
const rule = spec.debounce?.completion_idle_after;
|
|
26875
|
+
if (!rule?.regex) return null;
|
|
26876
|
+
const haystack = rule.section ? ev.sections.find((section) => section.id === rule.section)?.text ?? "" : screen;
|
|
26877
|
+
if (!haystack) return null;
|
|
26878
|
+
try {
|
|
26879
|
+
const regex = new RegExp(rule.regex, rule.flags || "");
|
|
26880
|
+
const match = haystack.match(regex);
|
|
26881
|
+
return match?.[0] || null;
|
|
26882
|
+
} catch {
|
|
26883
|
+
return null;
|
|
26884
|
+
}
|
|
26885
|
+
}
|
|
26886
|
+
function matchesCompletionIdleTargetState(spec, ev, screen) {
|
|
26887
|
+
const target = spec.states.find((state) => state.id === spec.default_state) ?? spec.states.find((state) => state.id === "idle");
|
|
26888
|
+
if (!target?.when?.regex) return false;
|
|
26889
|
+
const haystack = target.when.section ? ev.sections.find((section) => section.id === target.when.section)?.text ?? "" : screen;
|
|
26890
|
+
if (!haystack) return false;
|
|
26891
|
+
try {
|
|
26892
|
+
return new RegExp(target.when.regex, target.when.flags || "i").test(haystack);
|
|
26893
|
+
} catch {
|
|
26894
|
+
return false;
|
|
26895
|
+
}
|
|
26896
|
+
}
|
|
26711
26897
|
var SpecDriver = class {
|
|
26712
26898
|
constructor(opts) {
|
|
26713
26899
|
this.opts = opts;
|
|
@@ -26747,6 +26933,8 @@ var SpecDriver = class {
|
|
|
26747
26933
|
* because the evaluator already moved past busy by the time the hold
|
|
26748
26934
|
* kicks in. */
|
|
26749
26935
|
lastBusyState = null;
|
|
26936
|
+
completionIdleFirstSeenAt = 0;
|
|
26937
|
+
completionIdleKey = "";
|
|
26750
26938
|
/** Timer that re-runs evaluate() once the hold window expires. Needed
|
|
26751
26939
|
* because the PTY stops emitting once the agent finishes; without an
|
|
26752
26940
|
* explicit wake-up there's nothing to trigger the busy → idle
|
|
@@ -26797,6 +26985,9 @@ var SpecDriver = class {
|
|
|
26797
26985
|
snapshot() {
|
|
26798
26986
|
return this.adapter.snapshot();
|
|
26799
26987
|
}
|
|
26988
|
+
getCursorPosition() {
|
|
26989
|
+
return this.adapter.getCursorPosition();
|
|
26990
|
+
}
|
|
26800
26991
|
shutdown() {
|
|
26801
26992
|
for (const t of this.delegateTimers.values()) clearTimeout(t);
|
|
26802
26993
|
this.delegateTimers.clear();
|
|
@@ -26861,7 +27052,8 @@ var SpecDriver = class {
|
|
|
26861
27052
|
}
|
|
26862
27053
|
reevaluate(forceEmit = false) {
|
|
26863
27054
|
const screen = this.adapter.snapshot();
|
|
26864
|
-
const
|
|
27055
|
+
const cursor = this.adapter.getCursorPosition();
|
|
27056
|
+
const ev = evaluate(this.spec, screen, cursor);
|
|
26865
27057
|
let evState = ev.state;
|
|
26866
27058
|
const busyHoldMs = this.spec.debounce?.busy_hold_ms ?? BUSY_HOLD_MS;
|
|
26867
27059
|
if (this.currentStateId === "busy" && evState.id === "idle") {
|
|
@@ -26870,10 +27062,40 @@ var SpecDriver = class {
|
|
|
26870
27062
|
evState = this.lastBusyState ?? evState;
|
|
26871
27063
|
}
|
|
26872
27064
|
}
|
|
27065
|
+
const completionIdleRule = this.spec.debounce?.completion_idle_after;
|
|
27066
|
+
let busyWakeMs = busyHoldMs;
|
|
27067
|
+
if (evState.id === "busy" && completionIdleRule) {
|
|
27068
|
+
const completionKey = matchesCompletionIdleRule(this.spec, ev, screen);
|
|
27069
|
+
if (completionKey) {
|
|
27070
|
+
const now = Date.now();
|
|
27071
|
+
if (completionKey !== this.completionIdleKey) {
|
|
27072
|
+
this.completionIdleKey = completionKey;
|
|
27073
|
+
this.completionIdleFirstSeenAt = now;
|
|
27074
|
+
}
|
|
27075
|
+
const holdMs = Math.max(0, completionIdleRule.hold_ms || 0);
|
|
27076
|
+
const ageMs = now - this.completionIdleFirstSeenAt;
|
|
27077
|
+
if (ageMs >= holdMs) {
|
|
27078
|
+
if (matchesCompletionIdleTargetState(this.spec, ev, screen)) {
|
|
27079
|
+
const idle = this.spec.states.find((state) => state.id === this.spec.default_state) ?? this.spec.states.find((state) => state.id === "idle");
|
|
27080
|
+
evState = idle ? { id: idle.id, label: idle.label, title: null } : { id: "idle", label: "Ready", title: null };
|
|
27081
|
+
} else {
|
|
27082
|
+
busyWakeMs = Math.min(busyWakeMs, 1e3);
|
|
27083
|
+
}
|
|
27084
|
+
} else {
|
|
27085
|
+
busyWakeMs = Math.min(busyWakeMs, Math.max(holdMs - ageMs, 0));
|
|
27086
|
+
}
|
|
27087
|
+
} else {
|
|
27088
|
+
this.completionIdleKey = "";
|
|
27089
|
+
this.completionIdleFirstSeenAt = 0;
|
|
27090
|
+
}
|
|
27091
|
+
} else if (evState.id !== "busy") {
|
|
27092
|
+
this.completionIdleKey = "";
|
|
27093
|
+
this.completionIdleFirstSeenAt = 0;
|
|
27094
|
+
}
|
|
26873
27095
|
if (evState.id === "busy") {
|
|
26874
27096
|
this.lastBusyAt = Date.now();
|
|
26875
27097
|
this.lastBusyState = evState;
|
|
26876
|
-
this.scheduleBusyExpiry(
|
|
27098
|
+
this.scheduleBusyExpiry(busyWakeMs);
|
|
26877
27099
|
}
|
|
26878
27100
|
const changed = forceEmit || evState.id !== this.currentStateId || !shallowSameModal(ev, this.currentEval) || !shallowSameControls(ev, this.currentEval);
|
|
26879
27101
|
if (this.pickerInProgress) this.tryAdvancePicker(screen);
|
|
@@ -27776,6 +27998,8 @@ var CliProviderInstance = class {
|
|
|
27776
27998
|
historyWriter;
|
|
27777
27999
|
runtimeMessages = [];
|
|
27778
28000
|
lastPersistedHistoryMessages = [];
|
|
28001
|
+
lastAcknowledgedUserInputAt = 0;
|
|
28002
|
+
externalBusyIdleFingerprint = "";
|
|
27779
28003
|
lastNativeSourceCanonicalCheckAt = 0;
|
|
27780
28004
|
lastNativeSourceCanonicalCacheKey = void 0;
|
|
27781
28005
|
cachedSqliteDb = null;
|
|
@@ -27904,7 +28128,11 @@ var CliProviderInstance = class {
|
|
|
27904
28128
|
typeof adapterStatus?.providerSessionId === "string" ? adapterStatus.providerSessionId : ""
|
|
27905
28129
|
);
|
|
27906
28130
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, Date.now());
|
|
27907
|
-
|
|
28131
|
+
let visibleStatus = parseErrorMessage || parsedStatus?.status === "error" ? "error" : autoApproveActive ? "generating" : adapterStatus.status;
|
|
28132
|
+
const externalNativeFinal = this.getExternalNativeFinalReconciliation(parsedStatus?.messages, adapterStatus);
|
|
28133
|
+
if (externalNativeFinal && isCliGeneratingLikeStatus(visibleStatus)) {
|
|
28134
|
+
visibleStatus = "idle";
|
|
28135
|
+
}
|
|
27908
28136
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
27909
28137
|
this.maybeAppendRuntimeRecoveryMessage(runtime);
|
|
27910
28138
|
let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
@@ -28066,7 +28294,22 @@ var CliProviderInstance = class {
|
|
|
28066
28294
|
};
|
|
28067
28295
|
}
|
|
28068
28296
|
updateSettings(newSettings) {
|
|
28069
|
-
|
|
28297
|
+
const runtimeMeshSettings = {};
|
|
28298
|
+
for (const key of [
|
|
28299
|
+
"meshNodeFor",
|
|
28300
|
+
"meshNodeId",
|
|
28301
|
+
"meshActiveTaskId",
|
|
28302
|
+
"meshCoordinatorFor",
|
|
28303
|
+
"meshCoordinatorDaemonId",
|
|
28304
|
+
"meshCoordinatorNodeId",
|
|
28305
|
+
"spawnedSessionVisibility",
|
|
28306
|
+
"launchedByCoordinator"
|
|
28307
|
+
]) {
|
|
28308
|
+
if (this.settings[key] !== void 0 && newSettings[key] === void 0) {
|
|
28309
|
+
runtimeMeshSettings[key] = this.settings[key];
|
|
28310
|
+
}
|
|
28311
|
+
}
|
|
28312
|
+
this.settings = { ...newSettings, ...runtimeMeshSettings };
|
|
28070
28313
|
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
28071
28314
|
this.monitor.updateConfig({
|
|
28072
28315
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
@@ -28157,6 +28400,8 @@ var CliProviderInstance = class {
|
|
|
28157
28400
|
const content = typeof input === "string" ? input.trim() : buildCliStructuredInputPrompt(input).trim();
|
|
28158
28401
|
if (!content) return;
|
|
28159
28402
|
const receivedAt = Date.now();
|
|
28403
|
+
this.lastAcknowledgedUserInputAt = receivedAt;
|
|
28404
|
+
this.externalBusyIdleFingerprint = "";
|
|
28160
28405
|
const dedupKey = `user_input_ack:${crypto4.createHash("sha256").update(`${this.instanceId}:${content}:${receivedAt}`).digest("hex").slice(0, 24)}`;
|
|
28161
28406
|
this.appendRuntimeMessage(buildChatMessage({
|
|
28162
28407
|
role: "user",
|
|
@@ -28305,6 +28550,50 @@ var CliProviderInstance = class {
|
|
|
28305
28550
|
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
28306
28551
|
return extractFinalSummaryFromMessages(evidence.messages);
|
|
28307
28552
|
}
|
|
28553
|
+
externalNativeFinalFingerprint(evidence) {
|
|
28554
|
+
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
28555
|
+
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
28556
|
+
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
28557
|
+
const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
|
|
28558
|
+
const receivedAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
28559
|
+
const probe = this.lastExternalCompletionProbe;
|
|
28560
|
+
return crypto4.createHash("sha256").update([
|
|
28561
|
+
this.type,
|
|
28562
|
+
this.providerSessionId || "",
|
|
28563
|
+
probe?.sourcePath || "",
|
|
28564
|
+
String(probe?.sourceMtimeMs || 0),
|
|
28565
|
+
String(receivedAt || 0),
|
|
28566
|
+
content.slice(-500)
|
|
28567
|
+
].join("\0")).digest("hex").slice(0, 24);
|
|
28568
|
+
}
|
|
28569
|
+
getExternalNativeFinalReconciliation(parsedMessages, adapterStatus) {
|
|
28570
|
+
const rawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
28571
|
+
if (!isCliGeneratingLikeStatus(rawStatus)) return null;
|
|
28572
|
+
if (hasNonEmptyCliModalButtons(adapterStatus?.activeModal ?? adapterStatus?.modal)) return null;
|
|
28573
|
+
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
28574
|
+
if (evidence.source !== "external-native" || !evidence.present) return null;
|
|
28575
|
+
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
28576
|
+
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
28577
|
+
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
28578
|
+
const lastMessageAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
28579
|
+
const sourceMtimeMs = Number(this.lastExternalCompletionProbe?.sourceMtimeMs || 0);
|
|
28580
|
+
const minEvidenceAt = Math.max(
|
|
28581
|
+
this.startedAt > 0 ? this.startedAt - 5e3 : 0,
|
|
28582
|
+
this.generatingStartedAt > 0 ? this.generatingStartedAt - 5e3 : 0,
|
|
28583
|
+
this.lastAcknowledgedUserInputAt > 0 ? this.lastAcknowledgedUserInputAt - 1e3 : 0
|
|
28584
|
+
);
|
|
28585
|
+
if (minEvidenceAt > 0 && lastMessageAt > 0 && lastMessageAt < minEvidenceAt && sourceMtimeMs < minEvidenceAt) {
|
|
28586
|
+
return null;
|
|
28587
|
+
}
|
|
28588
|
+
const finalSummary = extractFinalSummaryFromMessages(evidence.messages);
|
|
28589
|
+
if (!finalSummary) return null;
|
|
28590
|
+
const fingerprint = this.externalNativeFinalFingerprint(evidence);
|
|
28591
|
+
if (fingerprint === this.externalBusyIdleFingerprint) {
|
|
28592
|
+
return { fingerprint, finalSummary, evidence };
|
|
28593
|
+
}
|
|
28594
|
+
this.externalBusyIdleFingerprint = fingerprint;
|
|
28595
|
+
return { fingerprint, finalSummary, evidence };
|
|
28596
|
+
}
|
|
28308
28597
|
buildCompletedFinalizationDiagnostic(args) {
|
|
28309
28598
|
let parsed = null;
|
|
28310
28599
|
let parseError;
|
|
@@ -28375,17 +28664,18 @@ var CliProviderInstance = class {
|
|
|
28375
28664
|
if (typeof adapterAny?.responseBuffer === "string" && adapterAny.responseBuffer.trim()) return false;
|
|
28376
28665
|
return true;
|
|
28377
28666
|
}
|
|
28378
|
-
getCompletedFinalizationBlock(latestVisibleStatus, pending) {
|
|
28667
|
+
getCompletedFinalizationBlock(latestVisibleStatus, pending, opts) {
|
|
28379
28668
|
if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
|
|
28380
28669
|
const adapterAny = this.adapter;
|
|
28381
28670
|
const approvalResolvedIdle = pending.previousStatus === "waiting_approval";
|
|
28382
|
-
|
|
28671
|
+
const externalNativeFinal = opts?.externalNativeFinal || null;
|
|
28672
|
+
if (!approvalResolvedIdle && !externalNativeFinal) {
|
|
28383
28673
|
if (adapterAny?.isWaitingForResponse === true) return { reason: "adapter_waiting_for_response", terminal: true };
|
|
28384
28674
|
if (adapterAny?.currentTurnScope) return { reason: "adapter_turn_scope_active", terminal: true };
|
|
28385
28675
|
if (this.hasAdapterPendingResponse()) return { reason: "adapter_pending_response", terminal: true };
|
|
28386
28676
|
}
|
|
28387
28677
|
const partial = typeof this.adapter.getPartialResponse === "function" ? this.adapter.getPartialResponse() : "";
|
|
28388
|
-
if (typeof partial === "string" && partial.trim()) return { reason: "partial_response_pending", terminal: true };
|
|
28678
|
+
if (!externalNativeFinal && typeof partial === "string" && partial.trim()) return { reason: "partial_response_pending", terminal: true };
|
|
28389
28679
|
let parsed;
|
|
28390
28680
|
try {
|
|
28391
28681
|
parsed = this.adapter.getScriptParsedStatus();
|
|
@@ -28395,6 +28685,7 @@ var CliProviderInstance = class {
|
|
|
28395
28685
|
const parsedStatus = typeof parsed?.status === "string" ? parsed.status : "unknown";
|
|
28396
28686
|
if (parsedStatus !== "idle") {
|
|
28397
28687
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
28688
|
+
if (externalNativeFinal && isCliGeneratingLikeStatus(parsedStatus)) return null;
|
|
28398
28689
|
if (this.shouldSuppressStaleParsedBusyStatus(parsed, adapterStatus)) return null;
|
|
28399
28690
|
return { reason: `parsed_status:${parsedStatus}`, terminal: isCliGeneratingLikeStatus(parsedStatus) };
|
|
28400
28691
|
}
|
|
@@ -28447,14 +28738,15 @@ var CliProviderInstance = class {
|
|
|
28447
28738
|
}
|
|
28448
28739
|
const latestStatus = this.adapter.getStatus({ allowParse: false });
|
|
28449
28740
|
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
28450
|
-
const
|
|
28741
|
+
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, latestStatus);
|
|
28742
|
+
const latestVisibleStatus = externalNativeFinal && isCliGeneratingLikeStatus(latestStatus.status) ? "idle" : latestAutoApproveActive ? "generating" : latestStatus.status;
|
|
28451
28743
|
if (latestVisibleStatus !== "idle") {
|
|
28452
28744
|
LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
|
|
28453
28745
|
this.completedDebouncePending = null;
|
|
28454
28746
|
this.completedDebounceTimer = null;
|
|
28455
28747
|
return;
|
|
28456
28748
|
}
|
|
28457
|
-
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
28749
|
+
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending, { externalNativeFinal });
|
|
28458
28750
|
if (block2) {
|
|
28459
28751
|
const blockReason = block2.reason;
|
|
28460
28752
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
@@ -28495,7 +28787,18 @@ var CliProviderInstance = class {
|
|
|
28495
28787
|
chatTitle: pending.chatTitle,
|
|
28496
28788
|
duration: pending.duration,
|
|
28497
28789
|
timestamp: pending.timestamp,
|
|
28498
|
-
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
|
|
28790
|
+
finalSummary: externalNativeFinal?.finalSummary || this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages),
|
|
28791
|
+
...externalNativeFinal ? {
|
|
28792
|
+
completionDiagnostic: {
|
|
28793
|
+
providerType: this.type,
|
|
28794
|
+
sessionId: this.instanceId,
|
|
28795
|
+
providerSessionId: this.providerSessionId || null,
|
|
28796
|
+
reconciliationReason: "external_native_final_assistant_while_adapter_busy",
|
|
28797
|
+
finalAssistantPresent: true,
|
|
28798
|
+
finalAssistantEvidenceSource: externalNativeFinal.evidence.source,
|
|
28799
|
+
externalFinalFingerprint: externalNativeFinal.fingerprint
|
|
28800
|
+
}
|
|
28801
|
+
} : {}
|
|
28499
28802
|
});
|
|
28500
28803
|
this.completedDebouncePending = null;
|
|
28501
28804
|
this.completedDebounceTimer = null;
|
|
@@ -28551,7 +28854,8 @@ var CliProviderInstance = class {
|
|
|
28551
28854
|
const parsedStatus = null;
|
|
28552
28855
|
const rawStatus = adapterStatus.status;
|
|
28553
28856
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
|
|
28554
|
-
const
|
|
28857
|
+
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
|
|
28858
|
+
const newStatus = externalNativeFinal && isCliGeneratingLikeStatus(rawStatus) ? "idle" : autoApproveActive ? "generating" : rawStatus;
|
|
28555
28859
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
28556
28860
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
28557
28861
|
const partial = this.adapter.getPartialResponse();
|
|
@@ -30552,15 +30856,29 @@ function colorize(color, text) {
|
|
|
30552
30856
|
const fn = chalkApi?.[color];
|
|
30553
30857
|
return typeof fn === "function" ? fn(text) : text;
|
|
30554
30858
|
}
|
|
30555
|
-
var
|
|
30556
|
-
ADHDEV_INLINE_MESH
|
|
30557
|
-
ADHDEV_MCP_TRANSPORT
|
|
30558
|
-
ADHDEV_MESH_ID
|
|
30559
|
-
HERMES_EPHEMERAL_SYSTEM_PROMPT
|
|
30560
|
-
|
|
30859
|
+
var DEFAULT_COORDINATOR_DELEGATED_ENV_UNSETS = [
|
|
30860
|
+
"ADHDEV_INLINE_MESH",
|
|
30861
|
+
"ADHDEV_MCP_TRANSPORT",
|
|
30862
|
+
"ADHDEV_MESH_ID",
|
|
30863
|
+
"HERMES_EPHEMERAL_SYSTEM_PROMPT"
|
|
30864
|
+
];
|
|
30561
30865
|
function hasCliArg(args, flag) {
|
|
30562
30866
|
return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
30563
30867
|
}
|
|
30868
|
+
function hasConfigOverride(args, key) {
|
|
30869
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
30870
|
+
const arg = args[index];
|
|
30871
|
+
const next = args[index + 1];
|
|
30872
|
+
if ((arg === "-c" || arg === "--config") && typeof next === "string") {
|
|
30873
|
+
if (next === key || next.startsWith(`${key}=`) || next.startsWith(`${key}.`)) return true;
|
|
30874
|
+
}
|
|
30875
|
+
if (arg.startsWith("--config=")) {
|
|
30876
|
+
const value = arg.slice("--config=".length);
|
|
30877
|
+
if (value === key || value.startsWith(`${key}=`) || value.startsWith(`${key}.`)) return true;
|
|
30878
|
+
}
|
|
30879
|
+
}
|
|
30880
|
+
return false;
|
|
30881
|
+
}
|
|
30564
30882
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
30565
30883
|
const baseDir = path23.join(os17.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
30566
30884
|
(0, import_fs12.mkdirSync)(baseDir, { recursive: true });
|
|
@@ -30570,11 +30888,30 @@ function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
|
30570
30888
|
return filePath;
|
|
30571
30889
|
}
|
|
30572
30890
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
30573
|
-
const cliType = String(input.cliType || "").trim();
|
|
30574
30891
|
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
30575
|
-
const env = { ...input.env || {}
|
|
30576
|
-
|
|
30577
|
-
|
|
30892
|
+
const env = { ...input.env || {} };
|
|
30893
|
+
const envUnsets = new Set(DEFAULT_COORDINATOR_DELEGATED_ENV_UNSETS);
|
|
30894
|
+
for (const key of input.isolation?.env?.unset || []) {
|
|
30895
|
+
if (typeof key === "string" && key.trim()) envUnsets.add(key.trim());
|
|
30896
|
+
}
|
|
30897
|
+
for (const key of envUnsets) env[key] = "";
|
|
30898
|
+
for (const rule of input.isolation?.args || []) {
|
|
30899
|
+
if (!rule || typeof rule !== "object") continue;
|
|
30900
|
+
if (rule.mode === "empty_mcp_config") {
|
|
30901
|
+
if (rule.flag && !hasCliArg(cliArgs, rule.flag)) {
|
|
30902
|
+
cliArgs.unshift(rule.flag, ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
30903
|
+
}
|
|
30904
|
+
if (rule.strictFlag && !hasCliArg(cliArgs, rule.strictFlag)) {
|
|
30905
|
+
cliArgs.unshift(rule.strictFlag);
|
|
30906
|
+
}
|
|
30907
|
+
continue;
|
|
30908
|
+
}
|
|
30909
|
+
if (rule.mode === "config_override") {
|
|
30910
|
+
const key = String(rule.dedupeKey || rule.key || "").trim();
|
|
30911
|
+
const flag = String(rule.flag || "").trim();
|
|
30912
|
+
if (!key || !flag || hasConfigOverride(cliArgs, key)) continue;
|
|
30913
|
+
cliArgs.unshift(flag, `${rule.key}=${rule.value}`);
|
|
30914
|
+
}
|
|
30578
30915
|
}
|
|
30579
30916
|
return { cliArgs, env };
|
|
30580
30917
|
}
|
|
@@ -31237,22 +31574,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
31237
31574
|
const dir = resolved.path;
|
|
31238
31575
|
const launchSource = resolved.source;
|
|
31239
31576
|
if (!cliType) throw new Error("cliType required");
|
|
31577
|
+
const providerType = this.providerLoader.resolveAlias(cliType);
|
|
31578
|
+
const provLookup = this.providerLoader.getMeta(providerType);
|
|
31240
31579
|
const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
31241
31580
|
const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
|
|
31242
31581
|
cliType,
|
|
31243
31582
|
workspace: dir,
|
|
31244
31583
|
cliArgs: args?.cliArgs,
|
|
31245
|
-
env: args?.env
|
|
31584
|
+
env: args?.env,
|
|
31585
|
+
isolation: provLookup?.meshCoordinator?.delegatedWorkerIsolation
|
|
31246
31586
|
}) : null;
|
|
31247
|
-
const
|
|
31248
|
-
const provTrust =
|
|
31587
|
+
const provMeta = provLookup;
|
|
31588
|
+
const provTrust = provMeta?._sourceTrust;
|
|
31249
31589
|
if (provTrust === "external-untrusted" && args?.confirmExternalUntrusted !== true) {
|
|
31250
31590
|
return {
|
|
31251
31591
|
success: false,
|
|
31252
31592
|
error: "untrusted_external_provider",
|
|
31253
31593
|
provider: {
|
|
31254
31594
|
type: provLookup?.type ?? cliType,
|
|
31255
|
-
sourceName:
|
|
31595
|
+
sourceName: provMeta?._sourceName ?? null,
|
|
31256
31596
|
trust: provTrust
|
|
31257
31597
|
},
|
|
31258
31598
|
hint: "Resend launch_cli with confirmExternalUntrusted=true after the user explicitly approves running JavaScript from this 3rd-party source."
|
|
@@ -31724,7 +32064,10 @@ function validateMeshCoordinator(raw, errors) {
|
|
|
31724
32064
|
if (meshCoordinator.reason !== void 0 && (typeof meshCoordinator.reason !== "string" || !meshCoordinator.reason.trim())) {
|
|
31725
32065
|
errors.push("meshCoordinator.reason must be a non-empty string when provided");
|
|
31726
32066
|
}
|
|
31727
|
-
|
|
32067
|
+
validateMeshCoordinatorMcpConfig(meshCoordinator.mcpConfig, errors);
|
|
32068
|
+
validateMeshCoordinatorDelegatedWorkerIsolation(meshCoordinator.delegatedWorkerIsolation, errors);
|
|
32069
|
+
}
|
|
32070
|
+
function validateMeshCoordinatorMcpConfig(mcpConfig, errors) {
|
|
31728
32071
|
if (mcpConfig === void 0) return;
|
|
31729
32072
|
if (!mcpConfig || typeof mcpConfig !== "object" || Array.isArray(mcpConfig)) {
|
|
31730
32073
|
errors.push("meshCoordinator.mcpConfig must be an object");
|
|
@@ -31765,6 +32108,56 @@ function validateMeshCoordinator(raw, errors) {
|
|
|
31765
32108
|
}
|
|
31766
32109
|
}
|
|
31767
32110
|
}
|
|
32111
|
+
function validateMeshCoordinatorDelegatedWorkerIsolation(raw, errors) {
|
|
32112
|
+
if (raw === void 0) return;
|
|
32113
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
32114
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation must be an object");
|
|
32115
|
+
return;
|
|
32116
|
+
}
|
|
32117
|
+
const isolation = raw;
|
|
32118
|
+
const env = isolation.env;
|
|
32119
|
+
if (env !== void 0) {
|
|
32120
|
+
if (!env || typeof env !== "object" || Array.isArray(env)) {
|
|
32121
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation.env must be an object");
|
|
32122
|
+
} else {
|
|
32123
|
+
const unset = env.unset;
|
|
32124
|
+
if (unset !== void 0 && (!Array.isArray(unset) || unset.some((key) => typeof key !== "string" || !key.trim()))) {
|
|
32125
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation.env.unset must be an array of non-empty strings");
|
|
32126
|
+
}
|
|
32127
|
+
}
|
|
32128
|
+
}
|
|
32129
|
+
const args = isolation.args;
|
|
32130
|
+
if (args === void 0) return;
|
|
32131
|
+
if (!Array.isArray(args)) {
|
|
32132
|
+
errors.push("meshCoordinator.delegatedWorkerIsolation.args must be an array");
|
|
32133
|
+
return;
|
|
32134
|
+
}
|
|
32135
|
+
for (const [index, rule] of args.entries()) {
|
|
32136
|
+
const prefix = `meshCoordinator.delegatedWorkerIsolation.args[${index}]`;
|
|
32137
|
+
if (!rule || typeof rule !== "object" || Array.isArray(rule)) {
|
|
32138
|
+
errors.push(`${prefix} must be an object`);
|
|
32139
|
+
continue;
|
|
32140
|
+
}
|
|
32141
|
+
const item = rule;
|
|
32142
|
+
const mode = item.mode;
|
|
32143
|
+
if (mode !== "empty_mcp_config" && mode !== "config_override") {
|
|
32144
|
+
errors.push(`${prefix}.mode must be one of: empty_mcp_config, config_override`);
|
|
32145
|
+
continue;
|
|
32146
|
+
}
|
|
32147
|
+
for (const key of mode === "empty_mcp_config" ? ["flag"] : ["flag", "key", "value"]) {
|
|
32148
|
+
const value = item[key];
|
|
32149
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
32150
|
+
errors.push(`${prefix}.${key} must be a non-empty string`);
|
|
32151
|
+
}
|
|
32152
|
+
}
|
|
32153
|
+
for (const key of ["strictFlag", "dedupeKey"]) {
|
|
32154
|
+
const value = item[key];
|
|
32155
|
+
if (value !== void 0 && (typeof value !== "string" || !value.trim())) {
|
|
32156
|
+
errors.push(`${prefix}.${key} must be a non-empty string when provided`);
|
|
32157
|
+
}
|
|
32158
|
+
}
|
|
32159
|
+
}
|
|
32160
|
+
}
|
|
31768
32161
|
function validateControl(control, errors) {
|
|
31769
32162
|
if (!control || typeof control !== "object") {
|
|
31770
32163
|
errors.push("controls: each control must be an object");
|
|
@@ -37426,9 +37819,14 @@ function readCachedInlineMeshActiveSessionDetails(node) {
|
|
|
37426
37819
|
node?.provider_type
|
|
37427
37820
|
),
|
|
37428
37821
|
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
37822
|
+
chatStatus: readStringValue(fallbackSession.chatStatus, fallbackSession.chat_status),
|
|
37429
37823
|
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
37430
37824
|
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
37431
37825
|
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
37826
|
+
role: readStringValue(fallbackSession.role) ?? null,
|
|
37827
|
+
isSelfCoordinator: fallbackSession.isSelfCoordinator === true || fallbackSession.is_self_coordinator === true,
|
|
37828
|
+
createdAt: readStringValue(fallbackSession.createdAt, fallbackSession.created_at) ?? null,
|
|
37829
|
+
startedAt: readStringValue(fallbackSession.startedAt, fallbackSession.started_at) ?? null,
|
|
37432
37830
|
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
37433
37831
|
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
37434
37832
|
isCached: true
|
|
@@ -37569,15 +37967,26 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
37569
37967
|
};
|
|
37570
37968
|
}
|
|
37571
37969
|
function summarizeMeshSessionRecord(record) {
|
|
37970
|
+
const meta = readObjectRecord(record?.meta);
|
|
37971
|
+
const isSelfCoordinator = Boolean(readStringValue(meta.meshCoordinatorFor));
|
|
37972
|
+
const chatStatus = readStringValue(record?.chatStatus, record?.activeChat?.status, meta.chatStatus, meta.sessionStatus);
|
|
37973
|
+
const state = readLiveMeshSessionState(record);
|
|
37974
|
+
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;
|
|
37572
37975
|
return {
|
|
37573
37976
|
sessionId: readStringValue(record?.sessionId) || "unknown",
|
|
37574
37977
|
providerType: readStringValue(record?.providerType),
|
|
37575
|
-
state
|
|
37978
|
+
state,
|
|
37979
|
+
chatStatus,
|
|
37576
37980
|
lifecycle: readStringValue(record?.lifecycle),
|
|
37577
37981
|
surfaceKind: getSessionHostSurfaceKind(record),
|
|
37578
|
-
recoveryState: readStringValue(
|
|
37982
|
+
recoveryState: readStringValue(meta.runtimeRecoveryState) ?? null,
|
|
37579
37983
|
workspace: readStringValue(record?.workspace) ?? null,
|
|
37580
37984
|
title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
|
|
37985
|
+
role: isSelfCoordinator ? "coordinator" : readStringValue(meta.meshRole, meta.role) ?? null,
|
|
37986
|
+
isSelfCoordinator,
|
|
37987
|
+
statusNote,
|
|
37988
|
+
createdAt: toIsoTimestamp(record?.createdAt ?? record?.created_at),
|
|
37989
|
+
startedAt: toIsoTimestamp(record?.startedAt ?? record?.started_at ?? record?.spawnedAtMs ?? record?.spawned_at_ms),
|
|
37581
37990
|
lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
|
|
37582
37991
|
isCached: false
|
|
37583
37992
|
};
|
|
@@ -38601,6 +39010,15 @@ var DaemonCommandRouter = class {
|
|
|
38601
39010
|
this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next), queueRevision: getMeshQueueRevision(meshId) });
|
|
38602
39011
|
return next;
|
|
38603
39012
|
}
|
|
39013
|
+
getCachedInlineMeshNodes() {
|
|
39014
|
+
const nodes = [];
|
|
39015
|
+
for (const mesh of this.inlineMeshCache.values()) {
|
|
39016
|
+
if (Array.isArray(mesh?.nodes)) {
|
|
39017
|
+
nodes.push(...mesh.nodes);
|
|
39018
|
+
}
|
|
39019
|
+
}
|
|
39020
|
+
return nodes;
|
|
39021
|
+
}
|
|
38604
39022
|
getCachedInlineMesh(meshId, inlineMesh) {
|
|
38605
39023
|
if (inlineMesh && typeof inlineMesh === "object") {
|
|
38606
39024
|
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
@@ -38649,6 +39067,7 @@ var DaemonCommandRouter = class {
|
|
|
38649
39067
|
}
|
|
38650
39068
|
invalidateAggregateMeshStatus(meshId) {
|
|
38651
39069
|
this.aggregateMeshStatusCache.delete(meshId);
|
|
39070
|
+
this.deps.onMeshStateChange?.(meshId);
|
|
38652
39071
|
}
|
|
38653
39072
|
async requireMeshHostMutationOwner(meshId, inlineMesh, operation) {
|
|
38654
39073
|
const meshRecord = await this.getMeshForCommand(meshId, inlineMesh, { preferInline: true });
|
|
@@ -50134,6 +50553,7 @@ async function initDaemonComponents(config) {
|
|
|
50134
50553
|
},
|
|
50135
50554
|
onIdeConnected: () => poller?.start(),
|
|
50136
50555
|
onStatusChange: config.onStatusChange,
|
|
50556
|
+
onMeshStateChange: config.onMeshStateChange,
|
|
50137
50557
|
onPostChatCommand: config.onPostChatCommand,
|
|
50138
50558
|
sessionHostControl: config.sessionHostControl,
|
|
50139
50559
|
statusInstanceId: config.statusInstanceId,
|
|
@@ -50727,6 +51147,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
50727
51147
|
probeCdpPort,
|
|
50728
51148
|
queuePendingMeshCoordinatorEvent,
|
|
50729
51149
|
readAntigravityCliSession,
|
|
51150
|
+
readCachedInlineMeshActiveSessionDetails,
|
|
50730
51151
|
readChatHistory,
|
|
50731
51152
|
readClaudeCliSession,
|
|
50732
51153
|
readCodexCliSession,
|