@adhdev/daemon-core 0.9.35 → 0.9.37
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/cli-adapters/provider-cli-adapter.d.ts +8 -1
- package/dist/index.js +161 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +161 -35
- package/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +112 -35
- package/src/cli-adapters/provider-cli-parse.ts +89 -11
- package/src/providers/cli-provider-instance.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1688,27 +1688,86 @@ function sliceFromOffset(text, start) {
|
|
|
1688
1688
|
function hydrateCliParsedMessages(parsedMessages, options) {
|
|
1689
1689
|
const { committedMessages, scope, lastOutputAt } = options;
|
|
1690
1690
|
const referenceMessages = [...committedMessages];
|
|
1691
|
-
const referenceComparables = referenceMessages.
|
|
1691
|
+
const referenceComparables = new Array(referenceMessages.length);
|
|
1692
1692
|
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
1693
1693
|
const now = options.now ?? Date.now();
|
|
1694
|
-
|
|
1694
|
+
let exactReferenceIndexesByKey = null;
|
|
1695
|
+
const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
|
|
1696
|
+
const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
|
|
1697
|
+
const getReferenceComparable = (index) => {
|
|
1698
|
+
if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
|
|
1699
|
+
const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
|
|
1700
|
+
referenceComparables[index] = comparable;
|
|
1701
|
+
return comparable;
|
|
1702
|
+
};
|
|
1703
|
+
const messagesShareStableIdentity = (parsed, reference) => {
|
|
1704
|
+
if (!parsed || !reference) return false;
|
|
1705
|
+
const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
|
|
1706
|
+
const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
|
|
1707
|
+
if (parsedId && referenceId && parsedId === referenceId) return true;
|
|
1708
|
+
return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
|
|
1709
|
+
};
|
|
1710
|
+
const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
|
|
1711
|
+
const ensureExactReferenceIndex = () => {
|
|
1712
|
+
if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
|
|
1713
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1714
|
+
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1715
|
+
const candidate = referenceMessages[i];
|
|
1716
|
+
if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
|
|
1717
|
+
const comparable = getReferenceComparable(i);
|
|
1718
|
+
if (!comparable) continue;
|
|
1719
|
+
const key = exactReferenceKey(candidate.role, comparable);
|
|
1720
|
+
const indexes = byKey.get(key);
|
|
1721
|
+
if (indexes) {
|
|
1722
|
+
indexes.push(i);
|
|
1723
|
+
} else {
|
|
1724
|
+
byKey.set(key, [i]);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
exactReferenceIndexesByKey = byKey;
|
|
1728
|
+
return byKey;
|
|
1729
|
+
};
|
|
1730
|
+
const takeExactReferenceTimestamp = (role, normalizedContent) => {
|
|
1731
|
+
const key = exactReferenceKey(role, normalizedContent);
|
|
1732
|
+
const indexes = ensureExactReferenceIndex().get(key);
|
|
1733
|
+
if (!indexes) return void 0;
|
|
1734
|
+
let cursor = exactReferenceCursorByKey.get(key) || 0;
|
|
1735
|
+
while (cursor < indexes.length) {
|
|
1736
|
+
const candidateIndex = indexes[cursor];
|
|
1737
|
+
cursor += 1;
|
|
1738
|
+
if (usedReferenceIndexes.has(candidateIndex)) continue;
|
|
1739
|
+
const candidate = referenceMessages[candidateIndex];
|
|
1740
|
+
if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
|
|
1741
|
+
usedReferenceIndexes.add(candidateIndex);
|
|
1742
|
+
exactReferenceCursorByKey.set(key, cursor);
|
|
1743
|
+
return candidate.timestamp;
|
|
1744
|
+
}
|
|
1745
|
+
exactReferenceCursorByKey.set(key, cursor);
|
|
1746
|
+
return void 0;
|
|
1747
|
+
};
|
|
1748
|
+
const findReferenceTimestamp = (message, role, content, parsedIndex) => {
|
|
1749
|
+
const sameIndex = referenceMessages[parsedIndex];
|
|
1750
|
+
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
|
|
1751
|
+
usedReferenceIndexes.add(parsedIndex);
|
|
1752
|
+
return sameIndex.timestamp;
|
|
1753
|
+
}
|
|
1695
1754
|
const normalizedContent = normalizeComparableMessageContent(content);
|
|
1696
1755
|
if (!normalizedContent) return void 0;
|
|
1697
|
-
|
|
1698
|
-
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && referenceComparables[parsedIndex] === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
|
|
1756
|
+
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
|
|
1699
1757
|
usedReferenceIndexes.add(parsedIndex);
|
|
1700
1758
|
return sameIndex.timestamp;
|
|
1701
1759
|
}
|
|
1760
|
+
const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
|
|
1761
|
+
if (typeof exactTimestamp === "number") return exactTimestamp;
|
|
1702
1762
|
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1703
1763
|
if (usedReferenceIndexes.has(i)) continue;
|
|
1704
1764
|
const candidate = referenceMessages[i];
|
|
1705
1765
|
if (!candidate || candidate.role !== role) continue;
|
|
1706
|
-
const candidateContent =
|
|
1766
|
+
const candidateContent = getReferenceComparable(i);
|
|
1707
1767
|
if (!candidateContent) continue;
|
|
1708
|
-
const exactMatch = candidateContent === normalizedContent;
|
|
1709
1768
|
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
1710
|
-
if (!
|
|
1711
|
-
if (
|
|
1769
|
+
if (!fuzzyMatch) continue;
|
|
1770
|
+
if (hasFiniteTimestamp(candidate)) {
|
|
1712
1771
|
usedReferenceIndexes.add(i);
|
|
1713
1772
|
return candidate.timestamp;
|
|
1714
1773
|
}
|
|
@@ -1719,7 +1778,7 @@ function hydrateCliParsedMessages(parsedMessages, options) {
|
|
|
1719
1778
|
const role = message.role;
|
|
1720
1779
|
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
1721
1780
|
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
1722
|
-
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
|
|
1781
|
+
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
|
|
1723
1782
|
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
|
|
1724
1783
|
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
1725
1784
|
return {
|
|
@@ -2224,7 +2283,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
2224
2283
|
if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
|
|
2225
2284
|
return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
|
|
2226
2285
|
}
|
|
2286
|
+
messagesShareStableIdentity(left, right) {
|
|
2287
|
+
if (left === right) return true;
|
|
2288
|
+
if (!left || !right) return false;
|
|
2289
|
+
if ((left.role || "") !== (right.role || "")) return false;
|
|
2290
|
+
if (left.id && right.id && String(left.id) === String(right.id)) return true;
|
|
2291
|
+
if (typeof left.index === "number" && typeof right.index === "number" && left.index === right.index) return true;
|
|
2292
|
+
return false;
|
|
2293
|
+
}
|
|
2227
2294
|
messagesComparable(left, right) {
|
|
2295
|
+
if (this.messagesShareStableIdentity(left, right)) return true;
|
|
2228
2296
|
if (!left || !right) return false;
|
|
2229
2297
|
if ((left.role || "") !== (right.role || "")) return false;
|
|
2230
2298
|
const leftText = normalizeComparableTranscriptText(left.content);
|
|
@@ -3329,11 +3397,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
3329
3397
|
};
|
|
3330
3398
|
}
|
|
3331
3399
|
// ─── Public API (CliAdapter) ───────────────────
|
|
3332
|
-
getStatus() {
|
|
3333
|
-
const
|
|
3400
|
+
getStatus(options = {}) {
|
|
3401
|
+
const allowParse = options.allowParse !== false;
|
|
3402
|
+
const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
3334
3403
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
3335
3404
|
let effectiveModal = startupModal || this.activeModal;
|
|
3336
|
-
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3405
|
+
if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3337
3406
|
let parsed = this.getFreshParsedStatusCache();
|
|
3338
3407
|
if (!parsed && effectiveStatus !== "idle") {
|
|
3339
3408
|
const now = Date.now();
|
|
@@ -3375,6 +3444,69 @@ var init_provider_cli_adapter = __esm({
|
|
|
3375
3444
|
this.committedMessages = normalized;
|
|
3376
3445
|
this.syncMessageViews();
|
|
3377
3446
|
}
|
|
3447
|
+
getSharedCommittedPrefixLength(parsedMessages) {
|
|
3448
|
+
const committedMessages = this.committedMessages;
|
|
3449
|
+
const max = Math.min(parsedMessages.length, committedMessages.length);
|
|
3450
|
+
let index = 0;
|
|
3451
|
+
while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
|
|
3452
|
+
index += 1;
|
|
3453
|
+
}
|
|
3454
|
+
return index;
|
|
3455
|
+
}
|
|
3456
|
+
hydrateCommittedPrefixForParsedStatus(parsedMessages) {
|
|
3457
|
+
const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
|
|
3458
|
+
if (sharedPrefixLength !== this.committedMessages.length) return null;
|
|
3459
|
+
const committedHydratedMessages = this.committedMessages.map((message, index) => {
|
|
3460
|
+
const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
|
|
3461
|
+
const contentValue = message.content;
|
|
3462
|
+
return {
|
|
3463
|
+
role: message.role,
|
|
3464
|
+
content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
|
|
3465
|
+
timestamp,
|
|
3466
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
|
|
3467
|
+
kind: message.kind,
|
|
3468
|
+
id: message.id || `msg_${index}`,
|
|
3469
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
3470
|
+
meta: message.meta,
|
|
3471
|
+
senderName: message.senderName
|
|
3472
|
+
};
|
|
3473
|
+
});
|
|
3474
|
+
const extraMessages = parsedMessages.slice(sharedPrefixLength);
|
|
3475
|
+
if (extraMessages.length === 0) return committedHydratedMessages;
|
|
3476
|
+
const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
|
|
3477
|
+
committedMessages: [],
|
|
3478
|
+
scope: this.currentTurnScope,
|
|
3479
|
+
lastOutputAt: this.lastOutputAt
|
|
3480
|
+
}).map((message, offset) => ({
|
|
3481
|
+
...message,
|
|
3482
|
+
id: message.id || `msg_${sharedPrefixLength + offset}`,
|
|
3483
|
+
index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
|
|
3484
|
+
}));
|
|
3485
|
+
return [...committedHydratedMessages, ...extraHydratedMessages];
|
|
3486
|
+
}
|
|
3487
|
+
hydrateParsedMessagesForStatus(parsedMessages) {
|
|
3488
|
+
return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
|
|
3489
|
+
committedMessages: this.committedMessages,
|
|
3490
|
+
scope: this.currentTurnScope,
|
|
3491
|
+
lastOutputAt: this.lastOutputAt
|
|
3492
|
+
});
|
|
3493
|
+
}
|
|
3494
|
+
buildCommittedChatMessages() {
|
|
3495
|
+
return this.committedMessages.map((message, index) => {
|
|
3496
|
+
const contentValue = message.content;
|
|
3497
|
+
return buildChatMessage({
|
|
3498
|
+
role: message.role,
|
|
3499
|
+
content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
|
|
3500
|
+
timestamp: message.timestamp,
|
|
3501
|
+
kind: message.kind,
|
|
3502
|
+
meta: message.meta,
|
|
3503
|
+
senderName: message.senderName,
|
|
3504
|
+
id: message.id || `msg_${index}`,
|
|
3505
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
3506
|
+
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3507
|
+
});
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3378
3510
|
/**
|
|
3379
3511
|
* Script-based full parse — returns ReadChatResult.
|
|
3380
3512
|
* Called by command handler / dashboard for rich content rendering.
|
|
@@ -3400,7 +3532,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3400
3532
|
this.onStatusChange?.();
|
|
3401
3533
|
}
|
|
3402
3534
|
}
|
|
3403
|
-
if (parsed && Array.isArray(parsed.messages)) {
|
|
3535
|
+
if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
|
|
3404
3536
|
const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
3405
3537
|
committedMessages: this.committedMessages,
|
|
3406
3538
|
scope: this.currentTurnScope,
|
|
@@ -3419,21 +3551,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
3419
3551
|
const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
|
|
3420
3552
|
let result;
|
|
3421
3553
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
3422
|
-
const parsedHydratedMessages =
|
|
3423
|
-
committedMessages: this.committedMessages,
|
|
3424
|
-
scope: this.currentTurnScope,
|
|
3425
|
-
lastOutputAt: this.lastOutputAt
|
|
3426
|
-
});
|
|
3427
|
-
const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
|
|
3428
|
-
...message,
|
|
3429
|
-
id: message.id || `msg_${index}`,
|
|
3430
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3431
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3432
|
-
}));
|
|
3554
|
+
const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
|
|
3433
3555
|
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
|
|
3434
|
-
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages,
|
|
3556
|
+
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, this.committedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle");
|
|
3435
3557
|
if (shouldAdoptParsedIdleReplay) {
|
|
3436
|
-
this.committedMessages =
|
|
3558
|
+
this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
|
|
3559
|
+
role: message.role,
|
|
3560
|
+
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
3561
|
+
timestamp: message.timestamp,
|
|
3562
|
+
receivedAt: message.receivedAt,
|
|
3563
|
+
kind: message.kind,
|
|
3564
|
+
id: message.id,
|
|
3565
|
+
index: message.index,
|
|
3566
|
+
meta: message.meta,
|
|
3567
|
+
senderName: message.senderName
|
|
3568
|
+
})) : normalizeCliParsedMessages(parsed.messages, {
|
|
3437
3569
|
committedMessages: this.committedMessages,
|
|
3438
3570
|
scope: this.currentTurnScope,
|
|
3439
3571
|
lastOutputAt: this.lastOutputAt
|
|
@@ -3452,15 +3584,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
3452
3584
|
this.onStatusChange?.();
|
|
3453
3585
|
}
|
|
3454
3586
|
}
|
|
3455
|
-
const
|
|
3456
|
-
...message,
|
|
3457
|
-
id: message.id || `msg_${index}`,
|
|
3458
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3459
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3460
|
-
})) : committedHydratedMessages;
|
|
3461
|
-
const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && effectiveCommittedHydratedMessages.length > parsedHydratedMessages.length;
|
|
3587
|
+
const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
|
|
3462
3588
|
const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
|
|
3463
|
-
const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ?
|
|
3589
|
+
const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
|
|
3464
3590
|
result = {
|
|
3465
3591
|
id: parsed.id || "cli_session",
|
|
3466
3592
|
status: parsed.status || this.currentStatus,
|
|
@@ -13332,7 +13458,7 @@ var CliProviderInstance = class {
|
|
|
13332
13458
|
return this.presentationMode;
|
|
13333
13459
|
}
|
|
13334
13460
|
getHotChatSessionState() {
|
|
13335
|
-
const adapterStatus = this.adapter.getStatus();
|
|
13461
|
+
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
13336
13462
|
const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
13337
13463
|
const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
|
|
13338
13464
|
const runtime = this.adapter.getRuntimeMetadata();
|