@adhdev/daemon-core 0.9.63 → 0.9.65
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/chat/chat-signatures.d.ts +0 -4
- package/dist/chat/chat-signatures.js +0 -4
- package/dist/chat/chat-signatures.js.map +1 -1
- package/dist/chat/chat-signatures.mjs +0 -4
- package/dist/chat/chat-signatures.mjs.map +1 -1
- package/dist/chat/subscription-updates.d.ts +0 -2
- package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -30
- package/dist/cli-adapters/provider-cli-parse.d.ts +1 -8
- package/dist/cli-adapters/provider-cli-shared.d.ts +8 -3
- package/dist/commands/chat-commands.d.ts +0 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +646 -1687
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +646 -1687
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +0 -7
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/chat/chat-signatures.ts +0 -8
- package/src/chat/subscription-updates.ts +7 -46
- package/src/cli-adapters/provider-cli-adapter.d.ts +2 -10
- package/src/cli-adapters/provider-cli-adapter.ts +66 -692
- package/src/cli-adapters/provider-cli-parse.d.ts +0 -7
- package/src/cli-adapters/provider-cli-parse.ts +2 -226
- package/src/cli-adapters/provider-cli-shared.d.ts +0 -1
- package/src/cli-adapters/provider-cli-shared.ts +8 -3
- package/src/commands/chat-commands.ts +54 -338
- package/src/daemon/dev-auto-implement.ts +3 -3
- package/src/daemon/dev-server.ts +3 -3
- package/src/index.d.ts +1 -1
- package/src/index.ts +0 -1
- package/src/launch.ts +10 -3
- package/src/providers/cli-provider-instance.ts +2 -39
- package/src/shared-types.d.ts +0 -7
- package/src/shared-types.ts +0 -8
|
@@ -5,14 +5,7 @@ export interface TurnParseScope {
|
|
|
5
5
|
bufferStart: number;
|
|
6
6
|
rawBufferStart: number;
|
|
7
7
|
}
|
|
8
|
-
export declare function hydrateCliParsedMessages(parsedMessages: any[], options: {
|
|
9
|
-
committedMessages: CliChatMessage[];
|
|
10
|
-
scope?: TurnParseScope | null;
|
|
11
|
-
lastOutputAt: number;
|
|
12
|
-
now?: number;
|
|
13
|
-
}): any[];
|
|
14
8
|
export declare function normalizeCliParsedMessages(parsedMessages: any[], options: {
|
|
15
|
-
committedMessages: CliChatMessage[];
|
|
16
9
|
scope?: TurnParseScope | null;
|
|
17
10
|
lastOutputAt: number;
|
|
18
11
|
now?: number;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildCliScreenSnapshot,
|
|
3
|
-
normalizeComparableMessageContent,
|
|
4
3
|
sanitizeTerminalText,
|
|
5
4
|
type CliChatMessage,
|
|
6
5
|
type CliScriptInput,
|
|
@@ -20,238 +19,15 @@ function sliceFromOffset(text: string, start: number): string {
|
|
|
20
19
|
return text.slice(start);
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
export function hydrateCliParsedMessages(
|
|
24
|
-
parsedMessages: any[],
|
|
25
|
-
options: {
|
|
26
|
-
committedMessages: CliChatMessage[];
|
|
27
|
-
scope?: TurnParseScope | null;
|
|
28
|
-
lastOutputAt: number;
|
|
29
|
-
now?: number;
|
|
30
|
-
},
|
|
31
|
-
): any[] {
|
|
32
|
-
const { committedMessages, scope, lastOutputAt } = options;
|
|
33
|
-
const referenceMessages = [...committedMessages];
|
|
34
|
-
const referenceComparables: Array<string | undefined> = new Array(referenceMessages.length);
|
|
35
|
-
const usedReferenceIndexes = new Set<number>();
|
|
36
|
-
const now = options.now ?? Date.now();
|
|
37
|
-
let exactReferenceIndexesByKey: Map<string, number[]> | null = null;
|
|
38
|
-
const exactReferenceCursorByKey = new Map<string, number>();
|
|
39
|
-
|
|
40
|
-
const hasFiniteTimestamp = (message: any): message is { timestamp: number } => (
|
|
41
|
-
typeof message?.timestamp === 'number' && Number.isFinite(message.timestamp)
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const getReferenceComparable = (index: number): string => {
|
|
45
|
-
if (typeof referenceComparables[index] === 'string') return referenceComparables[index] || '';
|
|
46
|
-
const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || '');
|
|
47
|
-
referenceComparables[index] = comparable;
|
|
48
|
-
return comparable;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const messagesShareStableIdentity = (parsed: any, reference: any): boolean => {
|
|
52
|
-
if (!parsed || !reference) return false;
|
|
53
|
-
const parsedId = typeof parsed.id === 'string' ? parsed.id.trim() : '';
|
|
54
|
-
const referenceId = typeof reference.id === 'string' ? reference.id.trim() : '';
|
|
55
|
-
if (parsedId && referenceId && parsedId === referenceId) return true;
|
|
56
|
-
return typeof parsed.index === 'number'
|
|
57
|
-
&& Number.isFinite(parsed.index)
|
|
58
|
-
&& typeof reference.index === 'number'
|
|
59
|
-
&& Number.isFinite(reference.index)
|
|
60
|
-
&& parsed.index === reference.index;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const exactReferenceKey = (role: 'user' | 'assistant', comparable: string): string => `${role}\u0000${comparable}`;
|
|
64
|
-
|
|
65
|
-
const ensureExactReferenceIndex = (): Map<string, number[]> => {
|
|
66
|
-
if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
|
|
67
|
-
const byKey = new Map<string, number[]>();
|
|
68
|
-
for (let i = 0; i < referenceMessages.length; i++) {
|
|
69
|
-
const candidate = referenceMessages[i];
|
|
70
|
-
if (!candidate || (candidate.role !== 'user' && candidate.role !== 'assistant') || !hasFiniteTimestamp(candidate)) continue;
|
|
71
|
-
const comparable = getReferenceComparable(i);
|
|
72
|
-
if (!comparable) continue;
|
|
73
|
-
const key = exactReferenceKey(candidate.role, comparable);
|
|
74
|
-
const indexes = byKey.get(key);
|
|
75
|
-
if (indexes) {
|
|
76
|
-
indexes.push(i);
|
|
77
|
-
} else {
|
|
78
|
-
byKey.set(key, [i]);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
exactReferenceIndexesByKey = byKey;
|
|
82
|
-
return byKey;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const takeExactReferenceTimestamp = (role: 'user' | 'assistant', normalizedContent: string): number | undefined => {
|
|
86
|
-
const key = exactReferenceKey(role, normalizedContent);
|
|
87
|
-
const indexes = ensureExactReferenceIndex().get(key);
|
|
88
|
-
if (!indexes) return undefined;
|
|
89
|
-
let cursor = exactReferenceCursorByKey.get(key) || 0;
|
|
90
|
-
while (cursor < indexes.length) {
|
|
91
|
-
const candidateIndex = indexes[cursor];
|
|
92
|
-
cursor += 1;
|
|
93
|
-
if (usedReferenceIndexes.has(candidateIndex)) continue;
|
|
94
|
-
const candidate = referenceMessages[candidateIndex];
|
|
95
|
-
if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
|
|
96
|
-
usedReferenceIndexes.add(candidateIndex);
|
|
97
|
-
exactReferenceCursorByKey.set(key, cursor);
|
|
98
|
-
return candidate.timestamp;
|
|
99
|
-
}
|
|
100
|
-
exactReferenceCursorByKey.set(key, cursor);
|
|
101
|
-
return undefined;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const findReferenceTimestamp = (message: any, role: 'user' | 'assistant', content: string, parsedIndex: number): number | undefined => {
|
|
105
|
-
const sameIndex = referenceMessages[parsedIndex];
|
|
106
|
-
if (
|
|
107
|
-
sameIndex
|
|
108
|
-
&& !usedReferenceIndexes.has(parsedIndex)
|
|
109
|
-
&& sameIndex.role === role
|
|
110
|
-
&& hasFiniteTimestamp(sameIndex)
|
|
111
|
-
&& messagesShareStableIdentity(message, sameIndex)
|
|
112
|
-
) {
|
|
113
|
-
usedReferenceIndexes.add(parsedIndex);
|
|
114
|
-
return sameIndex.timestamp;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const normalizedContent = normalizeComparableMessageContent(content);
|
|
118
|
-
if (!normalizedContent) return undefined;
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
sameIndex
|
|
122
|
-
&& !usedReferenceIndexes.has(parsedIndex)
|
|
123
|
-
&& sameIndex.role === role
|
|
124
|
-
&& getReferenceComparable(parsedIndex) === normalizedContent
|
|
125
|
-
&& hasFiniteTimestamp(sameIndex)
|
|
126
|
-
) {
|
|
127
|
-
usedReferenceIndexes.add(parsedIndex);
|
|
128
|
-
return sameIndex.timestamp;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
|
|
132
|
-
if (typeof exactTimestamp === 'number') return exactTimestamp;
|
|
133
|
-
|
|
134
|
-
for (let i = 0; i < referenceMessages.length; i++) {
|
|
135
|
-
if (usedReferenceIndexes.has(i)) continue;
|
|
136
|
-
const candidate = referenceMessages[i];
|
|
137
|
-
if (!candidate || candidate.role !== role) continue;
|
|
138
|
-
const candidateContent = getReferenceComparable(i);
|
|
139
|
-
if (!candidateContent) continue;
|
|
140
|
-
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
141
|
-
if (!fuzzyMatch) continue;
|
|
142
|
-
if (hasFiniteTimestamp(candidate)) {
|
|
143
|
-
usedReferenceIndexes.add(i);
|
|
144
|
-
return candidate.timestamp;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return undefined;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
return parsedMessages
|
|
152
|
-
.filter((message) => message && (message.role === 'user' || message.role === 'assistant'))
|
|
153
|
-
.map((message, index) => {
|
|
154
|
-
const role = message.role as 'user' | 'assistant';
|
|
155
|
-
const content = typeof message.content === 'string' ? message.content : String(message.content || '');
|
|
156
|
-
const parsedTimestamp = typeof message.timestamp === 'number' && Number.isFinite(message.timestamp)
|
|
157
|
-
? message.timestamp
|
|
158
|
-
: undefined;
|
|
159
|
-
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
|
|
160
|
-
const fallbackTimestamp = role === 'user'
|
|
161
|
-
? (scope?.startedAt || now)
|
|
162
|
-
: (lastOutputAt || scope?.startedAt || now);
|
|
163
|
-
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
164
|
-
return {
|
|
165
|
-
...message,
|
|
166
|
-
role,
|
|
167
|
-
content,
|
|
168
|
-
timestamp,
|
|
169
|
-
receivedAt: typeof message.receivedAt === 'number' && Number.isFinite(message.receivedAt)
|
|
170
|
-
? message.receivedAt
|
|
171
|
-
: timestamp,
|
|
172
|
-
};
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function chooseMoreComparableCliMessage(
|
|
177
|
-
left: CliChatMessage,
|
|
178
|
-
right: CliChatMessage,
|
|
179
|
-
leftComparable = normalizeComparableMessageContent(left.content || ''),
|
|
180
|
-
rightComparable = normalizeComparableMessageContent(right.content || ''),
|
|
181
|
-
): CliChatMessage {
|
|
182
|
-
if (leftComparable && leftComparable === rightComparable) {
|
|
183
|
-
const leftNewlines = String(left.content || '').split(/\r\n|\n|\r/g).length - 1;
|
|
184
|
-
const rightNewlines = String(right.content || '').split(/\r\n|\n|\r/g).length - 1;
|
|
185
|
-
return rightNewlines < leftNewlines ? right : left;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return rightComparable.length > leftComparable.length ? right : left;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function dedupeConsecutiveComparableCliMessages(messages: CliChatMessage[]): CliChatMessage[] {
|
|
192
|
-
const deduped: Array<{ message: CliChatMessage; comparable: string }> = [];
|
|
193
|
-
|
|
194
|
-
for (const message of messages) {
|
|
195
|
-
const current = {
|
|
196
|
-
...message,
|
|
197
|
-
content: typeof message.content === 'string' ? message.content : String(message.content || ''),
|
|
198
|
-
} as CliChatMessage;
|
|
199
|
-
const currentComparable = normalizeComparableMessageContent(current.content || '');
|
|
200
|
-
const previous = deduped[deduped.length - 1];
|
|
201
|
-
if (!previous) {
|
|
202
|
-
deduped.push({ message: current, comparable: currentComparable });
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const sameRole = previous.message.role === current.role;
|
|
207
|
-
const sameKind = (previous.message.kind || 'standard') === (current.kind || 'standard');
|
|
208
|
-
const sameSender = (previous.message.senderName || '') === (current.senderName || '');
|
|
209
|
-
const comparableMatch = previous.comparable && previous.comparable === currentComparable;
|
|
210
|
-
|
|
211
|
-
if (sameRole && sameKind && sameSender && comparableMatch) {
|
|
212
|
-
const selected = chooseMoreComparableCliMessage(
|
|
213
|
-
previous.message,
|
|
214
|
-
current,
|
|
215
|
-
previous.comparable,
|
|
216
|
-
currentComparable,
|
|
217
|
-
);
|
|
218
|
-
deduped[deduped.length - 1] = {
|
|
219
|
-
message: selected,
|
|
220
|
-
comparable: selected === current ? currentComparable : previous.comparable,
|
|
221
|
-
};
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
deduped.push({ message: current, comparable: currentComparable });
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return deduped.map((entry) => entry.message);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
22
|
export function normalizeCliParsedMessages(
|
|
232
23
|
parsedMessages: any[],
|
|
233
|
-
|
|
234
|
-
committedMessages: CliChatMessage[];
|
|
24
|
+
_options: {
|
|
235
25
|
scope?: TurnParseScope | null;
|
|
236
26
|
lastOutputAt: number;
|
|
237
27
|
now?: number;
|
|
238
28
|
},
|
|
239
29
|
): CliChatMessage[] {
|
|
240
|
-
return
|
|
241
|
-
role: message.role,
|
|
242
|
-
content: message.content,
|
|
243
|
-
timestamp: message.timestamp,
|
|
244
|
-
receivedAt: message.receivedAt,
|
|
245
|
-
kind: message.kind,
|
|
246
|
-
id: message.id,
|
|
247
|
-
index: message.index,
|
|
248
|
-
providerUnitKey: message.providerUnitKey,
|
|
249
|
-
bubbleId: message.bubbleId,
|
|
250
|
-
bubbleState: message.bubbleState,
|
|
251
|
-
_turnKey: message._turnKey,
|
|
252
|
-
meta: message.meta,
|
|
253
|
-
senderName: message.senderName,
|
|
254
|
-
})));
|
|
30
|
+
return Array.isArray(parsedMessages) ? parsedMessages as CliChatMessage[] : [];
|
|
255
31
|
}
|
|
256
32
|
|
|
257
33
|
export function buildCliParseInput(options: {
|
|
@@ -20,7 +20,6 @@ export interface CliSessionStatus {
|
|
|
20
20
|
errorReason?: string;
|
|
21
21
|
}
|
|
22
22
|
export interface CliScripts {
|
|
23
|
-
parseOutput?: (input: CliScriptInput) => any;
|
|
24
23
|
detectStatus?: (input: CliStatusInput) => string | null;
|
|
25
24
|
parseApproval?: (input: CliApprovalInput) => {
|
|
26
25
|
message: string;
|
|
@@ -3,18 +3,24 @@ import * as path from 'path';
|
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import type { ProviderResumeCapability } from '../providers/contracts.js';
|
|
5
5
|
import type { ChatMessageKind } from '../providers/chat-message-normalization.js';
|
|
6
|
+
import type { ChatBubbleState } from '../types.js';
|
|
6
7
|
import { sanitizeSpawnEnv } from './spawn-env.js';
|
|
7
8
|
|
|
8
9
|
export interface CliChatMessage {
|
|
9
|
-
role:
|
|
10
|
-
content:
|
|
10
|
+
role: string;
|
|
11
|
+
content: any;
|
|
11
12
|
timestamp?: number;
|
|
12
13
|
receivedAt?: number;
|
|
13
14
|
kind?: ChatMessageKind;
|
|
14
15
|
id?: string;
|
|
15
16
|
index?: number;
|
|
17
|
+
providerUnitKey?: string;
|
|
18
|
+
bubbleId?: string;
|
|
19
|
+
bubbleState?: ChatBubbleState;
|
|
20
|
+
_turnKey?: string;
|
|
16
21
|
meta?: Record<string, unknown>;
|
|
17
22
|
senderName?: string;
|
|
23
|
+
[key: string]: any;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
export interface CliSessionStatus {
|
|
@@ -43,7 +49,6 @@ export interface ParsedSession {
|
|
|
43
49
|
|
|
44
50
|
export interface CliScripts {
|
|
45
51
|
parseSession?: (input: CliScriptInput & { tail?: string; tailScreen?: CliScreenSnapshot }) => ParsedSession | null;
|
|
46
|
-
parseOutput?: (input: CliScriptInput) => any;
|
|
47
52
|
detectStatus?: (input: CliStatusInput) => string | null;
|
|
48
53
|
parseApproval?: (input: CliApprovalInput) => { message: string; buttons: string[] } | null;
|
|
49
54
|
resolveAction?: (data: any) => string;
|