@adhdev/daemon-core 0.9.82-rc.128 → 0.9.82-rc.129
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 +86 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +88 -12
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +1 -0
- package/package.json +1 -1
- package/src/commands/chat-commands.ts +71 -5
- package/src/providers/cli-provider-instance.ts +46 -5
|
@@ -97,6 +97,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
97
97
|
getSessionModalState(): SessionModalState;
|
|
98
98
|
updateSettings(newSettings: Record<string, any>): void;
|
|
99
99
|
onEvent(event: string, data?: any): void;
|
|
100
|
+
recordAcknowledgedUserInput(input: InputEnvelope | string): void;
|
|
100
101
|
dispose(): void;
|
|
101
102
|
private completedDebounceTimer;
|
|
102
103
|
private completedDebouncePending;
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ import { assertProviderSupportsDeclaredInput, assertTextOnlyInput } from '../pro
|
|
|
14
14
|
import { validateReadChatResultPayload } from '../providers/read-chat-contract.js';
|
|
15
15
|
import { pickApprovalButton } from '../providers/approval-utils.js';
|
|
16
16
|
import type { ProviderInstance } from '../providers/provider-instance.js';
|
|
17
|
-
import { isNativeSourceCanonicalHistory, readProviderChatHistory } from '../config/chat-history.js';
|
|
17
|
+
import { isNativeSourceCanonicalHistory, readChatHistory, readProviderChatHistory } from '../config/chat-history.js';
|
|
18
18
|
import { LOG, getRecentLogs } from '../logging/logger.js';
|
|
19
19
|
import { getRecentDebugTrace, recordDebugTrace } from '../logging/debug-trace.js';
|
|
20
20
|
import { buildChatMessageSignature, hashSignatureParts } from '../chat/chat-signatures.js';
|
|
@@ -40,6 +40,7 @@ interface ApprovalSelectableInstance extends ProviderInstance {
|
|
|
40
40
|
|
|
41
41
|
interface RuntimeChatMessageMerger extends ProviderInstance {
|
|
42
42
|
mergeRuntimeChatMessages?(messages: ChatMessage[]): ChatMessage[];
|
|
43
|
+
recordAcknowledgedUserInput?(input: InputEnvelope | string): void;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
type LegacyStringScript = (params?: Record<string, unknown> | string) => string;
|
|
@@ -454,6 +455,45 @@ function coerceUnsafeNativeFallbackStatus(status: string, activeModal: unknown):
|
|
|
454
455
|
return 'idle';
|
|
455
456
|
}
|
|
456
457
|
|
|
458
|
+
function isRuntimeInputAckMessage(message: ChatMessage | undefined): boolean {
|
|
459
|
+
if (!message || typeof message !== 'object') return false;
|
|
460
|
+
const role = String((message as any).role || '').trim().toLowerCase();
|
|
461
|
+
if (role !== 'user' && role !== 'human') return false;
|
|
462
|
+
const meta = (message as any).meta;
|
|
463
|
+
return !!meta && typeof meta === 'object' && !Array.isArray(meta) && meta.runtimeInputAck === true;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function selectRuntimeInputAckMessages(messages: ChatMessage[]): ChatMessage[] {
|
|
467
|
+
return messages.filter((message) => isRuntimeInputAckMessage(message));
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function readExactRuntimeMirrorMessages(args: {
|
|
471
|
+
providerType: string;
|
|
472
|
+
targetSessionId?: string;
|
|
473
|
+
currentSessionId?: string;
|
|
474
|
+
tailLimit: number;
|
|
475
|
+
historyBehavior?: ProviderModule['historyBehavior'];
|
|
476
|
+
}): ChatMessage[] {
|
|
477
|
+
const targetSessionId = String(args.targetSessionId || '').trim();
|
|
478
|
+
const currentSessionId = String(args.currentSessionId || '').trim();
|
|
479
|
+
if (!targetSessionId || targetSessionId !== currentSessionId) return [];
|
|
480
|
+
|
|
481
|
+
const history = readChatHistory(
|
|
482
|
+
args.providerType,
|
|
483
|
+
0,
|
|
484
|
+
Math.max(args.tailLimit || 0, 200),
|
|
485
|
+
targetSessionId,
|
|
486
|
+
0,
|
|
487
|
+
args.historyBehavior,
|
|
488
|
+
);
|
|
489
|
+
return normalizeChatMessages((history.messages || []) as ChatMessage[])
|
|
490
|
+
.filter((message) => {
|
|
491
|
+
const historySessionId = String((message as any).historySessionId || '').trim();
|
|
492
|
+
const instanceId = String((message as any).instanceId || '').trim();
|
|
493
|
+
return historySessionId === targetSessionId || instanceId === targetSessionId;
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
|
|
457
497
|
function supportsCliNativeTranscript(providerType: string, provider?: ProviderModule): boolean {
|
|
458
498
|
if (CLI_NATIVE_TRANSCRIPT_PROVIDERS.has(providerType)) return true;
|
|
459
499
|
return provider?.category === 'cli' && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
|
|
@@ -1512,10 +1552,26 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
1512
1552
|
});
|
|
1513
1553
|
const unsafeNativeFallback = adapter.cliType === 'codex-cli'
|
|
1514
1554
|
&& isUnsafeNativeTranscriptFallback(fallbackReason);
|
|
1555
|
+
const safeRuntimeAckMessages = unsafeNativeFallback
|
|
1556
|
+
? selectRuntimeInputAckMessages(returnedMessages)
|
|
1557
|
+
: [];
|
|
1558
|
+
const exactRuntimeMirrorMessages = unsafeNativeFallback
|
|
1559
|
+
&& safeRuntimeAckMessages.length === 0
|
|
1560
|
+
? readExactRuntimeMirrorMessages({
|
|
1561
|
+
providerType,
|
|
1562
|
+
targetSessionId: typeof args?.targetSessionId === 'string' ? args.targetSessionId : undefined,
|
|
1563
|
+
currentSessionId: typeof (h.currentSession as any)?.sessionId === 'string' ? (h.currentSession as any).sessionId : undefined,
|
|
1564
|
+
tailLimit: nativeHistoryLimit,
|
|
1565
|
+
historyBehavior: provider?.historyBehavior,
|
|
1566
|
+
})
|
|
1567
|
+
: [];
|
|
1568
|
+
const safeDaemonMessages = safeRuntimeAckMessages.length > 0
|
|
1569
|
+
? safeRuntimeAckMessages
|
|
1570
|
+
: exactRuntimeMirrorMessages;
|
|
1515
1571
|
if (unsafeNativeFallback) {
|
|
1516
|
-
selectedMessages =
|
|
1517
|
-
selectedTranscriptAuthority = undefined;
|
|
1518
|
-
selectedCoverage = undefined;
|
|
1572
|
+
selectedMessages = safeDaemonMessages;
|
|
1573
|
+
selectedTranscriptAuthority = safeDaemonMessages.length > 0 ? 'daemon' : undefined;
|
|
1574
|
+
selectedCoverage = safeDaemonMessages.length > 0 ? 'tail' : undefined;
|
|
1519
1575
|
selectedStatus = coerceUnsafeNativeFallbackStatus(returnedStatus, activeModal);
|
|
1520
1576
|
}
|
|
1521
1577
|
messageSource = buildCliMessageSourceProvenance({
|
|
@@ -1534,11 +1590,15 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
1534
1590
|
unavailableReason,
|
|
1535
1591
|
nativeMessages,
|
|
1536
1592
|
ptyMessages: returnedMessages,
|
|
1537
|
-
returnedMessages: unsafeNativeFallback ?
|
|
1593
|
+
returnedMessages: unsafeNativeFallback ? safeDaemonMessages : returnedMessages,
|
|
1538
1594
|
safeMapping,
|
|
1539
1595
|
freshEnough,
|
|
1540
1596
|
ptyStatusApprovalOnly: unsafeNativeFallback,
|
|
1541
1597
|
});
|
|
1598
|
+
if (unsafeNativeFallback && exactRuntimeMirrorMessages.length > 0) {
|
|
1599
|
+
(messageSource as any).selectedDaemonSource = 'exact-runtime-mirror';
|
|
1600
|
+
(messageSource as any).transcriptAuthority = 'daemon';
|
|
1601
|
+
}
|
|
1542
1602
|
}
|
|
1543
1603
|
}
|
|
1544
1604
|
}
|
|
@@ -1954,6 +2014,12 @@ export async function handleSendChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
1954
2014
|
} else {
|
|
1955
2015
|
await adapter.sendMessage(text);
|
|
1956
2016
|
}
|
|
2017
|
+
const target = getTargetInstance(h, args) as RuntimeChatMessageMerger | null;
|
|
2018
|
+
if (target?.category === 'cli'
|
|
2019
|
+
&& target.type === adapter.cliType
|
|
2020
|
+
&& typeof target.recordAcknowledgedUserInput === 'function') {
|
|
2021
|
+
target.recordAcknowledgedUserInput(input);
|
|
2022
|
+
}
|
|
1957
2023
|
return {
|
|
1958
2024
|
..._logSendSuccess(`${transport}-adapter`, adapter.cliType),
|
|
1959
2025
|
...(forceSend ? { forceSent: true } : {}),
|
|
@@ -752,6 +752,34 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
752
752
|
}
|
|
753
753
|
}
|
|
754
754
|
|
|
755
|
+
recordAcknowledgedUserInput(input: InputEnvelope | string): void {
|
|
756
|
+
const content = typeof input === 'string'
|
|
757
|
+
? input.trim()
|
|
758
|
+
: buildCliStructuredInputPrompt(input).trim();
|
|
759
|
+
if (!content) return;
|
|
760
|
+
|
|
761
|
+
const receivedAt = Date.now();
|
|
762
|
+
const dedupKey = `user_input_ack:${crypto
|
|
763
|
+
.createHash('sha256')
|
|
764
|
+
.update(`${this.instanceId}:${content}:${receivedAt}`)
|
|
765
|
+
.digest('hex')
|
|
766
|
+
.slice(0, 24)}`;
|
|
767
|
+
this.appendRuntimeMessage(buildChatMessage({
|
|
768
|
+
role: 'user',
|
|
769
|
+
senderName: 'User',
|
|
770
|
+
kind: 'standard',
|
|
771
|
+
content,
|
|
772
|
+
receivedAt,
|
|
773
|
+
timestamp: receivedAt,
|
|
774
|
+
source: 'runtime_input_ack',
|
|
775
|
+
meta: {
|
|
776
|
+
runtimeInputAck: true,
|
|
777
|
+
provider: this.type,
|
|
778
|
+
workspace: this.workingDir,
|
|
779
|
+
},
|
|
780
|
+
} as ChatMessage), dedupKey);
|
|
781
|
+
}
|
|
782
|
+
|
|
755
783
|
dispose(): void {
|
|
756
784
|
this.adapter.shutdown();
|
|
757
785
|
this.monitor.reset();
|
|
@@ -1450,12 +1478,28 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1450
1478
|
index,
|
|
1451
1479
|
source: 'parsed',
|
|
1452
1480
|
}));
|
|
1481
|
+
const getRole = (message: ChatMessage): string => typeof message.role === 'string'
|
|
1482
|
+
? message.role.trim().toLowerCase()
|
|
1483
|
+
: '';
|
|
1453
1484
|
const runtimeEntries: MergeEntry[] = this.runtimeMessages.map((entry, index) => ({
|
|
1454
1485
|
message: entry.message,
|
|
1455
1486
|
index: parsedMessages.length + index,
|
|
1456
|
-
source: 'runtime',
|
|
1487
|
+
source: 'runtime' as const,
|
|
1457
1488
|
runtimeKey: entry.key,
|
|
1458
|
-
}))
|
|
1489
|
+
})).filter((entry) => {
|
|
1490
|
+
const meta = entry.message.meta && typeof entry.message.meta === 'object' && !Array.isArray(entry.message.meta)
|
|
1491
|
+
? entry.message.meta as Record<string, unknown>
|
|
1492
|
+
: {};
|
|
1493
|
+
if (meta.runtimeInputAck !== true) return true;
|
|
1494
|
+
const runtimeText = flattenContent(entry.message.content).replace(/\s+/g, ' ').trim();
|
|
1495
|
+
if (!runtimeText) return false;
|
|
1496
|
+
return !parsedEntries.some((parsedEntry) => {
|
|
1497
|
+
const parsedRole = getRole(parsedEntry.message);
|
|
1498
|
+
if (parsedRole !== 'user' && parsedRole !== 'human') return false;
|
|
1499
|
+
const parsedText = flattenContent(parsedEntry.message.content).replace(/\s+/g, ' ').trim();
|
|
1500
|
+
return parsedText === runtimeText;
|
|
1501
|
+
});
|
|
1502
|
+
});
|
|
1459
1503
|
const getTime = (message: ChatMessage): number => {
|
|
1460
1504
|
const value = typeof message.receivedAt === 'number'
|
|
1461
1505
|
? message.receivedAt
|
|
@@ -1465,9 +1509,6 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1465
1509
|
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
1466
1510
|
};
|
|
1467
1511
|
|
|
1468
|
-
const getRole = (message: ChatMessage): string => typeof message.role === 'string'
|
|
1469
|
-
? message.role.trim().toLowerCase()
|
|
1470
|
-
: '';
|
|
1471
1512
|
const isRuntimeOverlay = (entry: MergeEntry): boolean => {
|
|
1472
1513
|
if (entry.source !== 'runtime') return false;
|
|
1473
1514
|
const key = typeof entry.runtimeKey === 'string' ? entry.runtimeKey.trim().toLowerCase() : '';
|