@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
|
@@ -117,6 +117,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
|
|
|
117
117
|
private resetTerminalScreen;
|
|
118
118
|
private getFreshParsedStatusCache;
|
|
119
119
|
private selectParseBaseMessages;
|
|
120
|
+
private messagesShareStableIdentity;
|
|
120
121
|
private messagesComparable;
|
|
121
122
|
private stitchParsedMessagesWithCommittedBase;
|
|
122
123
|
private getIdleFinishConfirmMs;
|
|
@@ -171,8 +172,14 @@ export declare class ProviderCliAdapter implements CliAdapter {
|
|
|
171
172
|
private hasActionableApproval;
|
|
172
173
|
private projectEffectiveStatus;
|
|
173
174
|
private suppressStaleParsedApproval;
|
|
174
|
-
getStatus(
|
|
175
|
+
getStatus(options?: {
|
|
176
|
+
allowParse?: boolean;
|
|
177
|
+
}): CliSessionStatus;
|
|
175
178
|
seedCommittedMessages(messages: SeedCliChatMessage[]): void;
|
|
179
|
+
private getSharedCommittedPrefixLength;
|
|
180
|
+
private hydrateCommittedPrefixForParsedStatus;
|
|
181
|
+
private hydrateParsedMessagesForStatus;
|
|
182
|
+
private buildCommittedChatMessages;
|
|
176
183
|
/**
|
|
177
184
|
* Script-based full parse — returns ReadChatResult.
|
|
178
185
|
* Called by command handler / dashboard for rich content rendering.
|
package/dist/index.js
CHANGED
|
@@ -1690,27 +1690,86 @@ function sliceFromOffset(text, start) {
|
|
|
1690
1690
|
function hydrateCliParsedMessages(parsedMessages, options) {
|
|
1691
1691
|
const { committedMessages, scope, lastOutputAt } = options;
|
|
1692
1692
|
const referenceMessages = [...committedMessages];
|
|
1693
|
-
const referenceComparables = referenceMessages.
|
|
1693
|
+
const referenceComparables = new Array(referenceMessages.length);
|
|
1694
1694
|
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
1695
1695
|
const now = options.now ?? Date.now();
|
|
1696
|
-
|
|
1696
|
+
let exactReferenceIndexesByKey = null;
|
|
1697
|
+
const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
|
|
1698
|
+
const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
|
|
1699
|
+
const getReferenceComparable = (index) => {
|
|
1700
|
+
if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
|
|
1701
|
+
const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
|
|
1702
|
+
referenceComparables[index] = comparable;
|
|
1703
|
+
return comparable;
|
|
1704
|
+
};
|
|
1705
|
+
const messagesShareStableIdentity = (parsed, reference) => {
|
|
1706
|
+
if (!parsed || !reference) return false;
|
|
1707
|
+
const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
|
|
1708
|
+
const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
|
|
1709
|
+
if (parsedId && referenceId && parsedId === referenceId) return true;
|
|
1710
|
+
return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
|
|
1711
|
+
};
|
|
1712
|
+
const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
|
|
1713
|
+
const ensureExactReferenceIndex = () => {
|
|
1714
|
+
if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
|
|
1715
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1716
|
+
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1717
|
+
const candidate = referenceMessages[i];
|
|
1718
|
+
if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
|
|
1719
|
+
const comparable = getReferenceComparable(i);
|
|
1720
|
+
if (!comparable) continue;
|
|
1721
|
+
const key = exactReferenceKey(candidate.role, comparable);
|
|
1722
|
+
const indexes = byKey.get(key);
|
|
1723
|
+
if (indexes) {
|
|
1724
|
+
indexes.push(i);
|
|
1725
|
+
} else {
|
|
1726
|
+
byKey.set(key, [i]);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
exactReferenceIndexesByKey = byKey;
|
|
1730
|
+
return byKey;
|
|
1731
|
+
};
|
|
1732
|
+
const takeExactReferenceTimestamp = (role, normalizedContent) => {
|
|
1733
|
+
const key = exactReferenceKey(role, normalizedContent);
|
|
1734
|
+
const indexes = ensureExactReferenceIndex().get(key);
|
|
1735
|
+
if (!indexes) return void 0;
|
|
1736
|
+
let cursor = exactReferenceCursorByKey.get(key) || 0;
|
|
1737
|
+
while (cursor < indexes.length) {
|
|
1738
|
+
const candidateIndex = indexes[cursor];
|
|
1739
|
+
cursor += 1;
|
|
1740
|
+
if (usedReferenceIndexes.has(candidateIndex)) continue;
|
|
1741
|
+
const candidate = referenceMessages[candidateIndex];
|
|
1742
|
+
if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
|
|
1743
|
+
usedReferenceIndexes.add(candidateIndex);
|
|
1744
|
+
exactReferenceCursorByKey.set(key, cursor);
|
|
1745
|
+
return candidate.timestamp;
|
|
1746
|
+
}
|
|
1747
|
+
exactReferenceCursorByKey.set(key, cursor);
|
|
1748
|
+
return void 0;
|
|
1749
|
+
};
|
|
1750
|
+
const findReferenceTimestamp = (message, role, content, parsedIndex) => {
|
|
1751
|
+
const sameIndex = referenceMessages[parsedIndex];
|
|
1752
|
+
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
|
|
1753
|
+
usedReferenceIndexes.add(parsedIndex);
|
|
1754
|
+
return sameIndex.timestamp;
|
|
1755
|
+
}
|
|
1697
1756
|
const normalizedContent = normalizeComparableMessageContent(content);
|
|
1698
1757
|
if (!normalizedContent) return void 0;
|
|
1699
|
-
|
|
1700
|
-
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && referenceComparables[parsedIndex] === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
|
|
1758
|
+
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
|
|
1701
1759
|
usedReferenceIndexes.add(parsedIndex);
|
|
1702
1760
|
return sameIndex.timestamp;
|
|
1703
1761
|
}
|
|
1762
|
+
const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
|
|
1763
|
+
if (typeof exactTimestamp === "number") return exactTimestamp;
|
|
1704
1764
|
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1705
1765
|
if (usedReferenceIndexes.has(i)) continue;
|
|
1706
1766
|
const candidate = referenceMessages[i];
|
|
1707
1767
|
if (!candidate || candidate.role !== role) continue;
|
|
1708
|
-
const candidateContent =
|
|
1768
|
+
const candidateContent = getReferenceComparable(i);
|
|
1709
1769
|
if (!candidateContent) continue;
|
|
1710
|
-
const exactMatch = candidateContent === normalizedContent;
|
|
1711
1770
|
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
1712
|
-
if (!
|
|
1713
|
-
if (
|
|
1771
|
+
if (!fuzzyMatch) continue;
|
|
1772
|
+
if (hasFiniteTimestamp(candidate)) {
|
|
1714
1773
|
usedReferenceIndexes.add(i);
|
|
1715
1774
|
return candidate.timestamp;
|
|
1716
1775
|
}
|
|
@@ -1721,7 +1780,7 @@ function hydrateCliParsedMessages(parsedMessages, options) {
|
|
|
1721
1780
|
const role = message.role;
|
|
1722
1781
|
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
1723
1782
|
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
1724
|
-
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
|
|
1783
|
+
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
|
|
1725
1784
|
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
|
|
1726
1785
|
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
1727
1786
|
return {
|
|
@@ -2227,7 +2286,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
2227
2286
|
if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
|
|
2228
2287
|
return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
|
|
2229
2288
|
}
|
|
2289
|
+
messagesShareStableIdentity(left, right) {
|
|
2290
|
+
if (left === right) return true;
|
|
2291
|
+
if (!left || !right) return false;
|
|
2292
|
+
if ((left.role || "") !== (right.role || "")) return false;
|
|
2293
|
+
if (left.id && right.id && String(left.id) === String(right.id)) return true;
|
|
2294
|
+
if (typeof left.index === "number" && typeof right.index === "number" && left.index === right.index) return true;
|
|
2295
|
+
return false;
|
|
2296
|
+
}
|
|
2230
2297
|
messagesComparable(left, right) {
|
|
2298
|
+
if (this.messagesShareStableIdentity(left, right)) return true;
|
|
2231
2299
|
if (!left || !right) return false;
|
|
2232
2300
|
if ((left.role || "") !== (right.role || "")) return false;
|
|
2233
2301
|
const leftText = normalizeComparableTranscriptText(left.content);
|
|
@@ -3332,11 +3400,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
3332
3400
|
};
|
|
3333
3401
|
}
|
|
3334
3402
|
// ─── Public API (CliAdapter) ───────────────────
|
|
3335
|
-
getStatus() {
|
|
3336
|
-
const
|
|
3403
|
+
getStatus(options = {}) {
|
|
3404
|
+
const allowParse = options.allowParse !== false;
|
|
3405
|
+
const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
3337
3406
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
3338
3407
|
let effectiveModal = startupModal || this.activeModal;
|
|
3339
|
-
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3408
|
+
if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3340
3409
|
let parsed = this.getFreshParsedStatusCache();
|
|
3341
3410
|
if (!parsed && effectiveStatus !== "idle") {
|
|
3342
3411
|
const now = Date.now();
|
|
@@ -3378,6 +3447,69 @@ var init_provider_cli_adapter = __esm({
|
|
|
3378
3447
|
this.committedMessages = normalized;
|
|
3379
3448
|
this.syncMessageViews();
|
|
3380
3449
|
}
|
|
3450
|
+
getSharedCommittedPrefixLength(parsedMessages) {
|
|
3451
|
+
const committedMessages = this.committedMessages;
|
|
3452
|
+
const max = Math.min(parsedMessages.length, committedMessages.length);
|
|
3453
|
+
let index = 0;
|
|
3454
|
+
while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
|
|
3455
|
+
index += 1;
|
|
3456
|
+
}
|
|
3457
|
+
return index;
|
|
3458
|
+
}
|
|
3459
|
+
hydrateCommittedPrefixForParsedStatus(parsedMessages) {
|
|
3460
|
+
const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
|
|
3461
|
+
if (sharedPrefixLength !== this.committedMessages.length) return null;
|
|
3462
|
+
const committedHydratedMessages = this.committedMessages.map((message, index) => {
|
|
3463
|
+
const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
|
|
3464
|
+
const contentValue = message.content;
|
|
3465
|
+
return {
|
|
3466
|
+
role: message.role,
|
|
3467
|
+
content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
|
|
3468
|
+
timestamp,
|
|
3469
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
|
|
3470
|
+
kind: message.kind,
|
|
3471
|
+
id: message.id || `msg_${index}`,
|
|
3472
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
3473
|
+
meta: message.meta,
|
|
3474
|
+
senderName: message.senderName
|
|
3475
|
+
};
|
|
3476
|
+
});
|
|
3477
|
+
const extraMessages = parsedMessages.slice(sharedPrefixLength);
|
|
3478
|
+
if (extraMessages.length === 0) return committedHydratedMessages;
|
|
3479
|
+
const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
|
|
3480
|
+
committedMessages: [],
|
|
3481
|
+
scope: this.currentTurnScope,
|
|
3482
|
+
lastOutputAt: this.lastOutputAt
|
|
3483
|
+
}).map((message, offset) => ({
|
|
3484
|
+
...message,
|
|
3485
|
+
id: message.id || `msg_${sharedPrefixLength + offset}`,
|
|
3486
|
+
index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
|
|
3487
|
+
}));
|
|
3488
|
+
return [...committedHydratedMessages, ...extraHydratedMessages];
|
|
3489
|
+
}
|
|
3490
|
+
hydrateParsedMessagesForStatus(parsedMessages) {
|
|
3491
|
+
return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
|
|
3492
|
+
committedMessages: this.committedMessages,
|
|
3493
|
+
scope: this.currentTurnScope,
|
|
3494
|
+
lastOutputAt: this.lastOutputAt
|
|
3495
|
+
});
|
|
3496
|
+
}
|
|
3497
|
+
buildCommittedChatMessages() {
|
|
3498
|
+
return this.committedMessages.map((message, index) => {
|
|
3499
|
+
const contentValue = message.content;
|
|
3500
|
+
return buildChatMessage({
|
|
3501
|
+
role: message.role,
|
|
3502
|
+
content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
|
|
3503
|
+
timestamp: message.timestamp,
|
|
3504
|
+
kind: message.kind,
|
|
3505
|
+
meta: message.meta,
|
|
3506
|
+
senderName: message.senderName,
|
|
3507
|
+
id: message.id || `msg_${index}`,
|
|
3508
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
3509
|
+
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3510
|
+
});
|
|
3511
|
+
});
|
|
3512
|
+
}
|
|
3381
3513
|
/**
|
|
3382
3514
|
* Script-based full parse — returns ReadChatResult.
|
|
3383
3515
|
* Called by command handler / dashboard for rich content rendering.
|
|
@@ -3403,7 +3535,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3403
3535
|
this.onStatusChange?.();
|
|
3404
3536
|
}
|
|
3405
3537
|
}
|
|
3406
|
-
if (parsed && Array.isArray(parsed.messages)) {
|
|
3538
|
+
if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
|
|
3407
3539
|
const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
3408
3540
|
committedMessages: this.committedMessages,
|
|
3409
3541
|
scope: this.currentTurnScope,
|
|
@@ -3422,21 +3554,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
3422
3554
|
const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
|
|
3423
3555
|
let result;
|
|
3424
3556
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
3425
|
-
const parsedHydratedMessages =
|
|
3426
|
-
committedMessages: this.committedMessages,
|
|
3427
|
-
scope: this.currentTurnScope,
|
|
3428
|
-
lastOutputAt: this.lastOutputAt
|
|
3429
|
-
});
|
|
3430
|
-
const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
|
|
3431
|
-
...message,
|
|
3432
|
-
id: message.id || `msg_${index}`,
|
|
3433
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3434
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3435
|
-
}));
|
|
3557
|
+
const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
|
|
3436
3558
|
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
|
|
3437
|
-
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages,
|
|
3559
|
+
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");
|
|
3438
3560
|
if (shouldAdoptParsedIdleReplay) {
|
|
3439
|
-
this.committedMessages =
|
|
3561
|
+
this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
|
|
3562
|
+
role: message.role,
|
|
3563
|
+
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
3564
|
+
timestamp: message.timestamp,
|
|
3565
|
+
receivedAt: message.receivedAt,
|
|
3566
|
+
kind: message.kind,
|
|
3567
|
+
id: message.id,
|
|
3568
|
+
index: message.index,
|
|
3569
|
+
meta: message.meta,
|
|
3570
|
+
senderName: message.senderName
|
|
3571
|
+
})) : normalizeCliParsedMessages(parsed.messages, {
|
|
3440
3572
|
committedMessages: this.committedMessages,
|
|
3441
3573
|
scope: this.currentTurnScope,
|
|
3442
3574
|
lastOutputAt: this.lastOutputAt
|
|
@@ -3455,15 +3587,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
3455
3587
|
this.onStatusChange?.();
|
|
3456
3588
|
}
|
|
3457
3589
|
}
|
|
3458
|
-
const
|
|
3459
|
-
...message,
|
|
3460
|
-
id: message.id || `msg_${index}`,
|
|
3461
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3462
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3463
|
-
})) : committedHydratedMessages;
|
|
3464
|
-
const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && effectiveCommittedHydratedMessages.length > parsedHydratedMessages.length;
|
|
3590
|
+
const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
|
|
3465
3591
|
const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
|
|
3466
|
-
const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ?
|
|
3592
|
+
const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
|
|
3467
3593
|
result = {
|
|
3468
3594
|
id: parsed.id || "cli_session",
|
|
3469
3595
|
status: parsed.status || this.currentStatus,
|
|
@@ -13485,7 +13611,7 @@ var CliProviderInstance = class {
|
|
|
13485
13611
|
return this.presentationMode;
|
|
13486
13612
|
}
|
|
13487
13613
|
getHotChatSessionState() {
|
|
13488
|
-
const adapterStatus = this.adapter.getStatus();
|
|
13614
|
+
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
13489
13615
|
const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
13490
13616
|
const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
|
|
13491
13617
|
const runtime = this.adapter.getRuntimeMetadata();
|