@adhdev/daemon-standalone 0.9.82-rc.351 → 0.9.82-rc.352
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 +422 -183
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30036,10 +30036,10 @@ var require_dist3 = __commonJS({
|
|
|
30036
30036
|
}
|
|
30037
30037
|
function getDaemonBuildInfo() {
|
|
30038
30038
|
if (cached2) return cached2;
|
|
30039
|
-
const commit = readInjected(true ? "
|
|
30040
|
-
const commitShort = readInjected(true ? "
|
|
30041
|
-
const version2 = readInjected(true ? "0.9.82-rc.
|
|
30042
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
30039
|
+
const commit = readInjected(true ? "ca5f944b7763a621357fc28a9f62ac398b0ced6c" : void 0) ?? "unknown";
|
|
30040
|
+
const commitShort = readInjected(true ? "ca5f944b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30041
|
+
const version2 = readInjected(true ? "0.9.82-rc.352" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30042
|
+
const builtAt = readInjected(true ? "2026-06-22T07:17:32.309Z" : void 0);
|
|
30043
30043
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30044
30044
|
return cached2;
|
|
30045
30045
|
}
|
|
@@ -32936,6 +32936,7 @@ Follow these recovery rules:
|
|
|
32936
32936
|
var LEVEL_NUM;
|
|
32937
32937
|
var LEVEL_LABEL;
|
|
32938
32938
|
var currentLevel;
|
|
32939
|
+
var ADHDEV_HOME;
|
|
32939
32940
|
var LOG_DIR;
|
|
32940
32941
|
var MAX_LOG_SIZE;
|
|
32941
32942
|
var MAX_LOG_DAYS;
|
|
@@ -32961,7 +32962,8 @@ Follow these recovery rules:
|
|
|
32961
32962
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
32962
32963
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
32963
32964
|
currentLevel = "info";
|
|
32964
|
-
|
|
32965
|
+
ADHDEV_HOME = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path9.join(os32.homedir(), ".adhdev");
|
|
32966
|
+
LOG_DIR = path9.join(ADHDEV_HOME, "logs");
|
|
32965
32967
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
32966
32968
|
MAX_LOG_DAYS = 7;
|
|
32967
32969
|
try {
|
|
@@ -33774,6 +33776,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
33774
33776
|
nodeSatisfiesRequiredTags: () => nodeSatisfiesRequiredTags,
|
|
33775
33777
|
normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
|
|
33776
33778
|
normalizeMeshTaskMode: () => normalizeMeshTaskMode,
|
|
33779
|
+
reclaimStrandedAssignedTask: () => reclaimStrandedAssignedTask,
|
|
33777
33780
|
recordDirectDispatchTask: () => recordDirectDispatchTask,
|
|
33778
33781
|
recordMeshToolCall: () => recordMeshToolCall,
|
|
33779
33782
|
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
@@ -34209,6 +34212,52 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34209
34212
|
return entry;
|
|
34210
34213
|
});
|
|
34211
34214
|
}
|
|
34215
|
+
function reclaimStrandedAssignedTask(meshId, taskId, opts) {
|
|
34216
|
+
requireMeshHostQueueOwner(opts);
|
|
34217
|
+
return withQueueLock(meshId, () => {
|
|
34218
|
+
const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
|
|
34219
|
+
if (!entry) return null;
|
|
34220
|
+
if (entry.status !== "assigned") return null;
|
|
34221
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34222
|
+
const reason = opts?.reason || "assigned_stranded_dispatch_unconfirmed";
|
|
34223
|
+
const reclaims = (entry.strandedReclaimCount || 0) + 1;
|
|
34224
|
+
const prevNode = entry.assignedNodeId;
|
|
34225
|
+
const prevSession = entry.assignedSessionId;
|
|
34226
|
+
delete entry.assignedNodeId;
|
|
34227
|
+
delete entry.assignedSessionId;
|
|
34228
|
+
delete entry.assignedProviderType;
|
|
34229
|
+
delete entry.dispatchTimestamp;
|
|
34230
|
+
entry.strandedReclaimCount = reclaims;
|
|
34231
|
+
entry.updatedAt = now;
|
|
34232
|
+
if (reclaims > MAX_STRANDED_RECLAIMS) {
|
|
34233
|
+
entry.status = "failed";
|
|
34234
|
+
entry.cancelReason = `stranded_dispatch_unrecovered: reclaimed ${reclaims - 1} time(s) without a confirmed dispatch`;
|
|
34235
|
+
MeshRuntimeStore.getInstance().updateQueueEntry(entry);
|
|
34236
|
+
propagateDependencyFailure(meshId, taskId);
|
|
34237
|
+
} else {
|
|
34238
|
+
entry.status = "pending";
|
|
34239
|
+
entry.requeuedAt = now;
|
|
34240
|
+
entry.requeueReason = reason;
|
|
34241
|
+
MeshRuntimeStore.getInstance().updateQueueEntry(entry);
|
|
34242
|
+
}
|
|
34243
|
+
try {
|
|
34244
|
+
appendLedgerEntry(meshId, {
|
|
34245
|
+
kind: "task_reclaimed",
|
|
34246
|
+
nodeId: prevNode,
|
|
34247
|
+
sessionId: prevSession,
|
|
34248
|
+
payload: {
|
|
34249
|
+
taskId,
|
|
34250
|
+
reason,
|
|
34251
|
+
...typeof opts?.ageMs === "number" ? { ageMs: opts.ageMs } : {},
|
|
34252
|
+
reclaimCount: reclaims,
|
|
34253
|
+
outcome: entry.status
|
|
34254
|
+
}
|
|
34255
|
+
});
|
|
34256
|
+
} catch {
|
|
34257
|
+
}
|
|
34258
|
+
return entry;
|
|
34259
|
+
});
|
|
34260
|
+
}
|
|
34212
34261
|
function updateSessionTaskStatus(meshId, sessionId, status, opts) {
|
|
34213
34262
|
return withQueueLock(meshId, () => {
|
|
34214
34263
|
const store = MeshRuntimeStore.getInstance();
|
|
@@ -34332,6 +34381,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34332
34381
|
var GIT_MUTATION_SUBCOMMANDS;
|
|
34333
34382
|
var GIT_STASH_READONLY_SUBCOMMANDS;
|
|
34334
34383
|
var DEPENDENCY_FAILURE_TERMINALS;
|
|
34384
|
+
var MAX_STRANDED_RECLAIMS;
|
|
34335
34385
|
var init_mesh_work_queue = __esm2({
|
|
34336
34386
|
"src/mesh/mesh-work-queue.ts"() {
|
|
34337
34387
|
"use strict";
|
|
@@ -34341,6 +34391,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34341
34391
|
init_mesh_runtime_store();
|
|
34342
34392
|
init_mesh_config();
|
|
34343
34393
|
init_logger();
|
|
34394
|
+
init_mesh_ledger();
|
|
34344
34395
|
ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
|
|
34345
34396
|
HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
|
|
34346
34397
|
MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
|
|
@@ -34393,6 +34444,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34393
34444
|
]);
|
|
34394
34445
|
GIT_STASH_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set(["list", "show"]);
|
|
34395
34446
|
DEPENDENCY_FAILURE_TERMINALS = /* @__PURE__ */ new Set(["failed", "cancelled"]);
|
|
34447
|
+
MAX_STRANDED_RECLAIMS = 3;
|
|
34396
34448
|
}
|
|
34397
34449
|
});
|
|
34398
34450
|
function loadDatabaseCtor() {
|
|
@@ -35280,6 +35332,22 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
35280
35332
|
updatedAt: r.updated_at
|
|
35281
35333
|
}));
|
|
35282
35334
|
}
|
|
35335
|
+
/**
|
|
35336
|
+
* Bug B watchdog support: true when at least one delivery record for the task has
|
|
35337
|
+
* reached a confirmed-handed-off status (delivered / acked / completed). The
|
|
35338
|
+
* assigned-stranded watchdog uses this to distinguish a dispatch that was never
|
|
35339
|
+
* confirmed (reclaimable) from one that WAS handed to the worker (a genuinely
|
|
35340
|
+
* in-flight or completion-lost task, which is PHASE 4's responsibility, not this
|
|
35341
|
+
* watchdog's). Indexed by (mesh_id, task_id).
|
|
35342
|
+
*/
|
|
35343
|
+
taskHasConfirmedDelivery(meshId, taskId) {
|
|
35344
|
+
const row = this.db.prepare(`
|
|
35345
|
+
SELECT 1 FROM mesh_session_delivery
|
|
35346
|
+
WHERE mesh_id = ? AND task_id = ? AND status IN ('delivered','acked','completed')
|
|
35347
|
+
LIMIT 1
|
|
35348
|
+
`).get(meshId, taskId);
|
|
35349
|
+
return !!row;
|
|
35350
|
+
}
|
|
35283
35351
|
expireStaleSessionDeliveries(meshId) {
|
|
35284
35352
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
35285
35353
|
this.db.prepare(`
|
|
@@ -37704,6 +37772,35 @@ ${rendered}`, "utf-8");
|
|
|
37704
37772
|
if (!trimmed) return false;
|
|
37705
37773
|
return normalizeMeshNodeId(node) === trimmed;
|
|
37706
37774
|
}
|
|
37775
|
+
function machineCoreFromDaemonId(id) {
|
|
37776
|
+
const trimmed = readString5(id);
|
|
37777
|
+
if (!trimmed) return void 0;
|
|
37778
|
+
for (const prefix of DAEMON_ID_PREFIXES) {
|
|
37779
|
+
if (trimmed.startsWith(prefix)) {
|
|
37780
|
+
const core = trimmed.slice(prefix.length).trim();
|
|
37781
|
+
return core || void 0;
|
|
37782
|
+
}
|
|
37783
|
+
}
|
|
37784
|
+
return trimmed;
|
|
37785
|
+
}
|
|
37786
|
+
function expandDaemonIdForms(ids) {
|
|
37787
|
+
const list = Array.isArray(ids) ? ids : ids != null ? [ids] : [];
|
|
37788
|
+
const out = [];
|
|
37789
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37790
|
+
const add = (value) => {
|
|
37791
|
+
if (!value || seen.has(value)) return;
|
|
37792
|
+
seen.add(value);
|
|
37793
|
+
out.push(value);
|
|
37794
|
+
};
|
|
37795
|
+
for (const raw of list) add(readString5(raw));
|
|
37796
|
+
for (const raw of list) {
|
|
37797
|
+
const core = machineCoreFromDaemonId(readString5(raw));
|
|
37798
|
+
if (!core || !core.startsWith("mach_")) continue;
|
|
37799
|
+
add(core);
|
|
37800
|
+
for (const prefix of DAEMON_ID_PREFIXES) add(`${prefix}${core}`);
|
|
37801
|
+
}
|
|
37802
|
+
return out;
|
|
37803
|
+
}
|
|
37707
37804
|
function summarizeGitShape(status) {
|
|
37708
37805
|
const record2 = readRecord3(status);
|
|
37709
37806
|
if (!Object.keys(record2).length) return null;
|
|
@@ -37738,9 +37835,11 @@ ${rendered}`, "utf-8");
|
|
|
37738
37835
|
submodules
|
|
37739
37836
|
};
|
|
37740
37837
|
}
|
|
37838
|
+
var DAEMON_ID_PREFIXES;
|
|
37741
37839
|
var init_dist = __esm2({
|
|
37742
37840
|
"../mesh-shared/dist/index.mjs"() {
|
|
37743
37841
|
"use strict";
|
|
37842
|
+
DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
|
|
37744
37843
|
}
|
|
37745
37844
|
});
|
|
37746
37845
|
function readString6(value) {
|
|
@@ -38395,17 +38494,7 @@ Next step: ${nextStep}`;
|
|
|
38395
38494
|
}
|
|
38396
38495
|
});
|
|
38397
38496
|
function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
|
|
38398
|
-
|
|
38399
|
-
const seen = /* @__PURE__ */ new Set();
|
|
38400
|
-
const out = [];
|
|
38401
|
-
for (const id of raw) {
|
|
38402
|
-
if (typeof id !== "string") continue;
|
|
38403
|
-
const trimmed = id.trim();
|
|
38404
|
-
if (!trimmed || seen.has(trimmed)) continue;
|
|
38405
|
-
seen.add(trimmed);
|
|
38406
|
-
out.push(trimmed);
|
|
38407
|
-
}
|
|
38408
|
-
return out;
|
|
38497
|
+
return expandDaemonIdForms(coordinatorDaemonId);
|
|
38409
38498
|
}
|
|
38410
38499
|
function readRefineJobId2(event) {
|
|
38411
38500
|
const metadata = readRecord4(event.metadataEvent) || event;
|
|
@@ -38800,6 +38889,7 @@ Next step: ${nextStep}`;
|
|
|
38800
38889
|
init_mesh_ledger();
|
|
38801
38890
|
init_mesh_runtime_store();
|
|
38802
38891
|
init_mesh_events_utils();
|
|
38892
|
+
init_dist();
|
|
38803
38893
|
REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
|
|
38804
38894
|
MAX_PENDING_EVENTS_BYTES = 100 * 1024;
|
|
38805
38895
|
MAX_PENDING_EVENTS_KEEP = 50;
|
|
@@ -42257,12 +42347,9 @@ ${cleanBody}`;
|
|
|
42257
42347
|
}
|
|
42258
42348
|
});
|
|
42259
42349
|
function resolveCoordinatorDrainDaemonIds(components) {
|
|
42260
|
-
const ids = /* @__PURE__ */ new Set();
|
|
42261
42350
|
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
42262
|
-
if (statusInstanceId) ids.add(statusInstanceId);
|
|
42263
42351
|
const machineId = readNonEmptyString2(loadConfig2().machineId);
|
|
42264
|
-
|
|
42265
|
-
return [...ids];
|
|
42352
|
+
return expandDaemonIdForms([statusInstanceId, machineId]);
|
|
42266
42353
|
}
|
|
42267
42354
|
function getCachedMeshByWorkspace(workspace) {
|
|
42268
42355
|
const now = Date.now();
|
|
@@ -42413,6 +42500,55 @@ ${cleanBody}`;
|
|
|
42413
42500
|
return void 0;
|
|
42414
42501
|
}
|
|
42415
42502
|
}
|
|
42503
|
+
function deliverTaskToSession(dispatchThunk, ctx) {
|
|
42504
|
+
const delivery = createSessionDelivery({
|
|
42505
|
+
meshId: ctx.meshId,
|
|
42506
|
+
nodeId: ctx.nodeId,
|
|
42507
|
+
sessionId: ctx.sessionId,
|
|
42508
|
+
providerType: ctx.providerType,
|
|
42509
|
+
taskId: ctx.task.id,
|
|
42510
|
+
kind: "task",
|
|
42511
|
+
message: ctx.task.message,
|
|
42512
|
+
status: "delivering",
|
|
42513
|
+
...ctx.sourceCoordinatorSessionId ? { sourceCoordinatorSessionId: ctx.sourceCoordinatorSessionId } : {},
|
|
42514
|
+
...ctx.sourceCoordinatorDaemonId ? { sourceCoordinatorDaemonId: ctx.sourceCoordinatorDaemonId } : {}
|
|
42515
|
+
});
|
|
42516
|
+
let dispatchPromise;
|
|
42517
|
+
try {
|
|
42518
|
+
dispatchPromise = Promise.resolve(dispatchThunk());
|
|
42519
|
+
} catch (e) {
|
|
42520
|
+
dispatchPromise = Promise.reject(e);
|
|
42521
|
+
}
|
|
42522
|
+
let timer;
|
|
42523
|
+
const guarded = Promise.race([
|
|
42524
|
+
dispatchPromise,
|
|
42525
|
+
new Promise((_, reject) => {
|
|
42526
|
+
timer = setTimeout(
|
|
42527
|
+
() => reject(new Error(`dispatch_confirm_timeout after ${DISPATCH_CONFIRM_TIMEOUT_MS}ms`)),
|
|
42528
|
+
DISPATCH_CONFIRM_TIMEOUT_MS
|
|
42529
|
+
);
|
|
42530
|
+
if (typeof timer?.unref === "function") timer.unref();
|
|
42531
|
+
})
|
|
42532
|
+
]);
|
|
42533
|
+
guarded.then(() => {
|
|
42534
|
+
if (timer) clearTimeout(timer);
|
|
42535
|
+
updateSessionDeliveryStatus(delivery.id, "delivered");
|
|
42536
|
+
}).catch((e) => {
|
|
42537
|
+
if (timer) clearTimeout(timer);
|
|
42538
|
+
LOG2.error("MeshQueue", `Failed to dispatch task via ${ctx.transport} to node ${ctx.nodeId}: ${e?.message}`);
|
|
42539
|
+
updateSessionDeliveryStatus(delivery.id, "failed", { lastError: e?.message, incrementAttempt: true });
|
|
42540
|
+
updateTaskStatus(ctx.meshId, ctx.task.id, "pending");
|
|
42541
|
+
try {
|
|
42542
|
+
appendLedgerEntry(ctx.meshId, {
|
|
42543
|
+
kind: "dispatch_failed",
|
|
42544
|
+
nodeId: ctx.nodeId,
|
|
42545
|
+
sessionId: ctx.sessionId,
|
|
42546
|
+
payload: { taskId: ctx.task.id, deliveryId: delivery.id, error: e?.message, retryable: true, transport: ctx.transport }
|
|
42547
|
+
});
|
|
42548
|
+
} catch {
|
|
42549
|
+
}
|
|
42550
|
+
});
|
|
42551
|
+
}
|
|
42416
42552
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
42417
42553
|
const mesh = getMeshWithCache(components, meshId);
|
|
42418
42554
|
const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
|
|
@@ -42431,46 +42567,33 @@ ${cleanBody}`;
|
|
|
42431
42567
|
if (!isLocalNode) {
|
|
42432
42568
|
const localDaemonIdForDispatch = readNonEmptyString2(loadConfig2().machineId) || void 0;
|
|
42433
42569
|
const sourceCoordinatorSessionId = readNonEmptyString2(task.sourceCoordinatorSessionId) || void 0;
|
|
42434
|
-
const
|
|
42435
|
-
|
|
42436
|
-
|
|
42437
|
-
|
|
42438
|
-
|
|
42439
|
-
|
|
42440
|
-
|
|
42441
|
-
|
|
42442
|
-
|
|
42443
|
-
|
|
42444
|
-
|
|
42445
|
-
|
|
42446
|
-
|
|
42447
|
-
|
|
42448
|
-
|
|
42449
|
-
|
|
42450
|
-
|
|
42451
|
-
meshContext: {
|
|
42570
|
+
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
42571
|
+
const remoteDaemonId = node.daemonId;
|
|
42572
|
+
deliverTaskToSession(
|
|
42573
|
+
() => dispatchMeshCommand(remoteDaemonId, "agent_command", {
|
|
42574
|
+
targetSessionId: sessionId,
|
|
42575
|
+
cliType: providerType,
|
|
42576
|
+
action: "send_chat",
|
|
42577
|
+
message: task.message,
|
|
42578
|
+
meshContext: {
|
|
42579
|
+
meshId,
|
|
42580
|
+
nodeId,
|
|
42581
|
+
taskId: task.id,
|
|
42582
|
+
...localDaemonIdForDispatch ? { coordinatorDaemonId: localDaemonIdForDispatch } : {},
|
|
42583
|
+
...sourceCoordinatorSessionId ? { coordinatorSessionId: sourceCoordinatorSessionId } : {}
|
|
42584
|
+
}
|
|
42585
|
+
}),
|
|
42586
|
+
{
|
|
42452
42587
|
meshId,
|
|
42453
42588
|
nodeId,
|
|
42454
|
-
|
|
42455
|
-
|
|
42456
|
-
|
|
42457
|
-
|
|
42458
|
-
|
|
42459
|
-
|
|
42460
|
-
}).catch((e) => {
|
|
42461
|
-
LOG2.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
42462
|
-
updateSessionDeliveryStatus(delivery2.id, "failed", { lastError: e?.message, incrementAttempt: true });
|
|
42463
|
-
updateTaskStatus(meshId, task.id, "pending");
|
|
42464
|
-
try {
|
|
42465
|
-
appendLedgerEntry(meshId, {
|
|
42466
|
-
kind: "dispatch_failed",
|
|
42467
|
-
nodeId,
|
|
42468
|
-
sessionId,
|
|
42469
|
-
payload: { taskId: task.id, deliveryId: delivery2.id, error: e?.message, retryable: true }
|
|
42470
|
-
});
|
|
42471
|
-
} catch {
|
|
42589
|
+
sessionId,
|
|
42590
|
+
providerType,
|
|
42591
|
+
task,
|
|
42592
|
+
transport: "remote",
|
|
42593
|
+
...sourceCoordinatorSessionId ? { sourceCoordinatorSessionId } : {},
|
|
42594
|
+
...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {}
|
|
42472
42595
|
}
|
|
42473
|
-
|
|
42596
|
+
);
|
|
42474
42597
|
return true;
|
|
42475
42598
|
}
|
|
42476
42599
|
}
|
|
@@ -42492,39 +42615,24 @@ ${cleanBody}`;
|
|
|
42492
42615
|
}
|
|
42493
42616
|
} catch {
|
|
42494
42617
|
}
|
|
42495
|
-
|
|
42496
|
-
|
|
42497
|
-
|
|
42498
|
-
|
|
42499
|
-
|
|
42500
|
-
|
|
42501
|
-
|
|
42502
|
-
|
|
42503
|
-
|
|
42504
|
-
|
|
42505
|
-
|
|
42506
|
-
|
|
42507
|
-
|
|
42508
|
-
|
|
42509
|
-
|
|
42510
|
-
|
|
42511
|
-
message: task.message
|
|
42512
|
-
}).then(() => {
|
|
42513
|
-
updateSessionDeliveryStatus(delivery.id, "delivered");
|
|
42514
|
-
}).catch((e) => {
|
|
42515
|
-
LOG2.error("MeshQueue", `Failed to dispatch task locally to node ${nodeId}: ${e?.message}`);
|
|
42516
|
-
updateSessionDeliveryStatus(delivery.id, "failed", { lastError: e?.message, incrementAttempt: true });
|
|
42517
|
-
updateTaskStatus(meshId, task.id, "pending");
|
|
42518
|
-
try {
|
|
42519
|
-
appendLedgerEntry(meshId, {
|
|
42520
|
-
kind: "dispatch_failed",
|
|
42521
|
-
nodeId,
|
|
42522
|
-
sessionId,
|
|
42523
|
-
payload: { taskId: task.id, deliveryId: delivery.id, error: e?.message, retryable: true }
|
|
42524
|
-
});
|
|
42525
|
-
} catch {
|
|
42618
|
+
deliverTaskToSession(
|
|
42619
|
+
() => components.cliManager.handleCliCommand("agent_command", {
|
|
42620
|
+
targetSessionId: sessionId,
|
|
42621
|
+
cliType: providerType,
|
|
42622
|
+
action: "send_chat",
|
|
42623
|
+
message: task.message
|
|
42624
|
+
}),
|
|
42625
|
+
{
|
|
42626
|
+
meshId,
|
|
42627
|
+
nodeId,
|
|
42628
|
+
sessionId,
|
|
42629
|
+
providerType,
|
|
42630
|
+
task,
|
|
42631
|
+
transport: "local",
|
|
42632
|
+
...readNonEmptyString2(task.sourceCoordinatorSessionId) ? { sourceCoordinatorSessionId: readNonEmptyString2(task.sourceCoordinatorSessionId) } : {},
|
|
42633
|
+
...readNonEmptyString2(loadConfig2().machineId) ? { sourceCoordinatorDaemonId: readNonEmptyString2(loadConfig2().machineId) } : {}
|
|
42526
42634
|
}
|
|
42527
|
-
|
|
42635
|
+
);
|
|
42528
42636
|
return true;
|
|
42529
42637
|
}
|
|
42530
42638
|
function sweepExpiredCooldowns() {
|
|
@@ -42789,7 +42897,7 @@ ${cleanBody}`;
|
|
|
42789
42897
|
}
|
|
42790
42898
|
}
|
|
42791
42899
|
const candidateNodes = Array.isArray(mesh?.nodes) ? mesh.nodes.filter((node) => {
|
|
42792
|
-
if (task.targetNodeId &&
|
|
42900
|
+
if (task.targetNodeId && !meshNodeIdMatches(node, task.targetNodeId)) return false;
|
|
42793
42901
|
if (task.requiredTags?.length) {
|
|
42794
42902
|
const priorities = normalizeProviderPriority(node?.policy);
|
|
42795
42903
|
const providerCandidates = priorities.length ? priorities : [void 0];
|
|
@@ -42800,7 +42908,12 @@ ${cleanBody}`;
|
|
|
42800
42908
|
return true;
|
|
42801
42909
|
}) : [];
|
|
42802
42910
|
if (!candidateNodes.length) {
|
|
42803
|
-
|
|
42911
|
+
const targetPinUnmatched = !!task.targetNodeId && !(Array.isArray(mesh?.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, task.targetNodeId)));
|
|
42912
|
+
markAutoLaunch(meshId, task.id, {
|
|
42913
|
+
status: "skipped",
|
|
42914
|
+
reason: targetPinUnmatched ? "target_node_id_unmatched" : "no_node_satisfies_required_tags",
|
|
42915
|
+
nodeId: task.targetNodeId
|
|
42916
|
+
});
|
|
42804
42917
|
continue;
|
|
42805
42918
|
}
|
|
42806
42919
|
const strategy = resolveSchedulingStrategy(mesh);
|
|
@@ -43759,6 +43872,7 @@ ${cleanBody}`;
|
|
|
43759
43872
|
var idleAutoFastForwardLastAttempt;
|
|
43760
43873
|
var INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS;
|
|
43761
43874
|
var RECENT_COMPLETION_FINGERPRINT_TTL_MS;
|
|
43875
|
+
var DISPATCH_CONFIRM_TIMEOUT_MS;
|
|
43762
43876
|
var autoLaunchInProgress;
|
|
43763
43877
|
var autoLaunchCooldownUntil;
|
|
43764
43878
|
var AUTO_LAUNCH_COOLDOWN_MS;
|
|
@@ -43796,6 +43910,7 @@ ${cleanBody}`;
|
|
|
43796
43910
|
idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
|
|
43797
43911
|
INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
|
|
43798
43912
|
RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
|
|
43913
|
+
DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
|
|
43799
43914
|
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
43800
43915
|
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
43801
43916
|
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
@@ -43849,12 +43964,9 @@ ${cleanBody}`;
|
|
|
43849
43964
|
return DEFAULT_RECONCILE_INTERVAL_MS;
|
|
43850
43965
|
}
|
|
43851
43966
|
function resolveCoordinatorDaemonIds(components) {
|
|
43852
|
-
const ids = /* @__PURE__ */ new Set();
|
|
43853
43967
|
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
43854
|
-
if (statusInstanceId) ids.add(statusInstanceId);
|
|
43855
43968
|
const machineId = readNonEmptyString2(loadConfig2().machineId);
|
|
43856
|
-
|
|
43857
|
-
return [...ids];
|
|
43969
|
+
return expandDaemonIdForms([statusInstanceId, machineId]);
|
|
43858
43970
|
}
|
|
43859
43971
|
function daemonHostsMesh(mesh, daemonIds) {
|
|
43860
43972
|
const host = mesh.meshHost;
|
|
@@ -43938,6 +44050,24 @@ ${cleanBody}`;
|
|
|
43938
44050
|
}
|
|
43939
44051
|
}
|
|
43940
44052
|
}
|
|
44053
|
+
function recoverStrandedAssignedDispatches(meshId, store) {
|
|
44054
|
+
const assigned = getQueue(meshId, { status: ["assigned"] });
|
|
44055
|
+
if (!assigned.length) return;
|
|
44056
|
+
const nowMs = Date.now();
|
|
44057
|
+
for (const row of assigned) {
|
|
44058
|
+
const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
|
|
44059
|
+
if (!Number.isFinite(dispatchedAtMs)) continue;
|
|
44060
|
+
if (nowMs - dispatchedAtMs < ASSIGNED_STRANDED_DEADLINE_MS) continue;
|
|
44061
|
+
if (store.taskHasConfirmedDelivery(meshId, row.id)) continue;
|
|
44062
|
+
const reclaimed = reclaimStrandedAssignedTask(meshId, row.id, {
|
|
44063
|
+
reason: "assigned_stranded_dispatch_unconfirmed",
|
|
44064
|
+
ageMs: nowMs - dispatchedAtMs
|
|
44065
|
+
});
|
|
44066
|
+
if (reclaimed) {
|
|
44067
|
+
LOG2.warn("MeshReconcile", `Reclaimed stranded assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, dispatched ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s ago, never confirmed delivered \u2192 ${reclaimed.status})`);
|
|
44068
|
+
}
|
|
44069
|
+
}
|
|
44070
|
+
}
|
|
43941
44071
|
async function runMeshReconcileTick(components) {
|
|
43942
44072
|
const localDaemonId = readNonEmptyString2(loadConfig2().machineId) || void 0;
|
|
43943
44073
|
const drainDaemonIds = resolveCoordinatorDaemonIds(components);
|
|
@@ -43967,6 +44097,17 @@ ${cleanBody}`;
|
|
|
43967
44097
|
}
|
|
43968
44098
|
}
|
|
43969
44099
|
}
|
|
44100
|
+
if (store) {
|
|
44101
|
+
for (const mesh of listMeshes()) {
|
|
44102
|
+
const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
|
|
44103
|
+
if (!daemonHostsMesh(mesh, selfIds)) continue;
|
|
44104
|
+
try {
|
|
44105
|
+
recoverStrandedAssignedDispatches(mesh.id, store);
|
|
44106
|
+
} catch (e) {
|
|
44107
|
+
LOG2.warn("MeshReconcile", `Assigned-stranded watchdog failed for mesh ${mesh.id}: ${e?.message || e}`);
|
|
44108
|
+
}
|
|
44109
|
+
}
|
|
44110
|
+
}
|
|
43970
44111
|
for (const mesh of listMeshes()) {
|
|
43971
44112
|
const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
|
|
43972
44113
|
if (!daemonHostsMesh(mesh, selfIds)) continue;
|
|
@@ -44357,6 +44498,7 @@ ${cleanBody}`;
|
|
|
44357
44498
|
var DEFAULT_RECONCILE_INTERVAL_MS;
|
|
44358
44499
|
var DEFAULT_AUTO_PRUNE_MIN_AGE_MS;
|
|
44359
44500
|
var heldEventLedgerRecorded;
|
|
44501
|
+
var ASSIGNED_STRANDED_DEADLINE_MS;
|
|
44360
44502
|
var STRICT_SESSION_MATCH_TTL_MS;
|
|
44361
44503
|
var init_mesh_reconcile_loop = __esm2({
|
|
44362
44504
|
"src/mesh/mesh-reconcile-loop.ts"() {
|
|
@@ -44370,6 +44512,7 @@ ${cleanBody}`;
|
|
|
44370
44512
|
init_mesh_events_coordinator();
|
|
44371
44513
|
init_mesh_unresolved_forward_outbox();
|
|
44372
44514
|
init_mesh_events_utils();
|
|
44515
|
+
init_dist();
|
|
44373
44516
|
init_mesh_work_queue();
|
|
44374
44517
|
init_mesh_ledger();
|
|
44375
44518
|
init_mesh_active_work();
|
|
@@ -44378,6 +44521,7 @@ ${cleanBody}`;
|
|
|
44378
44521
|
DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
|
|
44379
44522
|
DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
|
|
44380
44523
|
heldEventLedgerRecorded = /* @__PURE__ */ new Set();
|
|
44524
|
+
ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
|
|
44381
44525
|
STRICT_SESSION_MATCH_TTL_MS = 6e4;
|
|
44382
44526
|
}
|
|
44383
44527
|
});
|
|
@@ -44407,6 +44551,82 @@ ${cleanBody}`;
|
|
|
44407
44551
|
init_mesh_events_coordinator();
|
|
44408
44552
|
}
|
|
44409
44553
|
});
|
|
44554
|
+
function normalizeApprovalLabel(value) {
|
|
44555
|
+
return String(value || "").toLowerCase().replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, "").replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
44556
|
+
}
|
|
44557
|
+
function isNegativeApprovalLabel(value) {
|
|
44558
|
+
const label = normalizeApprovalLabel(value);
|
|
44559
|
+
return /^(no|deny|reject|cancel|skip|exit|stop)\b/.test(label) || /\bwithout\b/.test(label) || /\bdo not\b/.test(label);
|
|
44560
|
+
}
|
|
44561
|
+
function hasNegativeApprovalOption(buttons) {
|
|
44562
|
+
return (buttons || []).some((button) => isNegativeApprovalLabel(String(button || "")));
|
|
44563
|
+
}
|
|
44564
|
+
function getApprovalPositiveHints(provider) {
|
|
44565
|
+
const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
|
|
44566
|
+
return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
|
|
44567
|
+
}
|
|
44568
|
+
function pickApprovalButton(buttons, provider) {
|
|
44569
|
+
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
44570
|
+
if (labels.length === 0) {
|
|
44571
|
+
return { index: -1, label: "" };
|
|
44572
|
+
}
|
|
44573
|
+
const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
|
|
44574
|
+
const hints = getApprovalPositiveHints(provider);
|
|
44575
|
+
for (const hint of hints) {
|
|
44576
|
+
const exactIndex = normalizedButtons.findIndex((label, index) => label === hint && !isNegativeApprovalLabel(labels[index]));
|
|
44577
|
+
if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
|
|
44578
|
+
const prefixIndex = normalizedButtons.findIndex((label, index) => label.startsWith(hint) && !isNegativeApprovalLabel(labels[index]));
|
|
44579
|
+
if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
|
|
44580
|
+
const includeIndex = normalizedButtons.findIndex((label, index) => label.includes(hint) && !isNegativeApprovalLabel(labels[index]));
|
|
44581
|
+
if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
|
|
44582
|
+
}
|
|
44583
|
+
return { index: -1, label: "" };
|
|
44584
|
+
}
|
|
44585
|
+
function pickAutoApprovalButton(buttons) {
|
|
44586
|
+
const labels = (buttons || []).map((button) => String(button || "").trim());
|
|
44587
|
+
const index = labels.findIndex(Boolean);
|
|
44588
|
+
return index >= 0 ? { index, label: labels[index] } : { index: -1, label: "" };
|
|
44589
|
+
}
|
|
44590
|
+
function formatAutoApprovalMessage(modalMessage, buttonLabel) {
|
|
44591
|
+
const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
|
|
44592
|
+
const cleanMessage = String(modalMessage || "").trim();
|
|
44593
|
+
if (cleanMessage) lines.push(cleanMessage);
|
|
44594
|
+
return lines.join("\n");
|
|
44595
|
+
}
|
|
44596
|
+
function looksLikeActiveApprovalPromptText(content) {
|
|
44597
|
+
const text = content.trim();
|
|
44598
|
+
if (!text || text.length > 2e3) return false;
|
|
44599
|
+
const hasApprovalQuestion = /do you want to (?:proceed|allow|run|make this edit|create)/i.test(text) || /this command requires approval/i.test(text) || /quick safety check/i.test(text) || /is this a project you trust/i.test(text);
|
|
44600
|
+
const hasNumberedChoices = /^\s*[❯›>]?\s*1[.)]\s+(?:yes|allow|proceed|run)/im.test(text) || /^\s*1[.)]\s+yes\b/im.test(text);
|
|
44601
|
+
if (hasApprovalQuestion && hasNumberedChoices) return true;
|
|
44602
|
+
const lastLines = text.split(/\r?\n/).slice(-12).join("\n");
|
|
44603
|
+
const hasDontAskAgain = /yes.*don'?t ask again/i.test(lastLines) || /yes.*always allow/i.test(lastLines);
|
|
44604
|
+
const hasNoOption = /^\s*[❯›>]?\s*\d+[.)]\s+no\b/im.test(lastLines);
|
|
44605
|
+
if (hasDontAskAgain && hasNoOption) return true;
|
|
44606
|
+
if (/what do you want to do\?/i.test(text) && /^\s*\d+[.)]\s+\S/m.test(text)) return true;
|
|
44607
|
+
return false;
|
|
44608
|
+
}
|
|
44609
|
+
var DEFAULT_APPROVAL_POSITIVE_HINTS;
|
|
44610
|
+
var init_approval_utils = __esm2({
|
|
44611
|
+
"src/providers/approval-utils.ts"() {
|
|
44612
|
+
"use strict";
|
|
44613
|
+
DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
44614
|
+
"yes",
|
|
44615
|
+
"allow once",
|
|
44616
|
+
"approve",
|
|
44617
|
+
"accept",
|
|
44618
|
+
"continue",
|
|
44619
|
+
"run",
|
|
44620
|
+
"proceed",
|
|
44621
|
+
"confirm",
|
|
44622
|
+
"save",
|
|
44623
|
+
"ok",
|
|
44624
|
+
"trust",
|
|
44625
|
+
"allow",
|
|
44626
|
+
"always allow"
|
|
44627
|
+
];
|
|
44628
|
+
}
|
|
44629
|
+
});
|
|
44410
44630
|
function normalizeCategories(categories) {
|
|
44411
44631
|
if (!Array.isArray(categories)) return [];
|
|
44412
44632
|
return categories.map((category) => String(category || "").trim()).filter(Boolean);
|
|
@@ -45393,6 +45613,27 @@ ${cleanBody}`;
|
|
|
45393
45613
|
});
|
|
45394
45614
|
return { prompt, footers };
|
|
45395
45615
|
}
|
|
45616
|
+
function extractButtonLabels(spec, text) {
|
|
45617
|
+
if (!text) return [];
|
|
45618
|
+
const flags = spec.buttonFlags && spec.buttonFlags.includes("m") ? spec.buttonFlags : `${spec.buttonFlags ?? ""}m`;
|
|
45619
|
+
const buttonRe = compile2(spec.buttonPattern, flags);
|
|
45620
|
+
const labelGroup = Number.isInteger(spec.buttonLabelGroup) && (spec.buttonLabelGroup ?? 0) > 0 ? spec.buttonLabelGroup : 1;
|
|
45621
|
+
const out = [];
|
|
45622
|
+
for (const line of text.split("\n")) {
|
|
45623
|
+
buttonRe.lastIndex = 0;
|
|
45624
|
+
const m = buttonRe.exec(line);
|
|
45625
|
+
if (!m) continue;
|
|
45626
|
+
const captured = m[labelGroup] ?? (labelGroup === 1 && m.length > 2 ? m[m.length - 1] : void 0);
|
|
45627
|
+
if (captured && captured.trim()) out.push(captured.trim());
|
|
45628
|
+
}
|
|
45629
|
+
return out;
|
|
45630
|
+
}
|
|
45631
|
+
function buttonBlockApprovalCue(spec, text) {
|
|
45632
|
+
const labels = extractButtonLabels(spec, text);
|
|
45633
|
+
if (labels.length < 2) return false;
|
|
45634
|
+
if (pickApprovalButton(labels).index < 0) return false;
|
|
45635
|
+
return hasNegativeApprovalOption(labels);
|
|
45636
|
+
}
|
|
45396
45637
|
function modalMatches(spec, input) {
|
|
45397
45638
|
const text = input.screenText ?? "";
|
|
45398
45639
|
const question = compile2(spec.questionPattern, spec.questionFlags ?? "i");
|
|
@@ -45401,6 +45642,7 @@ ${cleanBody}`;
|
|
|
45401
45642
|
const re = compile2(variant.regex, variant.flags ?? "i");
|
|
45402
45643
|
if (re.test(text)) return true;
|
|
45403
45644
|
}
|
|
45645
|
+
if (buttonBlockApprovalCue(spec, text)) return true;
|
|
45404
45646
|
return false;
|
|
45405
45647
|
}
|
|
45406
45648
|
function evaluateGroup(group, spec, input, compiled) {
|
|
@@ -45455,6 +45697,7 @@ ${cleanBody}`;
|
|
|
45455
45697
|
"src/providers/sdk/v1/builders/cli/detect-status.ts"() {
|
|
45456
45698
|
"use strict";
|
|
45457
45699
|
init_visible_region();
|
|
45700
|
+
init_approval_utils();
|
|
45458
45701
|
DEFAULT_ORDER = ["spinner", "modal", "settled-prompt"];
|
|
45459
45702
|
}
|
|
45460
45703
|
});
|
|
@@ -55843,73 +56086,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
55843
56086
|
if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
|
|
55844
56087
|
return normalized;
|
|
55845
56088
|
}
|
|
55846
|
-
|
|
55847
|
-
"yes",
|
|
55848
|
-
"allow once",
|
|
55849
|
-
"approve",
|
|
55850
|
-
"accept",
|
|
55851
|
-
"continue",
|
|
55852
|
-
"run",
|
|
55853
|
-
"proceed",
|
|
55854
|
-
"confirm",
|
|
55855
|
-
"save",
|
|
55856
|
-
"ok",
|
|
55857
|
-
"trust",
|
|
55858
|
-
"allow",
|
|
55859
|
-
"always allow"
|
|
55860
|
-
];
|
|
55861
|
-
function normalizeApprovalLabel(value) {
|
|
55862
|
-
return String(value || "").toLowerCase().replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, "").replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
55863
|
-
}
|
|
55864
|
-
function isNegativeApprovalLabel(value) {
|
|
55865
|
-
const label = normalizeApprovalLabel(value);
|
|
55866
|
-
return /^(no|deny|reject|cancel|skip|exit|stop)\b/.test(label) || /\bwithout\b/.test(label) || /\bdo not\b/.test(label);
|
|
55867
|
-
}
|
|
55868
|
-
function getApprovalPositiveHints(provider) {
|
|
55869
|
-
const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
|
|
55870
|
-
return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
|
|
55871
|
-
}
|
|
55872
|
-
function pickApprovalButton(buttons, provider) {
|
|
55873
|
-
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
55874
|
-
if (labels.length === 0) {
|
|
55875
|
-
return { index: -1, label: "" };
|
|
55876
|
-
}
|
|
55877
|
-
const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
|
|
55878
|
-
const hints = getApprovalPositiveHints(provider);
|
|
55879
|
-
for (const hint of hints) {
|
|
55880
|
-
const exactIndex = normalizedButtons.findIndex((label, index) => label === hint && !isNegativeApprovalLabel(labels[index]));
|
|
55881
|
-
if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
|
|
55882
|
-
const prefixIndex = normalizedButtons.findIndex((label, index) => label.startsWith(hint) && !isNegativeApprovalLabel(labels[index]));
|
|
55883
|
-
if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
|
|
55884
|
-
const includeIndex = normalizedButtons.findIndex((label, index) => label.includes(hint) && !isNegativeApprovalLabel(labels[index]));
|
|
55885
|
-
if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
|
|
55886
|
-
}
|
|
55887
|
-
return { index: -1, label: "" };
|
|
55888
|
-
}
|
|
55889
|
-
function pickAutoApprovalButton(buttons) {
|
|
55890
|
-
const labels = (buttons || []).map((button) => String(button || "").trim());
|
|
55891
|
-
const index = labels.findIndex(Boolean);
|
|
55892
|
-
return index >= 0 ? { index, label: labels[index] } : { index: -1, label: "" };
|
|
55893
|
-
}
|
|
55894
|
-
function formatAutoApprovalMessage(modalMessage, buttonLabel) {
|
|
55895
|
-
const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
|
|
55896
|
-
const cleanMessage = String(modalMessage || "").trim();
|
|
55897
|
-
if (cleanMessage) lines.push(cleanMessage);
|
|
55898
|
-
return lines.join("\n");
|
|
55899
|
-
}
|
|
55900
|
-
function looksLikeActiveApprovalPromptText(content) {
|
|
55901
|
-
const text = content.trim();
|
|
55902
|
-
if (!text || text.length > 2e3) return false;
|
|
55903
|
-
const hasApprovalQuestion = /do you want to (?:proceed|allow|run|make this edit|create)/i.test(text) || /this command requires approval/i.test(text) || /quick safety check/i.test(text) || /is this a project you trust/i.test(text);
|
|
55904
|
-
const hasNumberedChoices = /^\s*[❯›>]?\s*1[.)]\s+(?:yes|allow|proceed|run)/im.test(text) || /^\s*1[.)]\s+yes\b/im.test(text);
|
|
55905
|
-
if (hasApprovalQuestion && hasNumberedChoices) return true;
|
|
55906
|
-
const lastLines = text.split(/\r?\n/).slice(-12).join("\n");
|
|
55907
|
-
const hasDontAskAgain = /yes.*don'?t ask again/i.test(lastLines) || /yes.*always allow/i.test(lastLines);
|
|
55908
|
-
const hasNoOption = /^\s*[❯›>]?\s*\d+[.)]\s+no\b/im.test(lastLines);
|
|
55909
|
-
if (hasDontAskAgain && hasNoOption) return true;
|
|
55910
|
-
if (/what do you want to do\?/i.test(text) && /^\s*\d+[.)]\s+\S/m.test(text)) return true;
|
|
55911
|
-
return false;
|
|
55912
|
-
}
|
|
56089
|
+
init_approval_utils();
|
|
55913
56090
|
init_provider_patch_state();
|
|
55914
56091
|
init_chat_message_normalization();
|
|
55915
56092
|
init_open_panel_support();
|
|
@@ -56973,6 +57150,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
56973
57150
|
var import_node_crypto3 = require("crypto");
|
|
56974
57151
|
init_contracts();
|
|
56975
57152
|
init_provider_input_support();
|
|
57153
|
+
init_approval_utils();
|
|
56976
57154
|
init_coordinator_registry();
|
|
56977
57155
|
init_logger();
|
|
56978
57156
|
init_debug_config();
|
|
@@ -64913,6 +65091,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64913
65091
|
}
|
|
64914
65092
|
init_logger();
|
|
64915
65093
|
init_control_effects();
|
|
65094
|
+
init_approval_utils();
|
|
64916
65095
|
init_provider_patch_state();
|
|
64917
65096
|
function normalizeProviderSessionId(provider, providerSessionId) {
|
|
64918
65097
|
const normalizedId = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
|
|
@@ -65166,6 +65345,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65166
65345
|
* keystroke until the modal *content* has settled.
|
|
65167
65346
|
*/
|
|
65168
65347
|
static AUTO_APPROVE_SETTLE_MS = 600;
|
|
65348
|
+
/**
|
|
65349
|
+
* Busy-side hysteresis for the settle gate. A momentary `generating` flip
|
|
65350
|
+
* while the SAME approval modal's button block is still on screen (its
|
|
65351
|
+
* question line scrolled out of the captured frame, only the buttons + a
|
|
65352
|
+
* residual `esc to interrupt` spinner remain) briefly reports
|
|
65353
|
+
* status!=waiting_approval. Without hysteresis that flip wipes the settle
|
|
65354
|
+
* clock, and the modal→generating→modal flap restarts the 600ms window
|
|
65355
|
+
* every time so auto-approve never fires. We keep the in-progress settle
|
|
65356
|
+
* gate warm across an inactive blip up to this bound; only once the modal
|
|
65357
|
+
* has genuinely stayed gone this long (a real resolution → idle) is the
|
|
65358
|
+
* gate cleared. Bounded so a genuinely new, later approval still re-settles
|
|
65359
|
+
* from scratch rather than firing on a stale timestamp.
|
|
65360
|
+
*/
|
|
65361
|
+
static AUTO_APPROVE_GATE_HYSTERESIS_MS = 1500;
|
|
65169
65362
|
adapter;
|
|
65170
65363
|
context = null;
|
|
65171
65364
|
events = [];
|
|
@@ -65187,6 +65380,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65187
65380
|
pendingAutoApprovalSignature = "";
|
|
65188
65381
|
pendingAutoApprovalSince = 0;
|
|
65189
65382
|
autoApproveSettleTimer = null;
|
|
65383
|
+
// Wall-clock when auto-approve first observed status!=waiting_approval while
|
|
65384
|
+
// a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS so a
|
|
65385
|
+
// brief generating flip does not immediately wipe the settle clock.
|
|
65386
|
+
autoApproveInactiveSince = 0;
|
|
65190
65387
|
controlValues = {};
|
|
65191
65388
|
summaryMetadata = void 0;
|
|
65192
65389
|
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
@@ -66007,14 +66204,28 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66007
66204
|
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
|
|
66008
66205
|
if (!autoApproveActive) {
|
|
66009
66206
|
this.lastAutoApprovalSignature = "";
|
|
66207
|
+
if (this.pendingAutoApprovalSince) {
|
|
66208
|
+
if (!this.autoApproveInactiveSince) this.autoApproveInactiveSince = now;
|
|
66209
|
+
const goneForMs = now - this.autoApproveInactiveSince;
|
|
66210
|
+
if (goneForMs < _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS) {
|
|
66211
|
+
if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
|
|
66212
|
+
this.autoApproveSettleTimer = setTimeout(() => {
|
|
66213
|
+
this.autoApproveSettleTimer = null;
|
|
66214
|
+
this.recheckAutoApproveSettled();
|
|
66215
|
+
}, _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS - goneForMs + 20);
|
|
66216
|
+
return autoApproveActive;
|
|
66217
|
+
}
|
|
66218
|
+
}
|
|
66010
66219
|
this.pendingAutoApprovalSignature = "";
|
|
66011
66220
|
this.pendingAutoApprovalSince = 0;
|
|
66221
|
+
this.autoApproveInactiveSince = 0;
|
|
66012
66222
|
if (this.autoApproveSettleTimer) {
|
|
66013
66223
|
clearTimeout(this.autoApproveSettleTimer);
|
|
66014
66224
|
this.autoApproveSettleTimer = null;
|
|
66015
66225
|
}
|
|
66016
66226
|
return autoApproveActive;
|
|
66017
66227
|
}
|
|
66228
|
+
this.autoApproveInactiveSince = 0;
|
|
66018
66229
|
const modal = adapterStatus.activeModal;
|
|
66019
66230
|
const buttons = Array.isArray(modal?.buttons) ? modal.buttons.map((b) => String(b || "").trim()).filter(Boolean) : [];
|
|
66020
66231
|
if (!modal || buttons.length === 0) {
|
|
@@ -66024,18 +66235,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66024
66235
|
if (buttonIndex < 0) {
|
|
66025
66236
|
return autoApproveActive;
|
|
66026
66237
|
}
|
|
66027
|
-
const
|
|
66028
|
-
const signature = [
|
|
66029
|
-
approvalEntrySeq,
|
|
66238
|
+
const modalSignature = [
|
|
66030
66239
|
typeof modal?.message === "string" ? modal.message.trim() : "",
|
|
66031
66240
|
buttons.join("|"),
|
|
66032
66241
|
buttonIndex
|
|
66033
66242
|
].join("::");
|
|
66034
|
-
|
|
66243
|
+
const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
|
|
66244
|
+
const busySignature = `${approvalEntrySeq}::${modalSignature}`;
|
|
66245
|
+
if (this.autoApproveBusy && busySignature === this.lastAutoApprovalSignature) {
|
|
66035
66246
|
return autoApproveActive;
|
|
66036
66247
|
}
|
|
66037
|
-
if (
|
|
66038
|
-
this.pendingAutoApprovalSignature =
|
|
66248
|
+
if (modalSignature !== this.pendingAutoApprovalSignature) {
|
|
66249
|
+
this.pendingAutoApprovalSignature = modalSignature;
|
|
66039
66250
|
this.pendingAutoApprovalSince = now;
|
|
66040
66251
|
}
|
|
66041
66252
|
const settledForMs = now - this.pendingAutoApprovalSince;
|
|
@@ -66052,9 +66263,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66052
66263
|
this.autoApproveSettleTimer = null;
|
|
66053
66264
|
}
|
|
66054
66265
|
this.autoApproveBusy = true;
|
|
66055
|
-
this.lastAutoApprovalSignature =
|
|
66266
|
+
this.lastAutoApprovalSignature = busySignature;
|
|
66056
66267
|
this.pendingAutoApprovalSignature = "";
|
|
66057
66268
|
this.pendingAutoApprovalSince = 0;
|
|
66269
|
+
this.autoApproveInactiveSince = 0;
|
|
66058
66270
|
if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
|
|
66059
66271
|
this.autoApproveBusyTimer = setTimeout(() => {
|
|
66060
66272
|
this.autoApproveBusy = false;
|
|
@@ -72903,7 +73115,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
72903
73115
|
var fs23 = __toESM2(require("fs"));
|
|
72904
73116
|
var path35 = __toESM2(require("path"));
|
|
72905
73117
|
var os26 = __toESM2(require("os"));
|
|
72906
|
-
var
|
|
73118
|
+
var ADHDEV_HOME2 = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path35.join(os26.homedir(), ".adhdev");
|
|
73119
|
+
var LOG_DIR2 = path35.join(ADHDEV_HOME2, "logs");
|
|
72907
73120
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
72908
73121
|
var MAX_DAYS = 7;
|
|
72909
73122
|
try {
|
|
@@ -73738,13 +73951,14 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
73738
73951
|
}
|
|
73739
73952
|
}
|
|
73740
73953
|
}
|
|
73741
|
-
function stopSessionHostProcesses(appName) {
|
|
73954
|
+
async function stopSessionHostProcesses(appName) {
|
|
73742
73955
|
const pidFile = path36.join(os27.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
73956
|
+
let killedPid = null;
|
|
73743
73957
|
try {
|
|
73744
73958
|
if (fs25.existsSync(pidFile)) {
|
|
73745
73959
|
const pid = Number.parseInt(fs25.readFileSync(pidFile, "utf8").trim(), 10);
|
|
73746
73960
|
if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
|
|
73747
|
-
killPid2(pid);
|
|
73961
|
+
if (killPid2(pid)) killedPid = pid;
|
|
73748
73962
|
}
|
|
73749
73963
|
}
|
|
73750
73964
|
} catch {
|
|
@@ -73754,6 +73968,15 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
73754
73968
|
} catch {
|
|
73755
73969
|
}
|
|
73756
73970
|
}
|
|
73971
|
+
if (killedPid !== null) {
|
|
73972
|
+
await waitForPidExit(killedPid, 15e3);
|
|
73973
|
+
}
|
|
73974
|
+
}
|
|
73975
|
+
function isRetriableInstallLockError(error48) {
|
|
73976
|
+
const code = error48?.code;
|
|
73977
|
+
if (code === "EBUSY" || code === "EPERM") return true;
|
|
73978
|
+
const text = `${error48?.message || ""} ${error48?.stderr || ""}`;
|
|
73979
|
+
return /\bEBUSY\b|\bEPERM\b|resource busy or locked/i.test(text);
|
|
73757
73980
|
}
|
|
73758
73981
|
function removeDaemonPidFile() {
|
|
73759
73982
|
const pidFile = path36.join(os27.homedir(), ".adhdev", "daemon.pid");
|
|
@@ -73833,22 +74056,37 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
73833
74056
|
appendUpgradeLog(`Waiting for parent pid ${payload.parentPid} to exit`);
|
|
73834
74057
|
await waitForPidExit(payload.parentPid, 15e3);
|
|
73835
74058
|
}
|
|
73836
|
-
stopSessionHostProcesses(sessionHostAppName);
|
|
74059
|
+
await stopSessionHostProcesses(sessionHostAppName);
|
|
73837
74060
|
removeDaemonPidFile();
|
|
73838
74061
|
cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
|
|
73839
74062
|
const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
|
|
73840
74063
|
appendUpgradeLog(`Installing ${spec}`);
|
|
73841
|
-
const
|
|
73842
|
-
|
|
73843
|
-
|
|
73844
|
-
{
|
|
73845
|
-
|
|
73846
|
-
|
|
73847
|
-
|
|
73848
|
-
|
|
73849
|
-
|
|
74064
|
+
const maxInstallAttempts = process.platform === "win32" ? 3 : 1;
|
|
74065
|
+
let installOutput = "";
|
|
74066
|
+
for (let attempt = 1; attempt <= maxInstallAttempts; attempt++) {
|
|
74067
|
+
try {
|
|
74068
|
+
installOutput = String((0, import_child_process8.execFileSync)(
|
|
74069
|
+
installCommand.command,
|
|
74070
|
+
installCommand.args,
|
|
74071
|
+
{
|
|
74072
|
+
encoding: "utf8",
|
|
74073
|
+
stdio: "pipe",
|
|
74074
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
74075
|
+
env: buildInstallEnvWithNodeOnPath(),
|
|
74076
|
+
...installCommand.execOptions
|
|
74077
|
+
}
|
|
74078
|
+
));
|
|
74079
|
+
break;
|
|
74080
|
+
} catch (error48) {
|
|
74081
|
+
if (attempt < maxInstallAttempts && isRetriableInstallLockError(error48)) {
|
|
74082
|
+
appendUpgradeLog(`Install attempt ${attempt} hit a file lock (${error48?.code || "lock"}); cleaning staging and retrying after backoff`);
|
|
74083
|
+
cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
|
|
74084
|
+
await new Promise((resolve24) => setTimeout(resolve24, attempt * 1500));
|
|
74085
|
+
continue;
|
|
74086
|
+
}
|
|
74087
|
+
throw error48;
|
|
73850
74088
|
}
|
|
73851
|
-
|
|
74089
|
+
}
|
|
73852
74090
|
if (installOutput.trim()) {
|
|
73853
74091
|
appendUpgradeLog(installOutput.trim());
|
|
73854
74092
|
}
|
|
@@ -82592,6 +82830,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
82592
82830
|
}
|
|
82593
82831
|
};
|
|
82594
82832
|
init_logger();
|
|
82833
|
+
init_approval_utils();
|
|
82595
82834
|
init_chat_message_normalization();
|
|
82596
82835
|
var AgentStreamPoller = class {
|
|
82597
82836
|
deps;
|