@adhdev/daemon-standalone 1.0.18-rc.10 → 1.0.18-rc.11
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/index.js +691 -34
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-Be0j0_PU.js → index-DB3QU2sn.js} +51 -51
- package/public/assets/index-DTkEOmrO.css +1 -0
- package/public/index.html +2 -2
- package/vendor/mcp-server/index.js +56 -0
- package/vendor/mcp-server/index.js.map +1 -1
- package/public/assets/index-CQVaCclg.css +0 -1
package/dist/index.js
CHANGED
|
@@ -30265,10 +30265,10 @@ var require_dist3 = __commonJS({
|
|
|
30265
30265
|
}
|
|
30266
30266
|
function getDaemonBuildInfo() {
|
|
30267
30267
|
if (cached2) return cached2;
|
|
30268
|
-
const commit = readInjected(true ? "
|
|
30269
|
-
const commitShort = readInjected(true ? "
|
|
30270
|
-
const version2 = readInjected(true ? "1.0.18-rc.
|
|
30271
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
30268
|
+
const commit = readInjected(true ? "99f9c20bcf4ceec1e7ab2bfe6c8f641ca88da360" : void 0) ?? "unknown";
|
|
30269
|
+
const commitShort = readInjected(true ? "99f9c20b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30270
|
+
const version2 = readInjected(true ? "1.0.18-rc.11" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30271
|
+
const builtAt = readInjected(true ? "2026-07-22T10:19:28.847Z" : void 0);
|
|
30272
30272
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30273
30273
|
return cached2;
|
|
30274
30274
|
}
|
|
@@ -32474,6 +32474,51 @@ ${error48.message || ""}`;
|
|
|
32474
32474
|
import_node_crypto = require("crypto");
|
|
32475
32475
|
}
|
|
32476
32476
|
});
|
|
32477
|
+
var dist_exports = {};
|
|
32478
|
+
__export2(dist_exports, {
|
|
32479
|
+
CANONICAL_MESH_TOOL_COUNT: () => CANONICAL_MESH_TOOL_COUNT,
|
|
32480
|
+
CANONICAL_MESH_TOOL_NAMES: () => CANONICAL_MESH_TOOL_NAMES,
|
|
32481
|
+
DEFAULT_DIFFICULTY_BRAINS: () => DEFAULT_DIFFICULTY_BRAINS,
|
|
32482
|
+
MAGI_RAW_ANSWER_CAP: () => MAGI_RAW_ANSWER_CAP,
|
|
32483
|
+
MESH_TASK_DIFFICULTIES: () => MESH_TASK_DIFFICULTIES,
|
|
32484
|
+
STATUS_PROBE_ARG_KEY: () => STATUS_PROBE_ARG_KEY,
|
|
32485
|
+
argsCarryStatusProbeMarker: () => argsCarryStatusProbeMarker,
|
|
32486
|
+
canonicalDaemonId: () => canonicalDaemonId,
|
|
32487
|
+
daemonIdsEquivalent: () => daemonIdsEquivalent,
|
|
32488
|
+
deriveSlotsFromLegacy: () => deriveSlotsFromLegacy,
|
|
32489
|
+
expandDaemonIdForms: () => expandDaemonIdForms,
|
|
32490
|
+
hasGitStatusEvidence: () => hasGitStatusEvidence,
|
|
32491
|
+
interpolateArgs: () => interpolateArgs,
|
|
32492
|
+
interpolateString: () => interpolateString,
|
|
32493
|
+
isMeshTaskDifficulty: () => isMeshTaskDifficulty,
|
|
32494
|
+
joinRepoPath: () => joinRepoPath,
|
|
32495
|
+
machineCoreFromDaemonId: () => machineCoreFromDaemonId,
|
|
32496
|
+
meshNodeIdMatches: () => meshNodeIdMatches,
|
|
32497
|
+
meshWorkspacesEquivalent: () => meshWorkspacesEquivalent,
|
|
32498
|
+
normalizeBrainSlot: () => normalizeBrainSlot,
|
|
32499
|
+
normalizeDifficultyBrainMap: () => normalizeDifficultyBrainMap,
|
|
32500
|
+
normalizeGitStatus: () => normalizeGitStatus,
|
|
32501
|
+
normalizeMeshNodeId: () => normalizeMeshNodeId,
|
|
32502
|
+
normalizeMeshSessionRecord: () => normalizeMeshSessionRecord,
|
|
32503
|
+
normalizeMeshWorkspaceForCompare: () => normalizeMeshWorkspaceForCompare,
|
|
32504
|
+
normalizeNodeCapabilitySlot: () => normalizeNodeCapabilitySlot,
|
|
32505
|
+
normalizeNodeCapabilitySlots: () => normalizeNodeCapabilitySlots,
|
|
32506
|
+
normalizeThinkingLevel: () => normalizeThinkingLevel,
|
|
32507
|
+
parseJsonRecord: () => parseJsonRecord,
|
|
32508
|
+
pickBestTransitGitStatus: () => pickBestTransitGitStatus,
|
|
32509
|
+
readBoolean: () => readBoolean,
|
|
32510
|
+
readGitSubmodules: () => readGitSubmodules,
|
|
32511
|
+
readNumber: () => readNumber,
|
|
32512
|
+
readRecord: () => readRecord,
|
|
32513
|
+
readString: () => readString2,
|
|
32514
|
+
readStringArray: () => readStringArray2,
|
|
32515
|
+
scoreGitStatusCandidate: () => scoreGitStatusCandidate,
|
|
32516
|
+
scoreGitUpstreamFreshness: () => scoreGitUpstreamFreshness,
|
|
32517
|
+
sessionIdsEquivalent: () => sessionIdsEquivalent,
|
|
32518
|
+
stripStatusProbeMarker: () => stripStatusProbeMarker,
|
|
32519
|
+
summarizeGitShape: () => summarizeGitShape,
|
|
32520
|
+
withStatusProbeMarker: () => withStatusProbeMarker
|
|
32521
|
+
});
|
|
32477
32522
|
function readRecord(value) {
|
|
32478
32523
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
32479
32524
|
}
|
|
@@ -32497,6 +32542,21 @@ ${error48.message || ""}`;
|
|
|
32497
32542
|
}
|
|
32498
32543
|
return void 0;
|
|
32499
32544
|
}
|
|
32545
|
+
function readStringArray2(value) {
|
|
32546
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
32547
|
+
}
|
|
32548
|
+
function parseJsonRecord(value) {
|
|
32549
|
+
if (!value) return {};
|
|
32550
|
+
if (typeof value === "object") return readRecord(value);
|
|
32551
|
+
if (typeof value !== "string") return {};
|
|
32552
|
+
const trimmed = value.trim();
|
|
32553
|
+
if (!trimmed) return {};
|
|
32554
|
+
try {
|
|
32555
|
+
return readRecord(JSON.parse(trimmed));
|
|
32556
|
+
} catch {
|
|
32557
|
+
return {};
|
|
32558
|
+
}
|
|
32559
|
+
}
|
|
32500
32560
|
function joinRepoPath(root, relativePath) {
|
|
32501
32561
|
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
32502
32562
|
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
@@ -32637,12 +32697,48 @@ ${error48.message || ""}`;
|
|
|
32637
32697
|
}
|
|
32638
32698
|
return best?.git;
|
|
32639
32699
|
}
|
|
32700
|
+
function deriveSyntheticSessionId(record2) {
|
|
32701
|
+
const parts = [
|
|
32702
|
+
readString2(record2.workspace),
|
|
32703
|
+
readString2(record2.providerType, record2.provider),
|
|
32704
|
+
readString2(record2.role),
|
|
32705
|
+
readString2(record2.state, record2.status),
|
|
32706
|
+
readString2(record2.title),
|
|
32707
|
+
readString2(record2.createdAt, record2.created_at),
|
|
32708
|
+
readString2(record2.startedAt, record2.started_at)
|
|
32709
|
+
].filter((part) => Boolean(part));
|
|
32710
|
+
if (parts.length === 0) return void 0;
|
|
32711
|
+
return `synthetic:${parts.join("|")}`;
|
|
32712
|
+
}
|
|
32640
32713
|
function sessionIdsEquivalent(a, b) {
|
|
32641
32714
|
const idA = readString2(a);
|
|
32642
32715
|
const idB = readString2(b);
|
|
32643
32716
|
if (!idA || !idB) return false;
|
|
32644
32717
|
return idA === idB;
|
|
32645
32718
|
}
|
|
32719
|
+
function normalizeMeshSessionRecord(entry) {
|
|
32720
|
+
const record2 = readRecord(entry);
|
|
32721
|
+
const sessionId = readString2(record2.sessionId, record2.session_id, record2.id) ?? deriveSyntheticSessionId(record2);
|
|
32722
|
+
if (!sessionId) return null;
|
|
32723
|
+
return {
|
|
32724
|
+
sessionId,
|
|
32725
|
+
...readString2(record2.providerType, record2.provider) ? { providerType: readString2(record2.providerType, record2.provider) } : {},
|
|
32726
|
+
...readString2(record2.state, record2.status) ? { state: readString2(record2.state, record2.status) } : {},
|
|
32727
|
+
...readString2(record2.chatStatus, record2.chat_status) ? { chatStatus: readString2(record2.chatStatus, record2.chat_status) } : {},
|
|
32728
|
+
...readString2(record2.lifecycle) ? { lifecycle: readString2(record2.lifecycle) } : {},
|
|
32729
|
+
...readString2(record2.surfaceKind, record2.surface_kind) ? { surfaceKind: readString2(record2.surfaceKind, record2.surface_kind) } : {},
|
|
32730
|
+
...readString2(record2.recoveryState, record2.recovery_state) ? { recoveryState: readString2(record2.recoveryState, record2.recovery_state) } : {},
|
|
32731
|
+
...readString2(record2.workspace) ? { workspace: readString2(record2.workspace) } : {},
|
|
32732
|
+
...readString2(record2.title) ? { title: readString2(record2.title) } : {},
|
|
32733
|
+
...readString2(record2.role) ? { role: readString2(record2.role) } : {},
|
|
32734
|
+
...readBoolean(record2.isSelfCoordinator, record2.is_self_coordinator) !== void 0 ? { isSelfCoordinator: readBoolean(record2.isSelfCoordinator, record2.is_self_coordinator) } : {},
|
|
32735
|
+
...readString2(record2.statusNote, record2.status_note) ? { statusNote: readString2(record2.statusNote, record2.status_note) } : {},
|
|
32736
|
+
...readString2(record2.createdAt, record2.created_at) ? { createdAt: readString2(record2.createdAt, record2.created_at) } : {},
|
|
32737
|
+
...readString2(record2.startedAt, record2.started_at) ? { startedAt: readString2(record2.startedAt, record2.started_at) } : {},
|
|
32738
|
+
...readString2(record2.lastActivityAt, record2.last_activity_at) ? { lastActivityAt: readString2(record2.lastActivityAt, record2.last_activity_at) } : {},
|
|
32739
|
+
...readBoolean(record2.isCached, record2.is_cached) !== void 0 ? { isCached: readBoolean(record2.isCached, record2.is_cached) } : {}
|
|
32740
|
+
};
|
|
32741
|
+
}
|
|
32646
32742
|
function normalizeMeshNodeId(node) {
|
|
32647
32743
|
const record2 = node && typeof node === "object" ? node : {};
|
|
32648
32744
|
return readString2(record2.id, record2.nodeId, record2.node_id);
|
|
@@ -32825,9 +32921,30 @@ ${error48.message || ""}`;
|
|
|
32825
32921
|
};
|
|
32826
32922
|
});
|
|
32827
32923
|
}
|
|
32924
|
+
function interpolateArgs(args, context) {
|
|
32925
|
+
const result = {};
|
|
32926
|
+
for (const [k, v] of Object.entries(args)) {
|
|
32927
|
+
result[k] = typeof v === "string" ? interpolateString(v, context) : v;
|
|
32928
|
+
}
|
|
32929
|
+
return result;
|
|
32930
|
+
}
|
|
32931
|
+
function interpolateString(template, ctx) {
|
|
32932
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key2) => {
|
|
32933
|
+
const val = ctx[key2];
|
|
32934
|
+
return val !== void 0 ? String(val) : `{{${key2}}}`;
|
|
32935
|
+
});
|
|
32936
|
+
}
|
|
32828
32937
|
function withStatusProbeMarker(args = {}) {
|
|
32829
32938
|
return { ...args, [STATUS_PROBE_ARG_KEY]: true };
|
|
32830
32939
|
}
|
|
32940
|
+
function argsCarryStatusProbeMarker(args) {
|
|
32941
|
+
return !!args && typeof args === "object" && args[STATUS_PROBE_ARG_KEY] === true;
|
|
32942
|
+
}
|
|
32943
|
+
function stripStatusProbeMarker(args) {
|
|
32944
|
+
if (!argsCarryStatusProbeMarker(args)) return args;
|
|
32945
|
+
const { [STATUS_PROBE_ARG_KEY]: _drop, ...rest } = args;
|
|
32946
|
+
return rest;
|
|
32947
|
+
}
|
|
32831
32948
|
var DAEMON_ID_PREFIXES;
|
|
32832
32949
|
var MAGI_RAW_ANSWER_CAP;
|
|
32833
32950
|
var MESH_TASK_DIFFICULTIES;
|
|
@@ -32865,6 +32982,7 @@ ${error48.message || ""}`;
|
|
|
32865
32982
|
"mesh_restart_daemon",
|
|
32866
32983
|
"mesh_checkpoint",
|
|
32867
32984
|
"mesh_approve",
|
|
32985
|
+
"mesh_answer_question",
|
|
32868
32986
|
"mesh_list_pending_approvals",
|
|
32869
32987
|
"mesh_clone_node",
|
|
32870
32988
|
"mesh_remove_node",
|
|
@@ -34314,6 +34432,42 @@ ${surfaced}`;
|
|
|
34314
34432
|
if (args.event === "agent:waiting_approval") {
|
|
34315
34433
|
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
34316
34434
|
}
|
|
34435
|
+
if (args.event === "agent:waiting_choice") {
|
|
34436
|
+
const prompt = args.metadataEvent.interactivePrompt;
|
|
34437
|
+
const promptId = readNonEmptyString(args.metadataEvent.promptId) || prompt && readNonEmptyString(prompt.promptId);
|
|
34438
|
+
const lines = [
|
|
34439
|
+
`[System] ${args.nodeLabel} is asking a question and is waiting for your answer${metadata}.`
|
|
34440
|
+
];
|
|
34441
|
+
const questions = Array.isArray(prompt?.questions) ? prompt.questions : [];
|
|
34442
|
+
if (questions.length > 0) {
|
|
34443
|
+
for (const q of questions) {
|
|
34444
|
+
const header = readNonEmptyString(q.header);
|
|
34445
|
+
const question = readNonEmptyString(q.question);
|
|
34446
|
+
const multiSelect = q.multiSelect === true;
|
|
34447
|
+
if (question) {
|
|
34448
|
+
lines.push(`
|
|
34449
|
+
**${header ? `${header}: ` : ""}${question}**${multiSelect ? " (select one or more)" : ""}`);
|
|
34450
|
+
}
|
|
34451
|
+
const options = Array.isArray(q.options) ? q.options : [];
|
|
34452
|
+
options.forEach((opt, i) => {
|
|
34453
|
+
const record2 = opt && typeof opt === "object" ? opt : {};
|
|
34454
|
+
const label = readNonEmptyString(record2.label);
|
|
34455
|
+
if (!label) return;
|
|
34456
|
+
const description = readNonEmptyString(record2.description);
|
|
34457
|
+
lines.push(` ${i + 1}. ${label}${description ? ` \u2014 ${description}` : ""}`);
|
|
34458
|
+
});
|
|
34459
|
+
}
|
|
34460
|
+
} else {
|
|
34461
|
+
const modalMessage = readNonEmptyString(args.metadataEvent.modalMessage);
|
|
34462
|
+
if (modalMessage) lines.push(`
|
|
34463
|
+
${modalMessage}`);
|
|
34464
|
+
}
|
|
34465
|
+
lines.push(
|
|
34466
|
+
`
|
|
34467
|
+
Answer with mesh_answer_question(node_id, session_id${promptId ? `, promptId: "${promptId}"` : ""}, answers). Do NOT use mesh_approve \u2014 that only resolves yes/no consent modals, not a question. Use mesh_read_chat once if you need the full context first.`
|
|
34468
|
+
);
|
|
34469
|
+
return lines.join("\n");
|
|
34470
|
+
}
|
|
34317
34471
|
if (args.event === "agent:stopped") {
|
|
34318
34472
|
const rc = args.recoveryContext;
|
|
34319
34473
|
if (rc && rc.consecutiveNodeFailures > 0) {
|
|
@@ -35831,6 +35985,7 @@ Next step: ${nextStep}`;
|
|
|
35831
35985
|
requeueTask: () => requeueTask,
|
|
35832
35986
|
resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
|
|
35833
35987
|
resolveNotBefore: () => resolveNotBefore,
|
|
35988
|
+
takeCancelledTaskAssignment: () => takeCancelledTaskAssignment,
|
|
35834
35989
|
taskDependenciesSatisfied: () => taskDependenciesSatisfied,
|
|
35835
35990
|
updateDirectDispatchStatus: () => updateDirectDispatchStatus,
|
|
35836
35991
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
@@ -36390,6 +36545,10 @@ Next step: ${nextStep}`;
|
|
|
36390
36545
|
const result = withQueueLock(meshId, () => {
|
|
36391
36546
|
const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
|
|
36392
36547
|
if (!entry) return null;
|
|
36548
|
+
if (!opts?.force && TERMINAL_TASK_STATUSES.has(entry.status) && !TERMINAL_TASK_STATUSES.has(status)) {
|
|
36549
|
+
LOG2.debug("MeshQueue", `Refusing updateTaskStatus(${taskId} \u2192 ${status}) on mesh ${meshId}: row is terminal (${entry.status}). A late writer (e.g. dispatch-failure requeue) must not resurrect a cancelled/completed/failed task. Pass force to override.`);
|
|
36550
|
+
return { entry, cascaded: [] };
|
|
36551
|
+
}
|
|
36393
36552
|
entry.status = status;
|
|
36394
36553
|
MeshRuntimeStore.getInstance().updateQueueEntry(entry);
|
|
36395
36554
|
if (status !== "assigned") endTaskDispatchInFlight(meshId, taskId);
|
|
@@ -36415,17 +36574,34 @@ Next step: ${nextStep}`;
|
|
|
36415
36574
|
const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
|
|
36416
36575
|
if (!entry) return null;
|
|
36417
36576
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36577
|
+
const priorAssignment = entry.assignedSessionId ? {
|
|
36578
|
+
sessionId: entry.assignedSessionId,
|
|
36579
|
+
nodeId: entry.assignedNodeId,
|
|
36580
|
+
providerType: entry.assignedProviderType
|
|
36581
|
+
} : void 0;
|
|
36418
36582
|
entry.status = "cancelled";
|
|
36419
36583
|
entry.cancelledAt = now;
|
|
36420
36584
|
if (opts?.reason) entry.cancelReason = opts.reason;
|
|
36585
|
+
delete entry.assignedNodeId;
|
|
36586
|
+
delete entry.assignedSessionId;
|
|
36587
|
+
delete entry.assignedProviderType;
|
|
36588
|
+
delete entry.dispatchTimestamp;
|
|
36589
|
+
entry.dispatchNonce = (entry.dispatchNonce || 0) + 1;
|
|
36421
36590
|
MeshRuntimeStore.getInstance().updateQueueEntry(entry);
|
|
36422
36591
|
endTaskDispatchInFlight(meshId, taskId);
|
|
36423
36592
|
const cascaded = propagateDependencyFailure(meshId, taskId);
|
|
36424
|
-
return { entry, cascaded };
|
|
36593
|
+
return { entry, cascaded, priorAssignment };
|
|
36425
36594
|
});
|
|
36426
36595
|
if (result) scheduleMissionCloseCandidateCheck(meshId, [result.entry, ...result.cascaded]);
|
|
36596
|
+
if (result?.priorAssignment) lastCancelledTaskAssignment.set(`${meshId}::${taskId}`, result.priorAssignment);
|
|
36427
36597
|
return result ? result.entry : null;
|
|
36428
36598
|
}
|
|
36599
|
+
function takeCancelledTaskAssignment(meshId, taskId) {
|
|
36600
|
+
const key2 = `${meshId}::${taskId}`;
|
|
36601
|
+
const value = lastCancelledTaskAssignment.get(key2);
|
|
36602
|
+
if (value) lastCancelledTaskAssignment.delete(key2);
|
|
36603
|
+
return value;
|
|
36604
|
+
}
|
|
36429
36605
|
function requeueTask(meshId, taskId, opts) {
|
|
36430
36606
|
requireMeshHostQueueOwner(opts);
|
|
36431
36607
|
const result = withQueueLock(meshId, () => {
|
|
@@ -36652,6 +36828,8 @@ Next step: ${nextStep}`;
|
|
|
36652
36828
|
var GIT_MUTATION_SUBCOMMANDS;
|
|
36653
36829
|
var GIT_STASH_READONLY_SUBCOMMANDS;
|
|
36654
36830
|
var DEPENDENCY_FAILURE_TERMINALS;
|
|
36831
|
+
var TERMINAL_TASK_STATUSES;
|
|
36832
|
+
var lastCancelledTaskAssignment;
|
|
36655
36833
|
var MAX_STRANDED_RECLAIMS;
|
|
36656
36834
|
var REDRIVE_RECLAIM_REASONS;
|
|
36657
36835
|
var REDRIVE_SUPERSEDE_WINDOW_MS;
|
|
@@ -36722,6 +36900,8 @@ Next step: ${nextStep}`;
|
|
|
36722
36900
|
]);
|
|
36723
36901
|
GIT_STASH_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set(["list", "show"]);
|
|
36724
36902
|
DEPENDENCY_FAILURE_TERMINALS = /* @__PURE__ */ new Set(["failed", "cancelled"]);
|
|
36903
|
+
TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
36904
|
+
lastCancelledTaskAssignment = /* @__PURE__ */ new Map();
|
|
36725
36905
|
MAX_STRANDED_RECLAIMS = 3;
|
|
36726
36906
|
REDRIVE_RECLAIM_REASONS = /* @__PURE__ */ new Set([
|
|
36727
36907
|
"delivered_no_turn_deadline",
|
|
@@ -38822,7 +39002,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
38822
39002
|
function readNonEmptyString2(value) {
|
|
38823
39003
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
38824
39004
|
}
|
|
38825
|
-
function
|
|
39005
|
+
function readStringArray3(value) {
|
|
38826
39006
|
if (!Array.isArray(value)) return [];
|
|
38827
39007
|
return value.map((item) => readNonEmptyString2(item)).filter(Boolean);
|
|
38828
39008
|
}
|
|
@@ -38882,11 +39062,11 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
38882
39062
|
return {
|
|
38883
39063
|
status,
|
|
38884
39064
|
...readNonEmptyString2(raw.classification) ? { classification: readNonEmptyString2(raw.classification) } : {},
|
|
38885
|
-
changedFiles:
|
|
39065
|
+
changedFiles: readStringArray3(raw.changedFiles),
|
|
38886
39066
|
validationResults: normalizeValidationResults(raw.validationResults),
|
|
38887
39067
|
...gitStatus ? { gitStatus } : {},
|
|
38888
39068
|
processArtifacts: normalizeProcessArtifacts(raw.processArtifacts),
|
|
38889
|
-
errors:
|
|
39069
|
+
errors: readStringArray3(raw.errors),
|
|
38890
39070
|
...readNonEmptyString2(raw.nextAction) ? { nextAction: readNonEmptyString2(raw.nextAction) } : {},
|
|
38891
39071
|
requiresUserAction: raw.requiresUserAction === true,
|
|
38892
39072
|
source
|
|
@@ -40065,7 +40245,8 @@ When you compose the task message you dispatch to a node, include these requirem
|
|
|
40065
40245
|
| \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
|
|
40066
40246
|
| \`mesh_restart_daemon\` | Update a node's daemon to the latest published version on its channel and restart it (the dashboard "preview update" path, as a mesh command) |
|
|
40067
40247
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
40068
|
-
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
40248
|
+
| \`mesh_approve\` | Approve/reject a pending agent action (a yes/no tool-consent modal) |
|
|
40249
|
+
| \`mesh_answer_question\` | Answer a delegated session's multi-choice QUESTION (AskUserQuestion / status awaiting_choice). NOT an approval \u2014 it offers labelled options (possibly multi-select or freeform). Pass the promptId from the agent:waiting_choice event + one answer per question (select by option label or 1-based index). Use this, never mesh_approve, for a question |
|
|
40069
40250
|
| \`mesh_list_pending_approvals\` | List every session across the mesh awaiting an approval decision (the approval inbox) \u2014 read-only; enumerate all blocked sessions at once, then drive a mesh_approve for each |
|
|
40070
40251
|
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
40071
40252
|
| \`mesh_refine_node\` | Validate and merge a completed worktree node back into its base branch |
|
|
@@ -40301,7 +40482,7 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
|
|
|
40301
40482
|
function readRecord4(value) {
|
|
40302
40483
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
40303
40484
|
}
|
|
40304
|
-
function
|
|
40485
|
+
function readStringArray4(value, max) {
|
|
40305
40486
|
if (!Array.isArray(value)) return { values: [], truncated: false };
|
|
40306
40487
|
const values = value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
40307
40488
|
return { values: values.slice(0, max), truncated: values.length > max };
|
|
@@ -40331,14 +40512,14 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
|
|
|
40331
40512
|
function readWorkerArtifact(value) {
|
|
40332
40513
|
const worker = readRecord4(value);
|
|
40333
40514
|
if (!worker) return null;
|
|
40334
|
-
const changed =
|
|
40515
|
+
const changed = readStringArray4(worker.changedFiles, MAX_CHANGED_FILES);
|
|
40335
40516
|
return {
|
|
40336
40517
|
status: readString5(worker.status) ?? "unknown",
|
|
40337
40518
|
...readString5(worker.classification) ? { classification: readString5(worker.classification) } : {},
|
|
40338
40519
|
changedFiles: changed.values,
|
|
40339
40520
|
...changed.truncated ? { changedFilesTruncated: true } : {},
|
|
40340
40521
|
validationResults: Array.isArray(worker.validationResults) ? worker.validationResults.map((item) => readRecord4(item)).filter((item) => item !== null) : [],
|
|
40341
|
-
errors:
|
|
40522
|
+
errors: readStringArray4(worker.errors, 20).values,
|
|
40342
40523
|
requiresUserAction: worker.requiresUserAction === true
|
|
40343
40524
|
};
|
|
40344
40525
|
}
|
|
@@ -43503,6 +43684,61 @@ ${rendered}`, "utf-8");
|
|
|
43503
43684
|
);
|
|
43504
43685
|
}
|
|
43505
43686
|
});
|
|
43687
|
+
var mesh_node_identity_exports = {};
|
|
43688
|
+
__export2(mesh_node_identity_exports, {
|
|
43689
|
+
MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS: () => MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS,
|
|
43690
|
+
MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS: () => MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
43691
|
+
MESH_DIRECT_PROBE_REUSE_MS: () => MESH_DIRECT_PROBE_REUSE_MS,
|
|
43692
|
+
MESH_DIRECT_PROBE_TIMEOUT_MS: () => MESH_DIRECT_PROBE_TIMEOUT_MS,
|
|
43693
|
+
MESH_NODE_LIVE_TRUTH_MARKER: () => MESH_NODE_LIVE_TRUTH_MARKER,
|
|
43694
|
+
MeshGitProbeCache: () => MeshGitProbeCache,
|
|
43695
|
+
applyCachedInlineMeshNodeStatus: () => applyCachedInlineMeshNodeStatus,
|
|
43696
|
+
applyInlineMeshBranchConvergence: () => applyInlineMeshBranchConvergence,
|
|
43697
|
+
awaitWithWarmupDeadline: () => awaitWithWarmupDeadline,
|
|
43698
|
+
buildHistoricalMeshSessions: () => buildHistoricalMeshSessions,
|
|
43699
|
+
buildInlineMeshTransitGitStatus: () => buildInlineMeshTransitGitStatus,
|
|
43700
|
+
buildLivePeerGitConnection: () => buildLivePeerGitConnection,
|
|
43701
|
+
buildMeshNodeDataFreshness: () => buildMeshNodeDataFreshness,
|
|
43702
|
+
buildMeshNodeDisplayLabel: () => buildMeshNodeDisplayLabel,
|
|
43703
|
+
buildMeshNodeMachineIdentity: () => buildMeshNodeMachineIdentity,
|
|
43704
|
+
buildMeshNodeProbeFreshness: () => buildMeshNodeProbeFreshness,
|
|
43705
|
+
collectLiveMeshSessionRecords: () => collectLiveMeshSessionRecords,
|
|
43706
|
+
collectMeshNodeHostedSessionIds: () => collectMeshNodeHostedSessionIds,
|
|
43707
|
+
deriveMeshNodeHealthFromGit: () => deriveMeshNodeHealthFromGit,
|
|
43708
|
+
finalizeMeshNodeStatus: () => finalizeMeshNodeStatus,
|
|
43709
|
+
foldMeshNodeIdentityToCanonical: () => foldMeshNodeIdentityToCanonical,
|
|
43710
|
+
hydrateInlineMeshDirectTruth: () => hydrateInlineMeshDirectTruth,
|
|
43711
|
+
inlineMeshCarriesTransientNodeTruth: () => inlineMeshCarriesTransientNodeTruth,
|
|
43712
|
+
isDeadLocalWorktreeNode: () => isDeadLocalWorktreeNode,
|
|
43713
|
+
isMeshNodeFreshEnoughToLaunch: () => isMeshNodeFreshEnoughToLaunch,
|
|
43714
|
+
isMeshNodeHealthLaunchable: () => isMeshNodeHealthLaunchable,
|
|
43715
|
+
logRepoMeshStatusDebug: () => logRepoMeshStatusDebug,
|
|
43716
|
+
normalizeInlineMeshNodeIdentity: () => normalizeInlineMeshNodeIdentity,
|
|
43717
|
+
normalizeProviderRoles: () => normalizeProviderRoles,
|
|
43718
|
+
persistNodeReporterPlatform: () => persistNodeReporterPlatform,
|
|
43719
|
+
probeRemoteMeshGitStatusWithRetry: () => probeRemoteMeshGitStatusWithRetry,
|
|
43720
|
+
readBooleanValue: () => readBooleanValue,
|
|
43721
|
+
readCachedInlineMeshActiveSessionDetails: () => readCachedInlineMeshActiveSessionDetails2,
|
|
43722
|
+
readCachedInlineMeshActiveSessions: () => readCachedInlineMeshActiveSessions,
|
|
43723
|
+
readInlineMeshNodeId: () => readInlineMeshNodeId,
|
|
43724
|
+
readLiveMeshNodeWorkspace: () => readLiveMeshNodeWorkspace,
|
|
43725
|
+
readMeshNodeDaemonId: () => readMeshNodeDaemonId,
|
|
43726
|
+
readMeshNodeHostname: () => readMeshNodeHostname,
|
|
43727
|
+
readMeshNodeMachineId: () => readMeshNodeMachineId,
|
|
43728
|
+
readObjectRecord: () => readObjectRecord,
|
|
43729
|
+
readProviderPriorityFromPolicy: () => readProviderPriorityFromPolicy,
|
|
43730
|
+
readStringValue: () => readStringValue,
|
|
43731
|
+
reconcileInlineMeshCache: () => reconcileInlineMeshCache,
|
|
43732
|
+
recordInlineMeshDirectGitTruth: () => recordInlineMeshDirectGitTruth,
|
|
43733
|
+
resolveEffectiveMeshNodeHealth: () => resolveEffectiveMeshNodeHealth,
|
|
43734
|
+
resolveMeshNodeAttribution: () => resolveMeshNodeAttribution,
|
|
43735
|
+
resolveProviderTypeFromPriority: () => resolveProviderTypeFromPriority,
|
|
43736
|
+
sanitizeInlineMesh: () => sanitizeInlineMesh,
|
|
43737
|
+
shouldRefreshStalePendingAggregate: () => shouldRefreshStalePendingAggregate,
|
|
43738
|
+
summarizeInlineMeshBranchConvergence: () => summarizeInlineMeshBranchConvergence,
|
|
43739
|
+
summarizeMeshSessionRecord: () => summarizeMeshSessionRecord,
|
|
43740
|
+
summarizeRepoMeshStatusDebug: () => summarizeRepoMeshStatusDebug
|
|
43741
|
+
});
|
|
43506
43742
|
function readProviderPriorityFromPolicy(policy) {
|
|
43507
43743
|
const record2 = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
|
|
43508
43744
|
const raw = record2.providerPriority;
|
|
@@ -44066,6 +44302,23 @@ ${rendered}`, "utf-8");
|
|
|
44066
44302
|
const health = resolveEffectiveMeshNodeHealth(node);
|
|
44067
44303
|
return health === "online" || health === "unknown";
|
|
44068
44304
|
}
|
|
44305
|
+
function resolveEffectiveNodeGit(node) {
|
|
44306
|
+
const git = readObjectRecord(node?.git);
|
|
44307
|
+
if (Object.keys(git).length > 0) return git;
|
|
44308
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
44309
|
+
return readObjectRecord(cachedStatus.git);
|
|
44310
|
+
}
|
|
44311
|
+
function isMeshNodeFreshEnoughToLaunch(node, opts) {
|
|
44312
|
+
const git = resolveEffectiveNodeGit(node);
|
|
44313
|
+
if (Object.keys(git).length === 0) return true;
|
|
44314
|
+
if (readBooleanValue(git.isGitRepo) === false) return true;
|
|
44315
|
+
const submoduleDrift = getGitSubmoduleDriftState(git);
|
|
44316
|
+
if (submoduleDrift.outOfSync) return false;
|
|
44317
|
+
const behind = readNumberValue(git.behind);
|
|
44318
|
+
if (behind === void 0) return true;
|
|
44319
|
+
const maxBehind = Number.isFinite(opts?.maxBehind) && opts?.maxBehind >= 0 ? Math.floor(opts.maxBehind) : 0;
|
|
44320
|
+
return behind <= maxBehind;
|
|
44321
|
+
}
|
|
44069
44322
|
function readMeshNodeLabel(status, node) {
|
|
44070
44323
|
return readStringValue(status.nodeId, normalizeMeshNodeId(node)) ?? "unknown";
|
|
44071
44324
|
}
|
|
@@ -44970,6 +45223,7 @@ ${rendered}`, "utf-8");
|
|
|
44970
45223
|
if (!session) return { staleReason: "direct task session is not present in live session records" };
|
|
44971
45224
|
if (typeof session === "string") return {};
|
|
44972
45225
|
const raw = `${readString6(session.status) || ""} ${readString6(session.lifecycle) || ""} ${readString6(session.state) || ""} ${readString6(session.activeChat?.status) || ""}`.toLowerCase();
|
|
45226
|
+
if (raw.includes("waiting_choice") || raw.includes("choice")) return { status: "awaiting_choice" };
|
|
44973
45227
|
if (raw.includes("approval")) return { status: "awaiting_approval" };
|
|
44974
45228
|
if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return { status: "generating" };
|
|
44975
45229
|
if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return { status: "failed" };
|
|
@@ -44995,6 +45249,7 @@ ${rendered}`, "utf-8");
|
|
|
44995
45249
|
}
|
|
44996
45250
|
function statusFromTerminal(entry) {
|
|
44997
45251
|
if (entry.kind === "task_approval_needed") return "awaiting_approval";
|
|
45252
|
+
if (entry.kind === "task_question_pending") return "awaiting_choice";
|
|
44998
45253
|
if (entry.kind === "task_completed") return "idle";
|
|
44999
45254
|
return "failed";
|
|
45000
45255
|
}
|
|
@@ -45073,7 +45328,8 @@ ${rendered}`, "utf-8");
|
|
|
45073
45328
|
generating: 0,
|
|
45074
45329
|
idle: 0,
|
|
45075
45330
|
failed: 0,
|
|
45076
|
-
awaiting_approval: 0
|
|
45331
|
+
awaiting_approval: 0,
|
|
45332
|
+
awaiting_choice: 0
|
|
45077
45333
|
};
|
|
45078
45334
|
const sourceCounts = { queue: 0, direct: 0 };
|
|
45079
45335
|
for (const item of activeWork) {
|
|
@@ -45108,7 +45364,7 @@ ${rendered}`, "utf-8");
|
|
|
45108
45364
|
const queueNodeId = task.assignedNodeId || task.targetNodeId;
|
|
45109
45365
|
const queueSessionId = task.assignedSessionId || task.targetSessionId;
|
|
45110
45366
|
const queueLive = task.status === "assigned" ? sessionStatusFromNodes(opts.nodes, queueNodeId ?? void 0, queueSessionId ?? void 0) : {};
|
|
45111
|
-
const queueStatus = queueLive.status === "awaiting_approval" || queueLive.status === "generating" ? queueLive.status : task.status;
|
|
45367
|
+
const queueStatus = queueLive.status === "awaiting_approval" || queueLive.status === "awaiting_choice" || queueLive.status === "generating" ? queueLive.status : task.status;
|
|
45112
45368
|
records.push({
|
|
45113
45369
|
taskId: task.id,
|
|
45114
45370
|
source: "queue",
|
|
@@ -46104,6 +46360,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
46104
46360
|
"agent:generating_started",
|
|
46105
46361
|
"agent:generating_completed",
|
|
46106
46362
|
"agent:waiting_approval",
|
|
46363
|
+
// A worker parked on an AskUserQuestion multi-choice prompt. DISTINCT from
|
|
46364
|
+
// agent:waiting_approval (a yes/no tool-consent modal): a question is answered
|
|
46365
|
+
// with mesh_answer_question, never mesh_approve (mission f1d25e11). Carries the
|
|
46366
|
+
// full InteractivePrompt payload so the coordinator can render + answer.
|
|
46367
|
+
"agent:waiting_choice",
|
|
46107
46368
|
"agent:stopped",
|
|
46108
46369
|
"agent:ready",
|
|
46109
46370
|
"monitor:no_progress",
|
|
@@ -46121,6 +46382,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
46121
46382
|
EVENT_TO_LEDGER_KIND = {
|
|
46122
46383
|
"agent:generating_completed": "task_completed",
|
|
46123
46384
|
"agent:waiting_approval": "task_approval_needed",
|
|
46385
|
+
"agent:waiting_choice": "task_question_pending",
|
|
46124
46386
|
"agent:stopped": "task_failed",
|
|
46125
46387
|
"monitor:no_progress": "task_stalled"
|
|
46126
46388
|
};
|
|
@@ -46128,13 +46390,26 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
46128
46390
|
"agent:generating_completed",
|
|
46129
46391
|
"agent:stopped",
|
|
46130
46392
|
"agent:waiting_approval",
|
|
46393
|
+
// A worker's question (waiting_choice) is real-time and the coordinator may be
|
|
46394
|
+
// generating when it arrives; force-inject it like approval so the busy coordinator
|
|
46395
|
+
// learns it must answer (mesh_answer_question) rather than the nudge sitting in the
|
|
46396
|
+
// adapter's outbound queue until the coordinator idles on its own (mission f1d25e11).
|
|
46397
|
+
"agent:waiting_choice",
|
|
46131
46398
|
"refine:completed",
|
|
46132
46399
|
"refine:failed",
|
|
46133
46400
|
"worktree_bootstrap_complete",
|
|
46134
46401
|
"worktree_bootstrap_failed"
|
|
46135
46402
|
]);
|
|
46136
46403
|
MESH_APPROVAL_EVENTS = /* @__PURE__ */ new Set([
|
|
46137
|
-
"agent:waiting_approval"
|
|
46404
|
+
"agent:waiting_approval",
|
|
46405
|
+
// agent:waiting_choice (a worker's AskUserQuestion) shares the approval class's
|
|
46406
|
+
// real-time-nudge / level-backed contract: its authoritative state is recorded at
|
|
46407
|
+
// LEVEL the moment it is processed (task_question_pending → mesh_status
|
|
46408
|
+
// awaiting_choice), so the pending event is only a NUDGE and can be delivered to a
|
|
46409
|
+
// busy coordinator's inbox (and dropped) without data loss — the level state
|
|
46410
|
+
// re-derives it. It is therefore exempt from the idle-edge hold completions require,
|
|
46411
|
+
// exactly like an approval nudge (mission f1d25e11).
|
|
46412
|
+
"agent:waiting_choice"
|
|
46138
46413
|
]);
|
|
46139
46414
|
}
|
|
46140
46415
|
});
|
|
@@ -47117,6 +47392,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
47117
47392
|
}
|
|
47118
47393
|
}
|
|
47119
47394
|
if (!pending.length) return false;
|
|
47395
|
+
const freshnessGate = { maxBehind: resolveAutoFastForwardPolicy(mesh).maxBehind };
|
|
47120
47396
|
const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
|
|
47121
47397
|
const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks);
|
|
47122
47398
|
for (const task of pending) {
|
|
@@ -47231,6 +47507,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
47231
47507
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_not_launch_ready", nodeId });
|
|
47232
47508
|
continue;
|
|
47233
47509
|
}
|
|
47510
|
+
if (!isMeshNodeFreshEnoughToLaunch(node, freshnessGate)) {
|
|
47511
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_stale_behind_upstream", nodeId });
|
|
47512
|
+
continue;
|
|
47513
|
+
}
|
|
47234
47514
|
const launchTarget = resolveAutoLaunchTarget(components, node);
|
|
47235
47515
|
if (launchTarget.mode === "skip") {
|
|
47236
47516
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: launchTarget.reason || "auto_launch_unavailable", nodeId });
|
|
@@ -50964,10 +51244,19 @@ ${cleanBody}`;
|
|
|
50964
51244
|
}
|
|
50965
51245
|
function markSessionTerminal(sessionId, outcome, occurredAtMs, opts) {
|
|
50966
51246
|
const eventTaskId = readNonEmptyString(args.metadataEvent.taskId) || void 0;
|
|
50967
|
-
const
|
|
51247
|
+
const completionDiagnostic = args.metadataEvent.completionDiagnostic && typeof args.metadataEvent.completionDiagnostic === "object" ? args.metadataEvent.completionDiagnostic : void 0;
|
|
51248
|
+
const emittedAfterFinalizationTimeout = completionDiagnostic?.emittedAfterFinalizationTimeout === true;
|
|
51249
|
+
const weakCompleted = outcome === "completed" && isWeakCompletionEvidence(args.metadataEvent) && !emittedAfterFinalizationTimeout;
|
|
51250
|
+
const task = weakCompleted ? updateSessionTaskStatus(args.meshId, sessionId, "assigned", {
|
|
51251
|
+
occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
|
|
51252
|
+
taskId: eventTaskId
|
|
51253
|
+
}) : updateSessionTaskStatus(args.meshId, sessionId, outcome, {
|
|
50968
51254
|
occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
|
|
50969
51255
|
taskId: eventTaskId
|
|
50970
51256
|
});
|
|
51257
|
+
if (weakCompleted && task) {
|
|
51258
|
+
LOG2.info("MeshQueue", `Weak completion (${readNonEmptyString(args.metadataEvent.evidenceLevel) || "missing_final_assistant"}) kept queue task ${task.id} tentative (session ${sessionId}); reconcile owns the genuine terminal`);
|
|
51259
|
+
}
|
|
50971
51260
|
const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true || !eventTaskId && !sessionHasActiveAssignment(args.meshId, sessionId);
|
|
50972
51261
|
if (!leaveDirectDispatchActive) {
|
|
50973
51262
|
updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
|
|
@@ -51424,6 +51713,14 @@ ${cleanBody}`;
|
|
|
51424
51713
|
retryOfJobId: readNonEmptyString(payload.retryOfJobId),
|
|
51425
51714
|
...relayModalMessage ? { modalMessage: relayModalMessage } : {},
|
|
51426
51715
|
...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
|
|
51716
|
+
// agent:waiting_choice (mission f1d25e11): carry the FULL structured question
|
|
51717
|
+
// payload across the machine boundary so a REMOTE worker's AskUserQuestion reaches
|
|
51718
|
+
// the coordinator with every question + option intact — the coordinator renders
|
|
51719
|
+
// these and answers with mesh_answer_question. The local in-process forward path
|
|
51720
|
+
// preserves the whole event for free; this mirrors the fields for the remote relay.
|
|
51721
|
+
...payload.interactivePrompt && typeof payload.interactivePrompt === "object" && !Array.isArray(payload.interactivePrompt) ? { interactivePrompt: payload.interactivePrompt } : {},
|
|
51722
|
+
...readNonEmptyString(payload.promptId) ? { promptId: readNonEmptyString(payload.promptId) } : {},
|
|
51723
|
+
...payload.multiSelect === true ? { multiSelect: true } : {},
|
|
51427
51724
|
...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
|
|
51428
51725
|
...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
|
|
51429
51726
|
...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
|
|
@@ -52842,7 +53139,8 @@ ${cleanBody}`;
|
|
|
52842
53139
|
function assignedRowLiveStatusIsAwaitingApproval(mesh, nodeId, sessionId) {
|
|
52843
53140
|
if (!nodeId || !sessionId) return false;
|
|
52844
53141
|
try {
|
|
52845
|
-
|
|
53142
|
+
const liveStatus = sessionStatusFromNodes(mesh.nodes, nodeId, sessionId).status;
|
|
53143
|
+
return liveStatus === "awaiting_approval" || liveStatus === "awaiting_choice";
|
|
52846
53144
|
} catch {
|
|
52847
53145
|
return false;
|
|
52848
53146
|
}
|
|
@@ -55324,8 +55622,15 @@ ${cleanBody}`;
|
|
|
55324
55622
|
if (pickApprovalButton(labels).index < 0) return false;
|
|
55325
55623
|
return hasNegativeApprovalOption(labels);
|
|
55326
55624
|
}
|
|
55625
|
+
function isAskUserQuestionPickerSignature(text) {
|
|
55626
|
+
if (!text) return false;
|
|
55627
|
+
const hasSelectFooter = /Enter to select/i.test(text) && /Esc to cancel/i.test(text);
|
|
55628
|
+
if (!hasSelectFooter) return false;
|
|
55629
|
+
return /Type something\.?|Chat about this/i.test(text);
|
|
55630
|
+
}
|
|
55327
55631
|
function modalMatches(spec, input) {
|
|
55328
55632
|
const text = input.screenText ?? "";
|
|
55633
|
+
if (isAskUserQuestionPickerSignature(text)) return false;
|
|
55329
55634
|
const question = compile2(spec.questionPattern, spec.questionFlags ?? "i");
|
|
55330
55635
|
if (question.test(text)) return true;
|
|
55331
55636
|
for (const variant of spec.questionVariants ?? []) {
|
|
@@ -55465,6 +55770,12 @@ ${cleanBody}`;
|
|
|
55465
55770
|
throw new Error(`Invalid regex /${re}/${flags ?? ""}: ${e.message}`);
|
|
55466
55771
|
}
|
|
55467
55772
|
}
|
|
55773
|
+
function isAskUserQuestionPickerSignature2(text) {
|
|
55774
|
+
if (!text) return false;
|
|
55775
|
+
const hasSelectFooter = /Enter to select/i.test(text) && /Esc to cancel/i.test(text);
|
|
55776
|
+
if (!hasSelectFooter) return false;
|
|
55777
|
+
return /Type something\.?|Chat about this/i.test(text);
|
|
55778
|
+
}
|
|
55468
55779
|
function findQuestionLineIndex(spec, lines) {
|
|
55469
55780
|
const primary = compile3(spec.questionPattern, spec.questionFlags ?? "i");
|
|
55470
55781
|
const buttonFlags = spec.buttonFlags && spec.buttonFlags.includes("m") ? spec.buttonFlags : `${spec.buttonFlags ?? ""}m`;
|
|
@@ -55589,6 +55900,7 @@ ${cleanBody}`;
|
|
|
55589
55900
|
return function parseApproval(input) {
|
|
55590
55901
|
const rawText = input.screenText ?? input.buffer ?? "";
|
|
55591
55902
|
if (!rawText) return null;
|
|
55903
|
+
if (isAskUserQuestionPickerSignature2(rawText)) return null;
|
|
55592
55904
|
const text = visibleRegion ? applyVisibleRegion(visibleRegion, rawText) : rawText;
|
|
55593
55905
|
const lines = text.split("\n");
|
|
55594
55906
|
const question = findQuestionLineIndex(spec, lines);
|
|
@@ -60413,6 +60725,57 @@ ${lastSnapshot}`;
|
|
|
60413
60725
|
}
|
|
60414
60726
|
return { promptId, answers };
|
|
60415
60727
|
}
|
|
60728
|
+
function resolveInteractivePromptResponse(prompt, raw) {
|
|
60729
|
+
if (!raw || typeof raw !== "object") throw new Error("Interactive prompt response must be an object");
|
|
60730
|
+
const record2 = raw;
|
|
60731
|
+
const promptId = readString(record2.promptId);
|
|
60732
|
+
if (!promptId) throw new Error("promptId must be a non-empty string");
|
|
60733
|
+
if (promptId !== prompt.promptId) throw new Error("Interactive prompt response does not match active prompt");
|
|
60734
|
+
if (record2.answers && typeof record2.answers === "object" && !Array.isArray(record2.answers)) {
|
|
60735
|
+
return normalizeInteractivePromptResponse2(record2);
|
|
60736
|
+
}
|
|
60737
|
+
if (!Array.isArray(record2.answers)) throw new Error("answers must be an array or a questionId-keyed object");
|
|
60738
|
+
const resolveOneLabel = (question, sel) => {
|
|
60739
|
+
if (typeof sel === "number" && Number.isFinite(sel)) {
|
|
60740
|
+
const idx = Math.trunc(sel) - 1;
|
|
60741
|
+
const option = question.options[idx];
|
|
60742
|
+
if (!option) throw new Error(`Option index ${sel} out of range for ${question.questionId}`);
|
|
60743
|
+
return option.label;
|
|
60744
|
+
}
|
|
60745
|
+
const label = readString(sel);
|
|
60746
|
+
if (!label) throw new Error(`Empty selection for ${question.questionId}`);
|
|
60747
|
+
const exact = question.options.find((o) => o.label === label);
|
|
60748
|
+
if (exact) return exact.label;
|
|
60749
|
+
const asIndex = Number(label);
|
|
60750
|
+
if (Number.isInteger(asIndex)) {
|
|
60751
|
+
const option = question.options[asIndex - 1];
|
|
60752
|
+
if (option) return option.label;
|
|
60753
|
+
}
|
|
60754
|
+
throw new Error(`Unknown option for ${question.questionId}: ${label}`);
|
|
60755
|
+
};
|
|
60756
|
+
const answers = {};
|
|
60757
|
+
const entries = record2.answers;
|
|
60758
|
+
entries.forEach((entryRaw, index) => {
|
|
60759
|
+
if (!entryRaw || typeof entryRaw !== "object" || Array.isArray(entryRaw)) return;
|
|
60760
|
+
const entry = entryRaw;
|
|
60761
|
+
const questionId = readString(entry.questionId);
|
|
60762
|
+
const question = (questionId ? prompt.questions.find((q) => q.questionId === questionId) : void 0) ?? prompt.questions[index];
|
|
60763
|
+
if (!question) throw new Error(`No matching question for answer entry ${index}`);
|
|
60764
|
+
const freeformText = readString(entry.freeform) ?? readString(entry.freeformText);
|
|
60765
|
+
const selectedLabels = [];
|
|
60766
|
+
const select = entry.select;
|
|
60767
|
+
if (Array.isArray(select)) {
|
|
60768
|
+
for (const sel of select) selectedLabels.push(resolveOneLabel(question, sel));
|
|
60769
|
+
} else if (select !== void 0 && select !== null) {
|
|
60770
|
+
selectedLabels.push(resolveOneLabel(question, select));
|
|
60771
|
+
}
|
|
60772
|
+
answers[question.questionId] = {
|
|
60773
|
+
selectedLabels,
|
|
60774
|
+
...freeformText ? { freeformText } : {}
|
|
60775
|
+
};
|
|
60776
|
+
});
|
|
60777
|
+
return { promptId, answers };
|
|
60778
|
+
}
|
|
60416
60779
|
function buildClaudeInteractiveToolResult(response) {
|
|
60417
60780
|
return JSON.stringify({
|
|
60418
60781
|
type: "user",
|
|
@@ -78593,6 +78956,7 @@ ${body}
|
|
|
78593
78956
|
var STATUS_HYDRATION_TAIL_LIMIT = 200;
|
|
78594
78957
|
var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
|
|
78595
78958
|
var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
|
|
78959
|
+
var CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS = 2e4;
|
|
78596
78960
|
var NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 4e3;
|
|
78597
78961
|
var PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS = 1200;
|
|
78598
78962
|
var ANTIGRAVITY_HOLD_QUIET_DWELL_MS = 3e3;
|
|
@@ -79007,10 +79371,12 @@ ${body}
|
|
|
79007
79371
|
// `waiting_choice` overlay in getState(); the raw adapter status stays idle/generating,
|
|
79008
79372
|
// so detectStatusTransition()'s status-keyed arms never fire and no push-worthy
|
|
79009
79373
|
// agent:* event is emitted — the owner misses the "ACTION REQUIRED" prompt when the
|
|
79010
|
-
// app is backgrounded. We emit one agent:
|
|
79011
|
-
// state (
|
|
79012
|
-
//
|
|
79013
|
-
//
|
|
79374
|
+
// app is backgrounded. We emit one agent:waiting_choice on ENTRY into the prompt
|
|
79375
|
+
// state (its own coordinator event, NOT the approval channel — a multi-choice
|
|
79376
|
+
// question is answered with mesh_answer_question, never mesh_approve) carrying the
|
|
79377
|
+
// FULL InteractivePrompt payload, and dedupe on this key so repeated status ticks
|
|
79378
|
+
// with the same prompt do not re-fire. '' means no prompt is currently active
|
|
79379
|
+
// (cleared when the prompt is answered/gone).
|
|
79014
79380
|
lastInteractivePromptEventKey = "";
|
|
79015
79381
|
autoApproveBusy = false;
|
|
79016
79382
|
autoApproveBusyTimer = null;
|
|
@@ -79655,7 +80021,7 @@ ${body}
|
|
|
79655
80021
|
}
|
|
79656
80022
|
} else if (event === "interactive_prompt_response" && data) {
|
|
79657
80023
|
try {
|
|
79658
|
-
const response = normalizeInteractivePromptResponse2(data);
|
|
80024
|
+
const response = this.activeInteractivePrompt && this.activeInteractivePrompt.promptId === data?.promptId && Array.isArray(data?.answers) ? resolveInteractivePromptResponse(this.activeInteractivePrompt, data) : normalizeInteractivePromptResponse2(data);
|
|
79659
80025
|
if (this.activeInteractivePrompt?.promptId === response.promptId) {
|
|
79660
80026
|
this.activeInteractivePrompt = null;
|
|
79661
80027
|
}
|
|
@@ -80194,7 +80560,12 @@ ${body}
|
|
|
80194
80560
|
return {
|
|
80195
80561
|
reason: "missing_final_assistant",
|
|
80196
80562
|
terminal: this.provider.requiresFinalAssistantBeforeIdle === true,
|
|
80197
|
-
allowTimeout: allowMissingAssistantTimeout
|
|
80563
|
+
allowTimeout: allowMissingAssistantTimeout,
|
|
80564
|
+
// PTY-parsed provider (codex-cli): no external transcript trails the idle
|
|
80565
|
+
// transition, so the CANON-C decoupled emit must observe the min-elapsed floor
|
|
80566
|
+
// rather than fire at the first-poll waitedMs. (claude-cli's external-native
|
|
80567
|
+
// branch above is exempt — its transcript legitimately lands moments later.)
|
|
80568
|
+
noExternalTranscriptSource: true
|
|
80198
80569
|
};
|
|
80199
80570
|
}
|
|
80200
80571
|
}
|
|
@@ -80692,6 +81063,24 @@ ${body}
|
|
|
80692
81063
|
this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
|
|
80693
81064
|
return;
|
|
80694
81065
|
}
|
|
81066
|
+
if (isTranscriptEvidenceGate && blockReason === "missing_final_assistant" && block2.noExternalTranscriptSource === true && waitedMs < CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS) {
|
|
81067
|
+
if (pending.loggedBlockReason !== "canon_c_min_elapsed_floor") {
|
|
81068
|
+
LOG2.info("CLI", `[${this.type}] holding CANON-C decoupled emit until min-elapsed floor (waitedMs=${waitedMs} floor=${CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS}); no final assistant yet (${blockReason})`);
|
|
81069
|
+
if (this.isMeshWorkerSession()) {
|
|
81070
|
+
traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `canon_c_min_elapsed_floor waited=${waitedMs}ms`);
|
|
81071
|
+
}
|
|
81072
|
+
if (this.completionTraceOn()) this.recordCompletionGateTrace("hold", {
|
|
81073
|
+
blockReason,
|
|
81074
|
+
latestVisibleStatus,
|
|
81075
|
+
terminal: block2.terminal === true,
|
|
81076
|
+
canonCMinElapsedFloor: true,
|
|
81077
|
+
waitedMs
|
|
81078
|
+
});
|
|
81079
|
+
pending.loggedBlockReason = "canon_c_min_elapsed_floor";
|
|
81080
|
+
}
|
|
81081
|
+
this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
|
|
81082
|
+
return;
|
|
81083
|
+
}
|
|
80695
81084
|
if (this.type === "antigravity-cli" && block2.holdForTranscript === true && waitedMs < ANTIGRAVITY_HOLD_HARD_CAP_MS && this.antigravityHoldPtyStillActive()) {
|
|
80696
81085
|
if (pending.loggedBlockReason !== "antigravity_hold_pty_active") {
|
|
80697
81086
|
LOG2.info("CLI", `[${this.type}] 30s cap reached but PTY still generating; holding antigravity completion past cap (waitedMs=${waitedMs} hardCap=${ANTIGRAVITY_HOLD_HARD_CAP_MS}) (${blockReason})`);
|
|
@@ -81391,9 +81780,16 @@ ${buttons.join("\n")}`;
|
|
|
81391
81780
|
const modalMessage = firstQuestion ? firstQuestion.header ? `${firstQuestion.header}: ${firstQuestion.question}` : firstQuestion.question : void 0;
|
|
81392
81781
|
const modalButtons = firstQuestion?.options?.map((option) => option.label);
|
|
81393
81782
|
this.pushEvent({
|
|
81394
|
-
event: "agent:
|
|
81783
|
+
event: "agent:waiting_choice",
|
|
81395
81784
|
chatTitle,
|
|
81396
81785
|
timestamp: now,
|
|
81786
|
+
// Structured, authoritative payload — the coordinator renders these and
|
|
81787
|
+
// answers via mesh_answer_question. Carried whole (all questions, all
|
|
81788
|
+
// options) so multi-question / multi-select prompts round-trip fully.
|
|
81789
|
+
interactivePrompt,
|
|
81790
|
+
promptId: interactivePrompt.promptId,
|
|
81791
|
+
multiSelect: firstQuestion?.multiSelect === true,
|
|
81792
|
+
// Push-notification-friendly projection (server push path reads these).
|
|
81397
81793
|
modalMessage,
|
|
81398
81794
|
modalButtons
|
|
81399
81795
|
});
|
|
@@ -90261,6 +90657,50 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
90261
90657
|
}
|
|
90262
90658
|
}
|
|
90263
90659
|
};
|
|
90660
|
+
init_logger();
|
|
90661
|
+
async function stopCancelledTaskWorker(ctx, meshId, prior) {
|
|
90662
|
+
const { sessionId, nodeId, providerType } = prior;
|
|
90663
|
+
const stopArgs = {
|
|
90664
|
+
targetSessionId: sessionId,
|
|
90665
|
+
...providerType ? { cliType: providerType } : {},
|
|
90666
|
+
mode: "hard",
|
|
90667
|
+
reason: "mesh_task_cancelled"
|
|
90668
|
+
};
|
|
90669
|
+
try {
|
|
90670
|
+
const cliManager = ctx.deps.cliManager;
|
|
90671
|
+
const isLocal = cliManager?.adapters?.has?.(sessionId) === true;
|
|
90672
|
+
if (isLocal) {
|
|
90673
|
+
if (!stopArgs.cliType) {
|
|
90674
|
+
const localType = cliManager?.adapters?.get?.(sessionId)?.cliType;
|
|
90675
|
+
if (localType) stopArgs.cliType = localType;
|
|
90676
|
+
}
|
|
90677
|
+
await Promise.resolve(cliManager?.handleCliCommand?.("stop_cli", stopArgs)).catch((e) => LOG2.warn("MeshQueue", `Local stop of cancelled worker ${sessionId} failed: ${e?.message || e}`));
|
|
90678
|
+
return;
|
|
90679
|
+
}
|
|
90680
|
+
const dispatch = ctx.deps.dispatchMeshCommand;
|
|
90681
|
+
let daemonId;
|
|
90682
|
+
if (nodeId) {
|
|
90683
|
+
try {
|
|
90684
|
+
const [{ getMesh: getMesh2 }, { meshNodeIdMatches: meshNodeIdMatches2 }, { readMeshNodeDaemonId: readMeshNodeDaemonId2 }] = await Promise.all([
|
|
90685
|
+
Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)),
|
|
90686
|
+
Promise.resolve().then(() => (init_dist(), dist_exports)),
|
|
90687
|
+
Promise.resolve().then(() => (init_mesh_node_identity(), mesh_node_identity_exports))
|
|
90688
|
+
]);
|
|
90689
|
+
const mesh = getMesh2(meshId);
|
|
90690
|
+
const node = mesh?.nodes?.find((n) => meshNodeIdMatches2(n, nodeId));
|
|
90691
|
+
daemonId = node ? readMeshNodeDaemonId2(node) || void 0 : void 0;
|
|
90692
|
+
} catch {
|
|
90693
|
+
}
|
|
90694
|
+
}
|
|
90695
|
+
if (daemonId && dispatch) {
|
|
90696
|
+
await Promise.resolve(dispatch(daemonId, "stop_cli", stopArgs)).catch((e) => LOG2.warn("MeshQueue", `Remote stop of cancelled worker ${sessionId} on daemon ${daemonId} failed: ${e?.message || e}`));
|
|
90697
|
+
} else {
|
|
90698
|
+
LOG2.warn("MeshQueue", `Cannot stop cancelled worker ${sessionId}: no local adapter and no resolvable remote daemon id (node ${nodeId ?? "?"}). Row is already terminal; if the worker completes it strand-fails harmlessly.`);
|
|
90699
|
+
}
|
|
90700
|
+
} catch (e) {
|
|
90701
|
+
LOG2.warn("MeshQueue", `stopCancelledTaskWorker error for ${sessionId}: ${e?.message || e}`);
|
|
90702
|
+
}
|
|
90703
|
+
}
|
|
90264
90704
|
var meshQueueHandlers = {
|
|
90265
90705
|
get_mesh_queue: async (_ctx, args) => {
|
|
90266
90706
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -90294,10 +90734,14 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
90294
90734
|
const ownerFailure = await ctx.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue cancellation");
|
|
90295
90735
|
if (ownerFailure) return ownerFailure;
|
|
90296
90736
|
try {
|
|
90297
|
-
const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
90737
|
+
const { cancelTask: cancelTask2, takeCancelledTaskAssignment: takeCancelledTaskAssignment2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
90298
90738
|
const reason = typeof args?.reason === "string" ? args.reason : void 0;
|
|
90299
90739
|
const task = cancelTask2(meshId, taskId, { reason });
|
|
90300
90740
|
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
90741
|
+
const prior = takeCancelledTaskAssignment2(meshId, taskId);
|
|
90742
|
+
if (prior?.sessionId) {
|
|
90743
|
+
void stopCancelledTaskWorker(ctx, meshId, prior);
|
|
90744
|
+
}
|
|
90301
90745
|
return { success: true, task };
|
|
90302
90746
|
} catch (e) {
|
|
90303
90747
|
return { success: false, error: e.message };
|
|
@@ -90764,10 +91208,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
90764
91208
|
interactive_prompt_response: async (ctx, args) => {
|
|
90765
91209
|
const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
|
|
90766
91210
|
if (!sessionId) return { success: false, error: "targetSessionId required" };
|
|
90767
|
-
const
|
|
91211
|
+
const rawResponse = args?.response ?? args;
|
|
90768
91212
|
const instance = ctx.deps.instanceManager.getInstance(sessionId);
|
|
90769
91213
|
if (!instance) return { success: false, error: `No running instance for session ${sessionId}` };
|
|
90770
|
-
|
|
91214
|
+
const isFriendlyArrayForm = rawResponse && typeof rawResponse === "object" && Array.isArray(rawResponse.answers);
|
|
91215
|
+
const payload = isFriendlyArrayForm ? rawResponse : normalizeInteractivePromptResponse2(rawResponse);
|
|
91216
|
+
ctx.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", payload);
|
|
90771
91217
|
return { success: true };
|
|
90772
91218
|
}
|
|
90773
91219
|
};
|
|
@@ -92808,6 +93254,171 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
92808
93254
|
return isSubmoduleFastForward((0, import_path15.resolve)(repoRoot, path46), baseCommit, branchCommit);
|
|
92809
93255
|
});
|
|
92810
93256
|
}
|
|
93257
|
+
function isSubmoduleDivergedSibling(submoduleRepoPath, baseCommit, branchCommit) {
|
|
93258
|
+
if (!baseCommit || !branchCommit || baseCommit === branchCommit) return false;
|
|
93259
|
+
try {
|
|
93260
|
+
if (!fs34.existsSync(submoduleRepoPath)) return false;
|
|
93261
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93262
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93263
|
+
} catch {
|
|
93264
|
+
return false;
|
|
93265
|
+
}
|
|
93266
|
+
try {
|
|
93267
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93268
|
+
return false;
|
|
93269
|
+
} catch {
|
|
93270
|
+
}
|
|
93271
|
+
try {
|
|
93272
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["merge-base", "--is-ancestor", branchCommit, baseCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93273
|
+
return false;
|
|
93274
|
+
} catch {
|
|
93275
|
+
}
|
|
93276
|
+
try {
|
|
93277
|
+
const mb = (0, import_node_child_process6.execFileSync)(GIT2, ["merge-base", baseCommit, branchCommit], { cwd: submoduleRepoPath, encoding: "utf8" }).trim();
|
|
93278
|
+
return !!mb;
|
|
93279
|
+
} catch {
|
|
93280
|
+
return false;
|
|
93281
|
+
}
|
|
93282
|
+
}
|
|
93283
|
+
function ensureSubmoduleCommitLocal(submoduleRepoPath, baseSubmoduleRepoPath, commit) {
|
|
93284
|
+
if (!commit) return;
|
|
93285
|
+
try {
|
|
93286
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["cat-file", "-e", `${commit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93287
|
+
return;
|
|
93288
|
+
} catch {
|
|
93289
|
+
}
|
|
93290
|
+
try {
|
|
93291
|
+
if (!fs34.existsSync(submoduleRepoPath) || !fs34.existsSync(baseSubmoduleRepoPath)) return;
|
|
93292
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["-c", "protocol.file.allow=always", "fetch", "-q", baseSubmoduleRepoPath, "+refs/heads/*:refs/adhdev-refine-base/*"], {
|
|
93293
|
+
cwd: submoduleRepoPath,
|
|
93294
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
93295
|
+
});
|
|
93296
|
+
} catch {
|
|
93297
|
+
}
|
|
93298
|
+
}
|
|
93299
|
+
function convergeDivergedSubmoduleGitlinks(worktreeRoot, baseRepoRoot, baseHead, branchHead) {
|
|
93300
|
+
const changed = readChangedGitlinkPaths(worktreeRoot, baseHead, branchHead);
|
|
93301
|
+
if (changed.length === 0) {
|
|
93302
|
+
return { converged: false, reason: "no_changed_gitlinks", resolutions: [], gitlinks: [] };
|
|
93303
|
+
}
|
|
93304
|
+
const gitlinks = [];
|
|
93305
|
+
const resolutions = [];
|
|
93306
|
+
let sawDiverged = false;
|
|
93307
|
+
for (const path46 of changed) {
|
|
93308
|
+
const baseCommit = readTreeObject(baseRepoRoot, baseHead, path46);
|
|
93309
|
+
const branchCommit = readTreeObject(worktreeRoot, branchHead, path46);
|
|
93310
|
+
const submoduleRepoPath = (0, import_path15.resolve)(worktreeRoot, path46);
|
|
93311
|
+
if (baseCommit) {
|
|
93312
|
+
ensureSubmoduleCommitLocal(submoduleRepoPath, (0, import_path15.resolve)(baseRepoRoot, path46), baseCommit);
|
|
93313
|
+
}
|
|
93314
|
+
if (!baseCommit || !branchCommit || !isSubmoduleDivergedSibling(submoduleRepoPath, baseCommit, branchCommit)) {
|
|
93315
|
+
gitlinks.push({ path: path46, baseCommit, branchCommit, action: "skipped_not_diverged" });
|
|
93316
|
+
continue;
|
|
93317
|
+
}
|
|
93318
|
+
sawDiverged = true;
|
|
93319
|
+
let rebasedCommit;
|
|
93320
|
+
try {
|
|
93321
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["checkout", "-q", "--detach", branchCommit], { cwd: submoduleRepoPath, stdio: ["ignore", "ignore", "pipe"] });
|
|
93322
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["rebase", baseCommit], { cwd: submoduleRepoPath, stdio: ["ignore", "pipe", "pipe"] });
|
|
93323
|
+
rebasedCommit = (0, import_node_child_process6.execFileSync)(GIT2, ["rev-parse", "HEAD"], { cwd: submoduleRepoPath, encoding: "utf8" }).trim();
|
|
93324
|
+
} catch {
|
|
93325
|
+
try {
|
|
93326
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["rebase", "--abort"], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93327
|
+
} catch {
|
|
93328
|
+
}
|
|
93329
|
+
try {
|
|
93330
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["checkout", "-q", "--detach", branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
93331
|
+
} catch {
|
|
93332
|
+
}
|
|
93333
|
+
gitlinks.push({ path: path46, baseCommit, branchCommit, action: "rebase_conflict" });
|
|
93334
|
+
return { converged: false, reason: "rebase_conflict", resolutions: [], gitlinks };
|
|
93335
|
+
}
|
|
93336
|
+
gitlinks.push({ path: path46, baseCommit, branchCommit, rebasedCommit, action: "rebased" });
|
|
93337
|
+
resolutions.push({ path: path46, baseCommit, branchCommit, rebasedCommit });
|
|
93338
|
+
}
|
|
93339
|
+
if (!sawDiverged) {
|
|
93340
|
+
return { converged: false, reason: "not_diverged", resolutions: [], gitlinks };
|
|
93341
|
+
}
|
|
93342
|
+
return { converged: resolutions.length > 0, resolutions, gitlinks };
|
|
93343
|
+
}
|
|
93344
|
+
function rootRebaseResolvingGitlinks(worktreeRoot, baseHead, resolutions) {
|
|
93345
|
+
const resolveByPath = new Map(resolutions.map((r) => [r.path, r.rebasedCommit]));
|
|
93346
|
+
const runRebase = (args) => {
|
|
93347
|
+
try {
|
|
93348
|
+
(0, import_node_child_process6.execFileSync)(GIT2, args, {
|
|
93349
|
+
cwd: worktreeRoot,
|
|
93350
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
93351
|
+
// A rebase editor prompt would hang; keep it non-interactive.
|
|
93352
|
+
env: { ...process.env, GIT_EDITOR: "true", GIT_SEQUENCE_EDITOR: "true" }
|
|
93353
|
+
});
|
|
93354
|
+
return { ok: true };
|
|
93355
|
+
} catch {
|
|
93356
|
+
return { ok: false };
|
|
93357
|
+
}
|
|
93358
|
+
};
|
|
93359
|
+
const unmergedPaths = () => {
|
|
93360
|
+
try {
|
|
93361
|
+
return (0, import_node_child_process6.execFileSync)(GIT2, ["diff", "--name-only", "--diff-filter=U"], { cwd: worktreeRoot, encoding: "utf8" }).split("\n").map((s2) => s2.trim()).filter(Boolean);
|
|
93362
|
+
} catch {
|
|
93363
|
+
return [];
|
|
93364
|
+
}
|
|
93365
|
+
};
|
|
93366
|
+
const abort = (reason, conflictPaths) => {
|
|
93367
|
+
try {
|
|
93368
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["rebase", "--abort"], { cwd: worktreeRoot, stdio: "ignore" });
|
|
93369
|
+
} catch {
|
|
93370
|
+
}
|
|
93371
|
+
return { ok: false, reason, conflictPaths };
|
|
93372
|
+
};
|
|
93373
|
+
let progress = runRebase(["rebase", baseHead]);
|
|
93374
|
+
let guard = 0;
|
|
93375
|
+
while (!progress.ok) {
|
|
93376
|
+
if (guard++ > 100) return abort("rebase_error");
|
|
93377
|
+
const conflicts = unmergedPaths();
|
|
93378
|
+
if (conflicts.length === 0) {
|
|
93379
|
+
return abort("rebase_error");
|
|
93380
|
+
}
|
|
93381
|
+
const unresolvable = conflicts.filter((p) => !resolveByPath.has(p));
|
|
93382
|
+
if (unresolvable.length > 0) {
|
|
93383
|
+
const unresolvableGitlink = unresolvable.some((p) => {
|
|
93384
|
+
try {
|
|
93385
|
+
const staged = (0, import_node_child_process6.execFileSync)(GIT2, ["ls-files", "--stage", "--", p], { cwd: worktreeRoot, encoding: "utf8" });
|
|
93386
|
+
return /^160000\s/m.test(staged);
|
|
93387
|
+
} catch {
|
|
93388
|
+
return false;
|
|
93389
|
+
}
|
|
93390
|
+
});
|
|
93391
|
+
const allGitlink = unresolvable.every((p) => {
|
|
93392
|
+
try {
|
|
93393
|
+
const staged = (0, import_node_child_process6.execFileSync)(GIT2, ["ls-files", "--stage", "--", p], { cwd: worktreeRoot, encoding: "utf8" });
|
|
93394
|
+
return /^160000\s/m.test(staged);
|
|
93395
|
+
} catch {
|
|
93396
|
+
return false;
|
|
93397
|
+
}
|
|
93398
|
+
});
|
|
93399
|
+
return abort(allGitlink && unresolvableGitlink ? "unexpected_gitlink" : "non_gitlink_conflict", conflicts);
|
|
93400
|
+
}
|
|
93401
|
+
for (const p of conflicts) {
|
|
93402
|
+
const commit = resolveByPath.get(p);
|
|
93403
|
+
try {
|
|
93404
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["checkout", "-q", "--detach", commit], { cwd: (0, import_path15.resolve)(worktreeRoot, p), stdio: "ignore" });
|
|
93405
|
+
} catch {
|
|
93406
|
+
}
|
|
93407
|
+
try {
|
|
93408
|
+
(0, import_node_child_process6.execFileSync)(GIT2, ["add", p], { cwd: worktreeRoot, stdio: "ignore" });
|
|
93409
|
+
} catch {
|
|
93410
|
+
return abort("rebase_error", conflicts);
|
|
93411
|
+
}
|
|
93412
|
+
}
|
|
93413
|
+
progress = runRebase(["rebase", "--continue"]);
|
|
93414
|
+
}
|
|
93415
|
+
let branchHead;
|
|
93416
|
+
try {
|
|
93417
|
+
branchHead = (0, import_node_child_process6.execFileSync)(GIT2, ["rev-parse", "HEAD"], { cwd: worktreeRoot, encoding: "utf8" }).trim();
|
|
93418
|
+
} catch {
|
|
93419
|
+
}
|
|
93420
|
+
return { ok: true, branchHead };
|
|
93421
|
+
}
|
|
92811
93422
|
function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
|
|
92812
93423
|
const changedGitlinks = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path46) => {
|
|
92813
93424
|
const baseCommit = readTreeObject(repoRoot, baseHead, path46);
|
|
@@ -93837,6 +94448,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
93837
94448
|
async function refineSyncBaseStage(self, ctx) {
|
|
93838
94449
|
const { repoRoot, baseHead, node, branch, baseBranch, refineStages, execFileAsync: execFileAsync4 } = ctx;
|
|
93839
94450
|
let branchHead = ctx.branchHead;
|
|
94451
|
+
let gitlinkResolutions = [];
|
|
93840
94452
|
const syncStarted = Date.now();
|
|
93841
94453
|
const divergence = await computeBranchBaseDivergence(execFileAsync4, node.workspace, baseHead, branchHead);
|
|
93842
94454
|
if (divergence.behind === 0) {
|
|
@@ -93852,24 +94464,61 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
93852
94464
|
const preRebasePe = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
|
|
93853
94465
|
const alreadyMerged = !preRebasePe.actualPatchId && !!preRebasePe.expectedPatchId;
|
|
93854
94466
|
const submoduleConflict = preRebasePe.actionableHint?.kind === "submodule_conflict";
|
|
93855
|
-
if (alreadyMerged
|
|
94467
|
+
if (alreadyMerged) {
|
|
93856
94468
|
recordMeshRefineStage(refineStages, "sync_base", "passed", syncStarted, {
|
|
93857
94469
|
ahead: divergence.ahead,
|
|
93858
94470
|
behind: divergence.behind,
|
|
93859
94471
|
rebased: false,
|
|
93860
|
-
reason:
|
|
94472
|
+
reason: "already_merged_via_other_path_skip_rebase"
|
|
93861
94473
|
});
|
|
93862
94474
|
return { kind: "continue", ctx };
|
|
93863
94475
|
}
|
|
94476
|
+
if (submoduleConflict) {
|
|
94477
|
+
const converge = convergeDivergedSubmoduleGitlinks(node.workspace, repoRoot, baseHead, branchHead);
|
|
94478
|
+
if (converge.converged) {
|
|
94479
|
+
gitlinkResolutions = converge.resolutions;
|
|
94480
|
+
recordMeshRefineStage(refineStages, "submodule_gitlink_converge", "passed", syncStarted, {
|
|
94481
|
+
reason: "submodule_diverged_auto_rebased",
|
|
94482
|
+
gitlinks: converge.gitlinks
|
|
94483
|
+
});
|
|
94484
|
+
LOG2.info("Mesh", `[Refinery] Auto-converged diverged submodule gitlink(s) onto base for node ${node.id}: ` + converge.resolutions.map((r) => `${r.path}\u2192${r.rebasedCommit.slice(0, 12)}`).join(", "));
|
|
94485
|
+
} else {
|
|
94486
|
+
recordMeshRefineStage(refineStages, "submodule_gitlink_converge", "skipped", syncStarted, {
|
|
94487
|
+
reason: "submodule_conflict_defer_to_patch_equivalence",
|
|
94488
|
+
convergeReason: converge.reason,
|
|
94489
|
+
gitlinks: converge.gitlinks
|
|
94490
|
+
});
|
|
94491
|
+
recordMeshRefineStage(refineStages, "sync_base", "passed", syncStarted, {
|
|
94492
|
+
ahead: divergence.ahead,
|
|
94493
|
+
behind: divergence.behind,
|
|
94494
|
+
rebased: false,
|
|
94495
|
+
reason: "submodule_conflict_defer_to_patch_equivalence"
|
|
94496
|
+
});
|
|
94497
|
+
return { kind: "continue", ctx };
|
|
94498
|
+
}
|
|
94499
|
+
}
|
|
93864
94500
|
} catch {
|
|
93865
94501
|
}
|
|
93866
94502
|
const rebaseStarted = Date.now();
|
|
93867
94503
|
try {
|
|
93868
|
-
(
|
|
94504
|
+
if (gitlinkResolutions.length > 0) {
|
|
94505
|
+
const gitlinkRebase = rootRebaseResolvingGitlinks(node.workspace, baseHead, gitlinkResolutions);
|
|
94506
|
+
if (!gitlinkRebase.ok) {
|
|
94507
|
+
const err = new Error(`gitlink-aware rebase aborted: ${gitlinkRebase.reason || "unknown"}`);
|
|
94508
|
+
err.gitlinkRebaseReason = gitlinkRebase.reason;
|
|
94509
|
+
err.gitlinkRebaseConflicts = gitlinkRebase.conflictPaths;
|
|
94510
|
+
err.alreadyAborted = true;
|
|
94511
|
+
throw err;
|
|
94512
|
+
}
|
|
94513
|
+
} else {
|
|
94514
|
+
(0, import_node_child_process7.execFileSync)("git", ["rebase", baseHead], { cwd: node.workspace, stdio: ["ignore", "pipe", "pipe"] });
|
|
94515
|
+
}
|
|
93869
94516
|
} catch (rebaseErr) {
|
|
93870
|
-
|
|
93871
|
-
|
|
93872
|
-
|
|
94517
|
+
if (!rebaseErr?.alreadyAborted) {
|
|
94518
|
+
try {
|
|
94519
|
+
(0, import_node_child_process7.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
|
|
94520
|
+
} catch {
|
|
94521
|
+
}
|
|
93873
94522
|
}
|
|
93874
94523
|
let submoduleHintPatchEquivalence;
|
|
93875
94524
|
try {
|
|
@@ -96176,7 +96825,15 @@ ${e?.stderr || ""}`;
|
|
|
96176
96825
|
// returns 'Session not found' (same class as mission 6938892f). Unlike read_terminal this
|
|
96177
96826
|
// MUTATES the worker PTY, so forwarding to the real owner (not a wrong local session) is
|
|
96178
96827
|
// doubly important. The daemon re-enforces the destructive-key confirm gate after the forward.
|
|
96179
|
-
"send_keys"
|
|
96828
|
+
"send_keys",
|
|
96829
|
+
// interactive_prompt_response (mesh_answer_question, mission f1d25e11): the coordinator
|
|
96830
|
+
// answers a REMOTE worker's AskUserQuestion (waiting_choice). The answer must reach the
|
|
96831
|
+
// OWNING worker session's live instance — its activeInteractivePrompt (the authoritative
|
|
96832
|
+
// prompt the labels/indexes resolve against) and its adapter.setInteractivePromptResponse
|
|
96833
|
+
// live only there. Without forwarding, the coordinator's local high-family handler returns
|
|
96834
|
+
// 'No running instance for session …' and the question is never answered — the exact
|
|
96835
|
+
// remote-worker forwarding gap of mission 6938892f, now closed for questions too.
|
|
96836
|
+
"interactive_prompt_response"
|
|
96180
96837
|
]);
|
|
96181
96838
|
function normalizeCommandSource(source) {
|
|
96182
96839
|
switch (source) {
|