@adhdev/daemon-core 0.9.6 → 0.9.8
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 +7 -8
- package/dist/cli-adapters/provider-cli-shared.d.ts +0 -1
- package/dist/index.js +379 -486
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +379 -486
- 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 +303 -446
- package/src/cli-adapters/provider-cli-parse.ts +47 -2
- package/src/cli-adapters/provider-cli-shared.ts +51 -5
- package/src/commands/chat-commands.ts +11 -13
|
@@ -94,6 +94,51 @@ export function hydrateCliParsedMessages(
|
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
function chooseMoreComparableCliMessage(left: CliChatMessage, right: CliChatMessage): CliChatMessage {
|
|
98
|
+
const leftComparable = normalizeComparableMessageContent(left.content || '');
|
|
99
|
+
const rightComparable = normalizeComparableMessageContent(right.content || '');
|
|
100
|
+
|
|
101
|
+
if (leftComparable && leftComparable === rightComparable) {
|
|
102
|
+
const leftNewlines = String(left.content || '').split(/\r\n|\n|\r/g).length - 1;
|
|
103
|
+
const rightNewlines = String(right.content || '').split(/\r\n|\n|\r/g).length - 1;
|
|
104
|
+
return rightNewlines < leftNewlines ? right : left;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return rightComparable.length > leftComparable.length ? right : left;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function dedupeConsecutiveComparableCliMessages(messages: CliChatMessage[]): CliChatMessage[] {
|
|
111
|
+
const deduped: CliChatMessage[] = [];
|
|
112
|
+
|
|
113
|
+
for (const message of messages) {
|
|
114
|
+
const current = {
|
|
115
|
+
...message,
|
|
116
|
+
content: typeof message.content === 'string' ? message.content : String(message.content || ''),
|
|
117
|
+
} as CliChatMessage;
|
|
118
|
+
const previous = deduped[deduped.length - 1];
|
|
119
|
+
if (!previous) {
|
|
120
|
+
deduped.push(current);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const previousComparable = normalizeComparableMessageContent(previous.content || '');
|
|
125
|
+
const currentComparable = normalizeComparableMessageContent(current.content || '');
|
|
126
|
+
const sameRole = previous.role === current.role;
|
|
127
|
+
const sameKind = (previous.kind || 'standard') === (current.kind || 'standard');
|
|
128
|
+
const sameSender = (previous.senderName || '') === (current.senderName || '');
|
|
129
|
+
const comparableMatch = previousComparable && previousComparable === currentComparable;
|
|
130
|
+
|
|
131
|
+
if (sameRole && sameKind && sameSender && comparableMatch) {
|
|
132
|
+
deduped[deduped.length - 1] = chooseMoreComparableCliMessage(previous, current);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
deduped.push(current);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return deduped;
|
|
140
|
+
}
|
|
141
|
+
|
|
97
142
|
export function normalizeCliParsedMessages(
|
|
98
143
|
parsedMessages: any[],
|
|
99
144
|
options: {
|
|
@@ -103,7 +148,7 @@ export function normalizeCliParsedMessages(
|
|
|
103
148
|
now?: number;
|
|
104
149
|
},
|
|
105
150
|
): CliChatMessage[] {
|
|
106
|
-
return hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
151
|
+
return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
107
152
|
role: message.role,
|
|
108
153
|
content: message.content,
|
|
109
154
|
timestamp: message.timestamp,
|
|
@@ -113,7 +158,7 @@ export function normalizeCliParsedMessages(
|
|
|
113
158
|
index: message.index,
|
|
114
159
|
meta: message.meta,
|
|
115
160
|
senderName: message.senderName,
|
|
116
|
-
}));
|
|
161
|
+
})));
|
|
117
162
|
}
|
|
118
163
|
|
|
119
164
|
export function buildCliParseInput(options: {
|
|
@@ -373,8 +373,58 @@ export function normalizeScreenSnapshot(text: string): string {
|
|
|
373
373
|
.trim();
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
+
const COMMON_COMPARABLE_WRAP_WORDS = new Set([
|
|
377
|
+
'a', 'an', 'and', 'as', 'at', 'but', 'by', 'for', 'from', 'in', 'into', 'is', 'it', 'of', 'on', 'or', 'that', 'the', 'their', 'then', 'this', 'to', 'was', 'with',
|
|
378
|
+
]);
|
|
379
|
+
|
|
380
|
+
function shouldReflowComparableMessageLines(lines: string[]): boolean {
|
|
381
|
+
return Array.isArray(lines)
|
|
382
|
+
&& lines.length > 1
|
|
383
|
+
&& lines.slice(0, -1).every((line) => String(line || '').trim().length >= 48)
|
|
384
|
+
&& !lines.some((line) => /^```/.test(line))
|
|
385
|
+
&& !lines.some((line) => /^\|/.test(line))
|
|
386
|
+
&& !lines.some((line) => /^\s*(?:[-*+] |\d+\.\s)/.test(line));
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function joinComparableMessageLines(lines: string[]): string {
|
|
390
|
+
return lines.reduce((acc, line) => {
|
|
391
|
+
const next = String(line || '').trim();
|
|
392
|
+
if (!next) return acc;
|
|
393
|
+
if (!acc) return next;
|
|
394
|
+
|
|
395
|
+
if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
|
|
396
|
+
return `${acc}${next}`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
|
|
400
|
+
return `${acc}${next}`;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
|
|
404
|
+
const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : '';
|
|
405
|
+
if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
|
|
406
|
+
return `${acc}${next}`;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return `${acc} ${next}`;
|
|
410
|
+
}, '')
|
|
411
|
+
.replace(/\s+([,.;:!?])/g, '$1')
|
|
412
|
+
.replace(/(\d)\s+,/g, '$1,')
|
|
413
|
+
.replace(/\s+/g, ' ')
|
|
414
|
+
.trim();
|
|
415
|
+
}
|
|
416
|
+
|
|
376
417
|
export function normalizeComparableMessageContent(text: string): string {
|
|
377
|
-
|
|
418
|
+
const lines = String(text || '')
|
|
419
|
+
.split(/\r\n|\n|\r/g)
|
|
420
|
+
.map((line) => line.trim())
|
|
421
|
+
.filter(Boolean);
|
|
422
|
+
|
|
423
|
+
if (lines.length === 0) return '';
|
|
424
|
+
if (shouldReflowComparableMessageLines(lines)) {
|
|
425
|
+
return joinComparableMessageLines(lines);
|
|
426
|
+
}
|
|
427
|
+
return lines.join(' ')
|
|
378
428
|
.replace(/\s+/g, ' ')
|
|
379
429
|
.trim();
|
|
380
430
|
}
|
|
@@ -414,10 +464,6 @@ export function getLastUserPromptText(messages: Array<{ role?: string; content?:
|
|
|
414
464
|
return '';
|
|
415
465
|
}
|
|
416
466
|
|
|
417
|
-
export function looksLikeConfirmOnlyLabel(label: string): boolean {
|
|
418
|
-
return /^(?:continue|confirm|ok|yes|trust|proceed|enter)$/i.test(String(label || '').trim());
|
|
419
|
-
}
|
|
420
|
-
|
|
421
467
|
function parsePatternEntry(x: unknown): RegExp | null {
|
|
422
468
|
if (x instanceof RegExp) return x;
|
|
423
469
|
if (x && typeof x === 'object' && typeof (x as { source?: string }).source === 'string') {
|
|
@@ -1255,26 +1255,24 @@ export async function handleResolveAction(h: CommandHelpers, args: any): Promise
|
|
|
1255
1255
|
? 'waiting_approval'
|
|
1256
1256
|
: status?.status;
|
|
1257
1257
|
LOG.info('Command', `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || '')} rawStatus=${String(status?.status || '')} effectiveStatus=${String(effectiveStatus || '')} statusModal=${statusModal ? 'yes' : 'no'} surfacedModal=${surfacedModal ? 'yes' : 'no'} instance=${targetInstance ? 'yes' : 'no'}`);
|
|
1258
|
-
if (
|
|
1258
|
+
if (!effectiveModal) {
|
|
1259
1259
|
return { success: false, error: 'Not in approval state' };
|
|
1260
1260
|
}
|
|
1261
|
-
const buttons: string[] = effectiveModal
|
|
1262
|
-
// Resolve button index: explicit buttonIndex arg →
|
|
1261
|
+
const buttons: string[] = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
|
|
1262
|
+
// Resolve button index: explicit buttonIndex arg → exact text match → explicit action mapping
|
|
1263
1263
|
let buttonIndex = typeof args?.buttonIndex === 'number' ? args.buttonIndex : -1;
|
|
1264
|
-
if (buttonIndex < 0) {
|
|
1264
|
+
if (buttonIndex < 0 && button) {
|
|
1265
1265
|
const btnLower = button.toLowerCase();
|
|
1266
1266
|
buttonIndex = buttons.findIndex(b => b.toLowerCase().includes(btnLower));
|
|
1267
1267
|
}
|
|
1268
|
+
if (buttonIndex < 0 && (action === 'reject' || action === 'deny')) {
|
|
1269
|
+
buttonIndex = buttons.findIndex(b => /deny|reject|no/i.test(b));
|
|
1270
|
+
}
|
|
1271
|
+
if (buttonIndex < 0 && (action === 'always' || /always/i.test(button))) {
|
|
1272
|
+
buttonIndex = buttons.findIndex(b => /always/i.test(b));
|
|
1273
|
+
}
|
|
1268
1274
|
if (buttonIndex < 0) {
|
|
1269
|
-
|
|
1270
|
-
buttonIndex = buttons.findIndex(b => /deny|reject|no/i.test(b));
|
|
1271
|
-
if (buttonIndex < 0) buttonIndex = buttons.length - 1;
|
|
1272
|
-
} else if (action === 'always' || /always/i.test(button)) {
|
|
1273
|
-
buttonIndex = buttons.findIndex(b => /always/i.test(b));
|
|
1274
|
-
if (buttonIndex < 0) buttonIndex = 1;
|
|
1275
|
-
} else {
|
|
1276
|
-
buttonIndex = 0; // approve → first option (default selected)
|
|
1277
|
-
}
|
|
1275
|
+
return { success: false, error: 'Approval action did not match any visible button' };
|
|
1278
1276
|
}
|
|
1279
1277
|
if (typeof adapter.resolveModal === 'function') {
|
|
1280
1278
|
adapter.resolveModal(buttonIndex);
|