@adhdev/daemon-core 0.9.82-rc.467 → 0.9.82-rc.468
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 +188 -147
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +195 -154
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-effect-format.d.ts +30 -0
- package/dist/providers/cli-provider-instance-types.d.ts +45 -0
- package/dist/providers/cli-provider-instance.d.ts +12 -6
- package/dist/providers/cli-provider-transcript-merge.d.ts +7 -0
- package/package.json +3 -3
- package/src/mesh/mesh-events-pending.ts +2 -0
- package/src/mesh/mesh-reconcile-loop.ts +32 -5
- package/src/mesh/mesh-runtime-store.ts +46 -1
- package/src/providers/cli-provider-effect-format.ts +53 -0
- package/src/providers/cli-provider-instance-types.ts +131 -0
- package/src/providers/cli-provider-instance.ts +87 -303
- package/src/providers/cli-provider-transcript-merge.ts +114 -0
package/dist/index.mjs
CHANGED
|
@@ -404,10 +404,10 @@ function readInjected(value) {
|
|
|
404
404
|
}
|
|
405
405
|
function getDaemonBuildInfo() {
|
|
406
406
|
if (cached) return cached;
|
|
407
|
-
const commit = readInjected(true ? "
|
|
408
|
-
const commitShort = readInjected(true ? "
|
|
409
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
410
|
-
const builtAt = readInjected(true ? "2026-07-05T10:
|
|
407
|
+
const commit = readInjected(true ? "f05125bad26f9ee974d8bd31a8b9ab66bca9d4cd" : void 0) ?? "unknown";
|
|
408
|
+
const commitShort = readInjected(true ? "f05125ba" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
409
|
+
const version = readInjected(true ? "0.9.82-rc.468" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
410
|
+
const builtAt = readInjected(true ? "2026-07-05T10:08:41.050Z" : void 0);
|
|
411
411
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
412
412
|
return cached;
|
|
413
413
|
}
|
|
@@ -6159,7 +6159,7 @@ var init_mesh_work_queue = __esm({
|
|
|
6159
6159
|
});
|
|
6160
6160
|
|
|
6161
6161
|
// src/mesh/mesh-runtime-store.ts
|
|
6162
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync3, statSync as statSync5 } from "fs";
|
|
6162
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync3, statSync as statSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
6163
6163
|
import { dirname as dirname2, join as join9 } from "path";
|
|
6164
6164
|
function loadDatabaseCtor() {
|
|
6165
6165
|
if (DatabaseCtor) return DatabaseCtor;
|
|
@@ -6172,9 +6172,28 @@ function safeMeshId(meshId) {
|
|
|
6172
6172
|
function legacyQueuePath(meshId) {
|
|
6173
6173
|
return join9(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
|
|
6174
6174
|
}
|
|
6175
|
+
function cleanupStrayRootRuntimeDb(canonicalPath) {
|
|
6176
|
+
try {
|
|
6177
|
+
const strayPath = join9(getConfigDir(), "mesh-runtime.db");
|
|
6178
|
+
if (strayPath === canonicalPath) return;
|
|
6179
|
+
if (!existsSync8(strayPath)) return;
|
|
6180
|
+
if (statSync5(strayPath).size !== 0) return;
|
|
6181
|
+
unlinkSync2(strayPath);
|
|
6182
|
+
if (!loggedStrayCleanup) {
|
|
6183
|
+
loggedStrayCleanup = true;
|
|
6184
|
+
LOG.info("MeshRuntimeStore", `Removed stray 0-byte root mesh-runtime.db at ${strayPath}`);
|
|
6185
|
+
}
|
|
6186
|
+
} catch (err) {
|
|
6187
|
+
if (!loggedStrayCleanup) {
|
|
6188
|
+
loggedStrayCleanup = true;
|
|
6189
|
+
LOG.warn("MeshRuntimeStore", `Stray root mesh-runtime.db cleanup failed (ignored): ${err?.message || err}`);
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6175
6193
|
function meshRuntimeStorePath() {
|
|
6176
6194
|
const dir = getLedgerDir();
|
|
6177
6195
|
const nextPath = join9(dir, "mesh-runtime.db");
|
|
6196
|
+
cleanupStrayRootRuntimeDb(nextPath);
|
|
6178
6197
|
if (existsSync8(nextPath)) return nextPath;
|
|
6179
6198
|
const legacyPath = join9(dir, "beads.db");
|
|
6180
6199
|
if (!existsSync8(legacyPath)) return nextPath;
|
|
@@ -6198,16 +6217,18 @@ function meshRuntimeStorePath() {
|
|
|
6198
6217
|
}
|
|
6199
6218
|
return nextPath;
|
|
6200
6219
|
}
|
|
6201
|
-
var DatabaseCtor, loggedMigrationFailure, MeshRuntimeStore;
|
|
6220
|
+
var DatabaseCtor, loggedMigrationFailure, loggedStrayCleanup, MeshRuntimeStore;
|
|
6202
6221
|
var init_mesh_runtime_store = __esm({
|
|
6203
6222
|
"src/mesh/mesh-runtime-store.ts"() {
|
|
6204
6223
|
"use strict";
|
|
6205
6224
|
init_logger();
|
|
6206
6225
|
init_load_better_sqlite3();
|
|
6226
|
+
init_config();
|
|
6207
6227
|
init_mesh_ledger();
|
|
6208
6228
|
init_mesh_work_queue();
|
|
6209
6229
|
init_dist();
|
|
6210
6230
|
loggedMigrationFailure = false;
|
|
6231
|
+
loggedStrayCleanup = false;
|
|
6211
6232
|
MeshRuntimeStore = class _MeshRuntimeStore {
|
|
6212
6233
|
static instance;
|
|
6213
6234
|
db;
|
|
@@ -6550,6 +6571,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
6550
6571
|
ON mesh_pending_events(mesh_id, event_id)
|
|
6551
6572
|
WHERE event_id IS NOT NULL
|
|
6552
6573
|
`);
|
|
6574
|
+
this.db.exec(`DROP TABLE IF EXISTS mesh_direct_delivered_events`);
|
|
6553
6575
|
} catch (err) {
|
|
6554
6576
|
if (!loggedMigrationFailure) {
|
|
6555
6577
|
loggedMigrationFailure = true;
|
|
@@ -11510,7 +11532,7 @@ var init_mesh_events_utils = __esm({
|
|
|
11510
11532
|
});
|
|
11511
11533
|
|
|
11512
11534
|
// src/mesh/mesh-events-pending.ts
|
|
11513
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync15, readFileSync as readFileSync12, renameSync as renameSync4, statSync as statSync6, unlinkSync as
|
|
11535
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync15, readFileSync as readFileSync12, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
11514
11536
|
import { join as join16 } from "path";
|
|
11515
11537
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
11516
11538
|
function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
|
|
@@ -11986,13 +12008,13 @@ function atomicDrainFile(path45) {
|
|
|
11986
12008
|
try {
|
|
11987
12009
|
const content = readFileSync12(tmpPath, "utf-8");
|
|
11988
12010
|
try {
|
|
11989
|
-
|
|
12011
|
+
unlinkSync3(tmpPath);
|
|
11990
12012
|
} catch {
|
|
11991
12013
|
}
|
|
11992
12014
|
return content;
|
|
11993
12015
|
} catch {
|
|
11994
12016
|
try {
|
|
11995
|
-
|
|
12017
|
+
unlinkSync3(tmpPath);
|
|
11996
12018
|
} catch {
|
|
11997
12019
|
}
|
|
11998
12020
|
return null;
|
|
@@ -12010,7 +12032,7 @@ function selectiveDrainFile(path45, predicate) {
|
|
|
12010
12032
|
content = readFileSync12(tmpPath, "utf-8");
|
|
12011
12033
|
} catch {
|
|
12012
12034
|
try {
|
|
12013
|
-
|
|
12035
|
+
unlinkSync3(tmpPath);
|
|
12014
12036
|
} catch {
|
|
12015
12037
|
}
|
|
12016
12038
|
return [];
|
|
@@ -12035,7 +12057,7 @@ function selectiveDrainFile(path45, predicate) {
|
|
|
12035
12057
|
if (keptLines.length > 0) {
|
|
12036
12058
|
writeFileSync6(path45, keptLines.join("\n") + "\n", "utf-8");
|
|
12037
12059
|
}
|
|
12038
|
-
|
|
12060
|
+
unlinkSync3(tmpPath);
|
|
12039
12061
|
} catch {
|
|
12040
12062
|
try {
|
|
12041
12063
|
if (existsSync15(tmpPath) && !existsSync15(path45)) renameSync4(tmpPath, path45);
|
|
@@ -12185,7 +12207,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
12185
12207
|
const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
12186
12208
|
for (const path45 of paths) {
|
|
12187
12209
|
if (existsSync15(path45)) try {
|
|
12188
|
-
|
|
12210
|
+
unlinkSync3(path45);
|
|
12189
12211
|
} catch {
|
|
12190
12212
|
}
|
|
12191
12213
|
}
|
|
@@ -19309,11 +19331,13 @@ async function pullRemoteNodeQueues(components, mesh, localDaemonId, candidateDa
|
|
|
19309
19331
|
if (!dispatchMeshCommand) return;
|
|
19310
19332
|
const meshId = mesh.id;
|
|
19311
19333
|
const pulls = candidateDaemonIds.length > 0 ? candidateDaemonIds.map((id) => ({ meshId, coordinatorDaemonId: id })) : [{ meshId }];
|
|
19312
|
-
|
|
19334
|
+
await Promise.allSettled(mesh.nodes.map(async (node) => {
|
|
19313
19335
|
const nodeDaemonId = readNonEmptyString2(node.daemonId);
|
|
19314
|
-
if (!nodeDaemonId)
|
|
19315
|
-
if (daemonIdsEquivalent(nodeDaemonId, localDaemonId))
|
|
19316
|
-
if (daemonIdListIncludes(candidateDaemonIds, nodeDaemonId))
|
|
19336
|
+
if (!nodeDaemonId) return;
|
|
19337
|
+
if (daemonIdsEquivalent(nodeDaemonId, localDaemonId)) return;
|
|
19338
|
+
if (daemonIdListIncludes(candidateDaemonIds, nodeDaemonId)) return;
|
|
19339
|
+
const peerSnapshot = components.getMeshPeerConnectionStatus?.(nodeDaemonId);
|
|
19340
|
+
if (peerSnapshot && String(peerSnapshot.state) !== "connected") return;
|
|
19317
19341
|
for (const pendingEventArgs of pulls) {
|
|
19318
19342
|
let events;
|
|
19319
19343
|
try {
|
|
@@ -19331,7 +19355,7 @@ async function pullRemoteNodeQueues(components, mesh, localDaemonId, candidateDa
|
|
|
19331
19355
|
}
|
|
19332
19356
|
}
|
|
19333
19357
|
}
|
|
19334
|
-
}
|
|
19358
|
+
}));
|
|
19335
19359
|
}
|
|
19336
19360
|
function unwrapReadChatPayload(raw) {
|
|
19337
19361
|
let cursor = raw;
|
|
@@ -19567,6 +19591,10 @@ async function collectLiveNodesWithSessions(components, mesh, selfIds, localDaem
|
|
|
19567
19591
|
return Promise.all(mesh.nodes.map(async (node) => {
|
|
19568
19592
|
const nodeDaemonId = readNonEmptyString2(node.daemonId);
|
|
19569
19593
|
const isLocalNode = !nodeDaemonId || daemonIdListIncludes(selfIds, nodeDaemonId) || daemonIdsEquivalent(nodeDaemonId, localDaemonId);
|
|
19594
|
+
if (!isLocalNode) {
|
|
19595
|
+
const peerSnapshot = components.getMeshPeerConnectionStatus?.(nodeDaemonId);
|
|
19596
|
+
if (peerSnapshot && String(peerSnapshot.state) !== "connected") return node;
|
|
19597
|
+
}
|
|
19570
19598
|
let statusResult;
|
|
19571
19599
|
try {
|
|
19572
19600
|
if (isLocalNode) {
|
|
@@ -42306,7 +42334,7 @@ async function waitForCliAdapterReady(adapter, options) {
|
|
|
42306
42334
|
throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
|
|
42307
42335
|
}
|
|
42308
42336
|
|
|
42309
|
-
// src/providers/cli-provider-instance.ts
|
|
42337
|
+
// src/providers/cli-provider-instance-types.ts
|
|
42310
42338
|
var STATUS_HYDRATION_TAIL_LIMIT = 200;
|
|
42311
42339
|
var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
|
|
42312
42340
|
var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
|
|
@@ -42318,6 +42346,123 @@ var TERMINAL_MESH_EVENTS = /* @__PURE__ */ new Set([
|
|
|
42318
42346
|
"agent:stopped",
|
|
42319
42347
|
"agent:ready"
|
|
42320
42348
|
]);
|
|
42349
|
+
|
|
42350
|
+
// src/providers/cli-provider-transcript-merge.ts
|
|
42351
|
+
init_contracts2();
|
|
42352
|
+
init_chat_message_normalization();
|
|
42353
|
+
function mergeConversationMessages(runtimeMessages, parsedMessages) {
|
|
42354
|
+
if (runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
|
|
42355
|
+
const parsedEntries = parsedMessages.map((message, index) => ({
|
|
42356
|
+
message,
|
|
42357
|
+
index,
|
|
42358
|
+
source: "parsed"
|
|
42359
|
+
}));
|
|
42360
|
+
const getRole = (message) => typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
42361
|
+
const runtimeEntries = runtimeMessages.map((entry, index) => ({
|
|
42362
|
+
message: entry.message,
|
|
42363
|
+
index: parsedMessages.length + index,
|
|
42364
|
+
source: "runtime",
|
|
42365
|
+
runtimeKey: entry.key
|
|
42366
|
+
})).filter((entry) => {
|
|
42367
|
+
const meta = entry.message.meta && typeof entry.message.meta === "object" && !Array.isArray(entry.message.meta) ? entry.message.meta : {};
|
|
42368
|
+
if (meta.runtimeInputAck !== true) return true;
|
|
42369
|
+
const runtimeText = flattenContent(entry.message.content).replace(/\s+/g, " ").trim();
|
|
42370
|
+
if (!runtimeText) return false;
|
|
42371
|
+
return !parsedEntries.some((parsedEntry) => {
|
|
42372
|
+
const parsedRole = getRole(parsedEntry.message);
|
|
42373
|
+
if (parsedRole !== "user" && parsedRole !== "human") return false;
|
|
42374
|
+
const parsedText = flattenContent(parsedEntry.message.content).replace(/\s+/g, " ").trim();
|
|
42375
|
+
return parsedText === runtimeText;
|
|
42376
|
+
});
|
|
42377
|
+
});
|
|
42378
|
+
const getTime = (message) => {
|
|
42379
|
+
const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
|
|
42380
|
+
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
42381
|
+
};
|
|
42382
|
+
const isRuntimeOverlay = (entry) => {
|
|
42383
|
+
if (entry.source !== "runtime") return false;
|
|
42384
|
+
const key2 = typeof entry.runtimeKey === "string" ? entry.runtimeKey.trim().toLowerCase() : "";
|
|
42385
|
+
if (key2.startsWith("auto_approval:")) return true;
|
|
42386
|
+
return !isUserFacingChatMessage(entry.message);
|
|
42387
|
+
};
|
|
42388
|
+
const shouldKeepParsedBeforeUntimedRuntime = (message) => {
|
|
42389
|
+
const role = getRole(message);
|
|
42390
|
+
return role === "user" || role === "human";
|
|
42391
|
+
};
|
|
42392
|
+
const shouldKeepParsedAfterUntimedRuntime = (message) => {
|
|
42393
|
+
const role = getRole(message);
|
|
42394
|
+
if (role !== "assistant") return false;
|
|
42395
|
+
const kind = resolveChatMessageKind(message);
|
|
42396
|
+
return kind === "standard" || kind === "terminal";
|
|
42397
|
+
};
|
|
42398
|
+
return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
|
|
42399
|
+
const aTime = getTime(a.message);
|
|
42400
|
+
const bTime = getTime(b.message);
|
|
42401
|
+
if (aTime && bTime && aTime !== bTime) return aTime - bTime;
|
|
42402
|
+
if (a.source !== b.source && aTime !== bTime) {
|
|
42403
|
+
const parsedEntry = a.source === "parsed" ? a : b.source === "parsed" ? b : null;
|
|
42404
|
+
const runtimeEntry = a.source === "runtime" ? a : b.source === "runtime" ? b : null;
|
|
42405
|
+
if (parsedEntry && runtimeEntry && isRuntimeOverlay(runtimeEntry) && getTime(parsedEntry.message) === 0 && getTime(runtimeEntry.message) > 0) {
|
|
42406
|
+
if (shouldKeepParsedBeforeUntimedRuntime(parsedEntry.message)) {
|
|
42407
|
+
return a.source === "parsed" ? -1 : 1;
|
|
42408
|
+
}
|
|
42409
|
+
if (shouldKeepParsedAfterUntimedRuntime(parsedEntry.message)) {
|
|
42410
|
+
return a.source === "parsed" ? 1 : -1;
|
|
42411
|
+
}
|
|
42412
|
+
}
|
|
42413
|
+
}
|
|
42414
|
+
return a.index - b.index;
|
|
42415
|
+
}).map((entry) => entry.message));
|
|
42416
|
+
}
|
|
42417
|
+
function buildExternalTranscriptProbe(messages, sourcePath, sourceMtimeMs) {
|
|
42418
|
+
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
42419
|
+
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
42420
|
+
const readAt = Date.now();
|
|
42421
|
+
const mtimeMs = Number(sourceMtimeMs) || 0;
|
|
42422
|
+
return {
|
|
42423
|
+
readAt,
|
|
42424
|
+
msgCount: messages.length,
|
|
42425
|
+
lastRole: typeof lastVisible?.role === "string" ? lastVisible.role.trim().toLowerCase() : null,
|
|
42426
|
+
lastKind: typeof lastVisible?.kind === "string" ? lastVisible.kind : null,
|
|
42427
|
+
contentLen: lastVisible ? flattenContent(lastVisible.content).trim().length : 0,
|
|
42428
|
+
sourcePath: typeof sourcePath === "string" && sourcePath ? sourcePath : null,
|
|
42429
|
+
sourceMtimeMs: mtimeMs || null,
|
|
42430
|
+
mtimeAgeMs: mtimeMs ? Math.max(0, readAt - mtimeMs) : null
|
|
42431
|
+
};
|
|
42432
|
+
}
|
|
42433
|
+
|
|
42434
|
+
// src/providers/cli-provider-effect-format.ts
|
|
42435
|
+
function getEffectDedupKey(effect) {
|
|
42436
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
42437
|
+
if (effect.type === "message") {
|
|
42438
|
+
const content = typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
42439
|
+
return `provider_effect:message:${content}`;
|
|
42440
|
+
}
|
|
42441
|
+
if (effect.type === "notification") {
|
|
42442
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
42443
|
+
}
|
|
42444
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
42445
|
+
}
|
|
42446
|
+
function formatApprovalRequestMessage(modalMessage, buttons) {
|
|
42447
|
+
const lines = ["Approval requested"];
|
|
42448
|
+
const cleanMessage = String(modalMessage || "").trim();
|
|
42449
|
+
if (cleanMessage) lines.push(cleanMessage);
|
|
42450
|
+
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
42451
|
+
if (labels.length > 0) {
|
|
42452
|
+
lines.push(labels.map((label) => `[${label}]`).join(" "));
|
|
42453
|
+
}
|
|
42454
|
+
return lines.join("\n");
|
|
42455
|
+
}
|
|
42456
|
+
function formatMarkerTimestamp(timestamp) {
|
|
42457
|
+
const date = new Date(timestamp);
|
|
42458
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
42459
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
42460
|
+
}
|
|
42461
|
+
|
|
42462
|
+
// src/providers/cli-provider-instance.ts
|
|
42463
|
+
function approvalModalSignature(message, affirmativeAnchor) {
|
|
42464
|
+
return [typeof message === "string" ? message.trim() : "", affirmativeAnchor].join("::");
|
|
42465
|
+
}
|
|
42321
42466
|
var CliProviderInstance = class _CliProviderInstance {
|
|
42322
42467
|
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
|
|
42323
42468
|
this.provider = provider;
|
|
@@ -42565,7 +42710,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42565
42710
|
const resumedAt = Date.now();
|
|
42566
42711
|
this.historyWriter.appendSystemMarker(
|
|
42567
42712
|
this.type,
|
|
42568
|
-
`Resumed saved session at ${
|
|
42713
|
+
`Resumed saved session at ${formatMarkerTimestamp(resumedAt)}`,
|
|
42569
42714
|
{
|
|
42570
42715
|
instanceId: this.instanceId,
|
|
42571
42716
|
historySessionId: this.providerSessionId,
|
|
@@ -42677,7 +42822,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42677
42822
|
if (historyMessageCount !== null) {
|
|
42678
42823
|
parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
|
|
42679
42824
|
}
|
|
42680
|
-
const mergedMessages = this.
|
|
42825
|
+
const mergedMessages = mergeConversationMessages(this.runtimeMessages, parsedMessages);
|
|
42681
42826
|
const canonicalBackedHistory = this.shouldHydrateExistingProviderHistory() ? this.syncCanonicalSavedHistoryIfNeeded() : false;
|
|
42682
42827
|
const statusMessages = canonicalBackedHistory && this.lastPersistedHistoryMessages.length > 0 ? this.lastPersistedHistoryMessages.map((message) => ({
|
|
42683
42828
|
role: message.role,
|
|
@@ -43142,22 +43287,6 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
43142
43287
|
}
|
|
43143
43288
|
return true;
|
|
43144
43289
|
}
|
|
43145
|
-
buildExternalTranscriptProbe(messages, sourcePath, sourceMtimeMs) {
|
|
43146
|
-
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
43147
|
-
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
43148
|
-
const readAt = Date.now();
|
|
43149
|
-
const mtimeMs = Number(sourceMtimeMs) || 0;
|
|
43150
|
-
return {
|
|
43151
|
-
readAt,
|
|
43152
|
-
msgCount: messages.length,
|
|
43153
|
-
lastRole: typeof lastVisible?.role === "string" ? lastVisible.role.trim().toLowerCase() : null,
|
|
43154
|
-
lastKind: typeof lastVisible?.kind === "string" ? lastVisible.kind : null,
|
|
43155
|
-
contentLen: lastVisible ? flattenContent(lastVisible.content).trim().length : 0,
|
|
43156
|
-
sourcePath: typeof sourcePath === "string" && sourcePath ? sourcePath : null,
|
|
43157
|
-
sourceMtimeMs: mtimeMs || null,
|
|
43158
|
-
mtimeAgeMs: mtimeMs ? Math.max(0, readAt - mtimeMs) : null
|
|
43159
|
-
};
|
|
43160
|
-
}
|
|
43161
43290
|
recordPendingTranscriptProbe(pending) {
|
|
43162
43291
|
const probe = this.lastExternalCompletionProbe;
|
|
43163
43292
|
if (!probe) return null;
|
|
@@ -43209,7 +43338,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
43209
43338
|
this.lastExternalCompletionProbe = null;
|
|
43210
43339
|
return null;
|
|
43211
43340
|
}
|
|
43212
|
-
this.lastExternalCompletionProbe =
|
|
43341
|
+
this.lastExternalCompletionProbe = buildExternalTranscriptProbe(
|
|
43213
43342
|
restoredHistory.messages,
|
|
43214
43343
|
restoredHistory.sourcePath,
|
|
43215
43344
|
restoredHistory.sourceMtimeMs
|
|
@@ -43457,6 +43586,27 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
43457
43586
|
autoApproveContinuityWindowMs() {
|
|
43458
43587
|
return this.autoApproveMaskSince > 0 && this.isMeshWorkerSession() ? _CliProviderInstance.AUTO_APPROVE_FLAP_CONTINUITY_MS : _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS;
|
|
43459
43588
|
}
|
|
43589
|
+
/**
|
|
43590
|
+
* The settle-gate identity signature for a raw activeModal, or null when the
|
|
43591
|
+
* modal is NOT a concrete auto-approvable consent prompt (no captured buttons,
|
|
43592
|
+
* a picker/confirm kind, or no reliable affirmative+decline anchor). Mirrors the
|
|
43593
|
+
* gates the auto-approve fire path applies before computing modalSignature, so
|
|
43594
|
+
* the mask-stall nudge can ask the SAME question the settle gate is tracking —
|
|
43595
|
+
* "is THIS frame's modal the identity the settle clock is accruing against?" —
|
|
43596
|
+
* without duplicating the button-pick logic. The signature is message +
|
|
43597
|
+
* normalized affirmative label only (no volatile counters/button set), matching
|
|
43598
|
+
* the fire path exactly (AUTOAPPROVE-SETTLE-FLAP).
|
|
43599
|
+
*/
|
|
43600
|
+
approvableModalSignature(modal) {
|
|
43601
|
+
const buttons = Array.isArray(modal?.buttons) ? modal.buttons.map((b) => String(b || "").trim()).filter(Boolean) : [];
|
|
43602
|
+
if (!modal || buttons.length === 0) return null;
|
|
43603
|
+
const modalKind = typeof modal?.kind === "string" ? modal.kind : "approval";
|
|
43604
|
+
if (modalKind !== "approval") return null;
|
|
43605
|
+
const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(buttons, this.provider);
|
|
43606
|
+
const hasReliableConsentAnchor = hasNegativeApprovalOption(buttons) || hasReliableApprovalAffirmative(buttons);
|
|
43607
|
+
if (buttonIndex < 0 || !hasReliableConsentAnchor) return null;
|
|
43608
|
+
return approvalModalSignature(modal?.message, normalizeApprovalLabel(buttonLabel));
|
|
43609
|
+
}
|
|
43460
43610
|
// FALSE-IDLE (self-coordinator settle): an autonomously-progressing mesh session
|
|
43461
43611
|
// is either a delegated worker (isMeshWorkerSession) OR the coordinator's OWN
|
|
43462
43612
|
// claude-cli session (meshCoordinatorFor). Both run auto-approved tool turns whose
|
|
@@ -43760,10 +43910,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
43760
43910
|
return autoApproveActive;
|
|
43761
43911
|
}
|
|
43762
43912
|
const affirmativeAnchor = normalizeApprovalLabel(buttonLabel);
|
|
43763
|
-
const modalSignature =
|
|
43764
|
-
typeof modal?.message === "string" ? modal.message.trim() : "",
|
|
43765
|
-
affirmativeAnchor
|
|
43766
|
-
].join("::");
|
|
43913
|
+
const modalSignature = approvalModalSignature(modal?.message, affirmativeAnchor);
|
|
43767
43914
|
const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
|
|
43768
43915
|
const busySignature = `${approvalEntrySeq}::${modalSignature}`;
|
|
43769
43916
|
if (this.autoApproveBusy && busySignature === this.lastAutoApprovalSignature) {
|
|
@@ -43996,7 +44143,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
43996
44143
|
if (approvalFingerprint !== this.lastApprovalEventFingerprint) {
|
|
43997
44144
|
this.lastApprovalEventFingerprint = approvalFingerprint;
|
|
43998
44145
|
this.appendRuntimeSystemMessage(
|
|
43999
|
-
|
|
44146
|
+
formatApprovalRequestMessage(modal?.message, modal?.buttons),
|
|
44000
44147
|
`approval_request:${now}`,
|
|
44001
44148
|
now
|
|
44002
44149
|
);
|
|
@@ -44297,7 +44444,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
44297
44444
|
const effectWhen = effect.when || "immediate";
|
|
44298
44445
|
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
44299
44446
|
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
44300
|
-
const effectKey =
|
|
44447
|
+
const effectKey = getEffectDedupKey(effect);
|
|
44301
44448
|
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
44302
44449
|
this.appliedEffectKeys.add(effectKey);
|
|
44303
44450
|
if (effect.persist !== false) {
|
|
@@ -44340,34 +44487,6 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
44340
44487
|
this.appliedEffectKeys = new Set(Array.from(this.appliedEffectKeys).slice(-100));
|
|
44341
44488
|
}
|
|
44342
44489
|
}
|
|
44343
|
-
getEffectDedupKey(effect) {
|
|
44344
|
-
if (effect.id) return `provider_effect:${effect.id}`;
|
|
44345
|
-
if (effect.type === "message") {
|
|
44346
|
-
const content = typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
44347
|
-
return `provider_effect:message:${content}`;
|
|
44348
|
-
}
|
|
44349
|
-
if (effect.type === "notification") {
|
|
44350
|
-
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
44351
|
-
}
|
|
44352
|
-
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
44353
|
-
}
|
|
44354
|
-
getPersistedEffectContent(effect) {
|
|
44355
|
-
if (effect.type === "message") {
|
|
44356
|
-
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
44357
|
-
}
|
|
44358
|
-
if (effect.type === "toast") {
|
|
44359
|
-
return effect.toast?.message || null;
|
|
44360
|
-
}
|
|
44361
|
-
if (effect.type === "notification") {
|
|
44362
|
-
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
44363
|
-
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
44364
|
-
return `${effect.notification.title}
|
|
44365
|
-
${effect.notification.body || ""}`.trim();
|
|
44366
|
-
}
|
|
44367
|
-
return effect.notification?.body || null;
|
|
44368
|
-
}
|
|
44369
|
-
return null;
|
|
44370
|
-
}
|
|
44371
44490
|
// ─── Adapter access (backward compat) ──────────────────
|
|
44372
44491
|
getAdapter() {
|
|
44373
44492
|
return this.adapter;
|
|
@@ -44439,15 +44558,16 @@ ${effect.notification.body || ""}`.trim();
|
|
|
44439
44558
|
if (!this.isMeshWorkerSession()) return;
|
|
44440
44559
|
if (adapterStatus?.status !== "waiting_approval") return;
|
|
44441
44560
|
if (!this.autoApproveMaskStalled(now)) return;
|
|
44442
|
-
const
|
|
44443
|
-
|
|
44561
|
+
const currentSignature = this.approvableModalSignature(adapterStatus.activeModal);
|
|
44562
|
+
const settleProgressing = !!currentSignature && this.pendingAutoApprovalSince > 0 && currentSignature === this.pendingAutoApprovalSignature;
|
|
44563
|
+
if (settleProgressing) return;
|
|
44444
44564
|
if (this.stalledApprovalNudgeEpisode === this.autoApproveMaskSince) return;
|
|
44445
44565
|
this.stalledApprovalNudgeEpisode = this.autoApproveMaskSince;
|
|
44446
44566
|
const modal = adapterStatus.activeModal;
|
|
44447
44567
|
const dirName = workingDirBasename(this.workingDir);
|
|
44448
44568
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
44449
44569
|
this.appendRuntimeSystemMessage(
|
|
44450
|
-
|
|
44570
|
+
formatApprovalRequestMessage(modal?.message, modal?.buttons),
|
|
44451
44571
|
`approval_request:${now}`,
|
|
44452
44572
|
now
|
|
44453
44573
|
);
|
|
@@ -44477,11 +44597,6 @@ ${effect.notification.body || ""}`.trim();
|
|
|
44477
44597
|
now
|
|
44478
44598
|
);
|
|
44479
44599
|
}
|
|
44480
|
-
formatMarkerTimestamp(timestamp) {
|
|
44481
|
-
const date = new Date(timestamp);
|
|
44482
|
-
const pad = (value) => String(value).padStart(2, "0");
|
|
44483
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
44484
|
-
}
|
|
44485
44600
|
maybeAppendRuntimeRecoveryMessage(runtime) {
|
|
44486
44601
|
if (!runtime?.restoredFromStorage || !runtime.runtimeId) return;
|
|
44487
44602
|
const recoveryState = String(runtime.recoveryState || "").trim();
|
|
@@ -44542,81 +44657,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
44542
44657
|
}
|
|
44543
44658
|
}
|
|
44544
44659
|
mergeRuntimeChatMessages(parsedMessages) {
|
|
44545
|
-
return this.
|
|
44546
|
-
}
|
|
44547
|
-
mergeConversationMessages(parsedMessages) {
|
|
44548
|
-
if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
|
|
44549
|
-
const parsedEntries = parsedMessages.map((message, index) => ({
|
|
44550
|
-
message,
|
|
44551
|
-
index,
|
|
44552
|
-
source: "parsed"
|
|
44553
|
-
}));
|
|
44554
|
-
const getRole = (message) => typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
44555
|
-
const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
|
|
44556
|
-
message: entry.message,
|
|
44557
|
-
index: parsedMessages.length + index,
|
|
44558
|
-
source: "runtime",
|
|
44559
|
-
runtimeKey: entry.key
|
|
44560
|
-
})).filter((entry) => {
|
|
44561
|
-
const meta = entry.message.meta && typeof entry.message.meta === "object" && !Array.isArray(entry.message.meta) ? entry.message.meta : {};
|
|
44562
|
-
if (meta.runtimeInputAck !== true) return true;
|
|
44563
|
-
const runtimeText = flattenContent(entry.message.content).replace(/\s+/g, " ").trim();
|
|
44564
|
-
if (!runtimeText) return false;
|
|
44565
|
-
return !parsedEntries.some((parsedEntry) => {
|
|
44566
|
-
const parsedRole = getRole(parsedEntry.message);
|
|
44567
|
-
if (parsedRole !== "user" && parsedRole !== "human") return false;
|
|
44568
|
-
const parsedText = flattenContent(parsedEntry.message.content).replace(/\s+/g, " ").trim();
|
|
44569
|
-
return parsedText === runtimeText;
|
|
44570
|
-
});
|
|
44571
|
-
});
|
|
44572
|
-
const getTime = (message) => {
|
|
44573
|
-
const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
|
|
44574
|
-
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
44575
|
-
};
|
|
44576
|
-
const isRuntimeOverlay = (entry) => {
|
|
44577
|
-
if (entry.source !== "runtime") return false;
|
|
44578
|
-
const key2 = typeof entry.runtimeKey === "string" ? entry.runtimeKey.trim().toLowerCase() : "";
|
|
44579
|
-
if (key2.startsWith("auto_approval:")) return true;
|
|
44580
|
-
return !isUserFacingChatMessage(entry.message);
|
|
44581
|
-
};
|
|
44582
|
-
const shouldKeepParsedBeforeUntimedRuntime = (message) => {
|
|
44583
|
-
const role = getRole(message);
|
|
44584
|
-
return role === "user" || role === "human";
|
|
44585
|
-
};
|
|
44586
|
-
const shouldKeepParsedAfterUntimedRuntime = (message) => {
|
|
44587
|
-
const role = getRole(message);
|
|
44588
|
-
if (role !== "assistant") return false;
|
|
44589
|
-
const kind = resolveChatMessageKind(message);
|
|
44590
|
-
return kind === "standard" || kind === "terminal";
|
|
44591
|
-
};
|
|
44592
|
-
return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
|
|
44593
|
-
const aTime = getTime(a.message);
|
|
44594
|
-
const bTime = getTime(b.message);
|
|
44595
|
-
if (aTime && bTime && aTime !== bTime) return aTime - bTime;
|
|
44596
|
-
if (a.source !== b.source && aTime !== bTime) {
|
|
44597
|
-
const parsedEntry = a.source === "parsed" ? a : b.source === "parsed" ? b : null;
|
|
44598
|
-
const runtimeEntry = a.source === "runtime" ? a : b.source === "runtime" ? b : null;
|
|
44599
|
-
if (parsedEntry && runtimeEntry && isRuntimeOverlay(runtimeEntry) && getTime(parsedEntry.message) === 0 && getTime(runtimeEntry.message) > 0) {
|
|
44600
|
-
if (shouldKeepParsedBeforeUntimedRuntime(parsedEntry.message)) {
|
|
44601
|
-
return a.source === "parsed" ? -1 : 1;
|
|
44602
|
-
}
|
|
44603
|
-
if (shouldKeepParsedAfterUntimedRuntime(parsedEntry.message)) {
|
|
44604
|
-
return a.source === "parsed" ? 1 : -1;
|
|
44605
|
-
}
|
|
44606
|
-
}
|
|
44607
|
-
}
|
|
44608
|
-
return a.index - b.index;
|
|
44609
|
-
}).map((entry) => entry.message));
|
|
44610
|
-
}
|
|
44611
|
-
formatApprovalRequestMessage(modalMessage, buttons) {
|
|
44612
|
-
const lines = ["Approval requested"];
|
|
44613
|
-
const cleanMessage = String(modalMessage || "").trim();
|
|
44614
|
-
if (cleanMessage) lines.push(cleanMessage);
|
|
44615
|
-
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
44616
|
-
if (labels.length > 0) {
|
|
44617
|
-
lines.push(labels.map((label) => `[${label}]`).join(" "));
|
|
44618
|
-
}
|
|
44619
|
-
return lines.join("\n");
|
|
44660
|
+
return mergeConversationMessages(this.runtimeMessages, parsedMessages);
|
|
44620
44661
|
}
|
|
44621
44662
|
promoteProviderSessionId(sessionId, opts = {}) {
|
|
44622
44663
|
const nextSessionId = String(sessionId || "").trim();
|