@adhdev/daemon-core 0.9.47 → 0.9.49
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-adapter-types.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +1 -0
- package/dist/commands/chat-commands.d.ts +9 -0
- package/dist/commands/upgrade-helper.d.ts +12 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +405 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +403 -29
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-script-results.d.ts +1 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapter-types.ts +1 -0
- package/src/cli-adapters/provider-cli-adapter.ts +82 -0
- package/src/cli-adapters/provider-cli-shared.ts +6 -1
- package/src/commands/chat-commands.ts +267 -2
- package/src/commands/cli-manager.ts +4 -1
- package/src/commands/handler.ts +1 -0
- package/src/commands/router.ts +5 -6
- package/src/commands/stream-commands.ts +5 -0
- package/src/commands/upgrade-helper.d.ts +26 -0
- package/src/commands/upgrade-helper.ts +63 -19
- package/src/detection/cli-detector.ts +5 -1
- package/src/index.d.ts +2 -2
- package/src/index.ts +10 -7
- package/src/launch.ts +2 -2
- package/src/providers/acp-provider-instance.ts +1 -0
- package/src/providers/cli-provider-instance.ts +5 -0
- package/src/providers/cli-script-results.ts +5 -2
package/package.json
CHANGED
package/src/cli-adapter-types.ts
CHANGED
|
@@ -41,6 +41,7 @@ export interface CliAdapter {
|
|
|
41
41
|
sendMessage(text: string): Promise<void>;
|
|
42
42
|
getStatus(): CliAdapterStatus;
|
|
43
43
|
getScriptParsedStatus?(): unknown;
|
|
44
|
+
getDebugSnapshot?(): unknown;
|
|
44
45
|
invokeScript?(scriptName: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
45
46
|
getPartialResponse(): string;
|
|
46
47
|
saveAndStop?(): Promise<void>;
|
|
@@ -2545,6 +2545,88 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
2545
2545
|
return this.responseBuffer;
|
|
2546
2546
|
}
|
|
2547
2547
|
|
|
2548
|
+
getDebugSnapshot(): Record<string, unknown> {
|
|
2549
|
+
const screenText = this.readTerminalScreenText();
|
|
2550
|
+
const parsedResult = this.parsedStatusCache?.result && typeof this.parsedStatusCache.result === 'object'
|
|
2551
|
+
? this.parsedStatusCache.result as Record<string, any>
|
|
2552
|
+
: null;
|
|
2553
|
+
return {
|
|
2554
|
+
cliType: this.cliType,
|
|
2555
|
+
cliName: this.cliName,
|
|
2556
|
+
workingDir: this.workingDir,
|
|
2557
|
+
currentStatus: this.currentStatus,
|
|
2558
|
+
ready: this.ready,
|
|
2559
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
2560
|
+
activeModal: this.activeModal,
|
|
2561
|
+
parseErrorMessage: this.parseErrorMessage,
|
|
2562
|
+
messageCounts: {
|
|
2563
|
+
committed: this.committedMessages.length,
|
|
2564
|
+
structured: this.structuredMessages.length,
|
|
2565
|
+
visible: this.messages.length,
|
|
2566
|
+
parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : undefined,
|
|
2567
|
+
},
|
|
2568
|
+
buffers: {
|
|
2569
|
+
accumulatedLength: this.accumulatedBuffer.length,
|
|
2570
|
+
accumulatedRawLength: this.accumulatedRawBuffer.length,
|
|
2571
|
+
recentOutputLength: this.recentOutputBuffer.length,
|
|
2572
|
+
responseLength: this.responseBuffer.length,
|
|
2573
|
+
startupLength: this.startupBuffer.length,
|
|
2574
|
+
accumulatedTail: this.accumulatedBuffer.slice(-24_000),
|
|
2575
|
+
accumulatedRawTail: this.accumulatedRawBuffer.slice(-24_000),
|
|
2576
|
+
recentOutputTail: this.recentOutputBuffer.slice(-12_000),
|
|
2577
|
+
responseTail: this.responseBuffer.slice(-12_000),
|
|
2578
|
+
},
|
|
2579
|
+
terminal: {
|
|
2580
|
+
screenText,
|
|
2581
|
+
lastScreenSnapshot: this.lastScreenSnapshot,
|
|
2582
|
+
lastScreenText: this.lastScreenText,
|
|
2583
|
+
lastOutputAt: this.lastOutputAt,
|
|
2584
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
2585
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
2586
|
+
lastScreenSnapshotReadAt: this.lastScreenSnapshotReadAt,
|
|
2587
|
+
},
|
|
2588
|
+
parser: {
|
|
2589
|
+
scriptNames: listCliScriptNames(this.cliScripts),
|
|
2590
|
+
traceSessionId: this.traceSessionId,
|
|
2591
|
+
traceSeq: this.traceSeq,
|
|
2592
|
+
currentTurnScope: this.currentTurnScope,
|
|
2593
|
+
parsedStatusCache: parsedResult
|
|
2594
|
+
? {
|
|
2595
|
+
id: parsedResult.id,
|
|
2596
|
+
status: parsedResult.status,
|
|
2597
|
+
title: parsedResult.title,
|
|
2598
|
+
providerSessionId: parsedResult.providerSessionId,
|
|
2599
|
+
transcriptAuthority: parsedResult.transcriptAuthority,
|
|
2600
|
+
coverage: parsedResult.coverage,
|
|
2601
|
+
messageCount: Array.isArray(parsedResult.messages) ? parsedResult.messages.length : undefined,
|
|
2602
|
+
activeModal: parsedResult.activeModal,
|
|
2603
|
+
}
|
|
2604
|
+
: null,
|
|
2605
|
+
pendingScriptStatus: this.pendingScriptStatus,
|
|
2606
|
+
pendingScriptStatusSince: this.pendingScriptStatusSince,
|
|
2607
|
+
},
|
|
2608
|
+
runtimeMetadata: this.getRuntimeMetadata(),
|
|
2609
|
+
statusHistory: this.statusHistory.slice(-80),
|
|
2610
|
+
traceEntries: this.traceEntries.slice(-120),
|
|
2611
|
+
timing: {
|
|
2612
|
+
spawnAt: this.spawnAt,
|
|
2613
|
+
startupFirstOutputAt: this.startupFirstOutputAt,
|
|
2614
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
2615
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
2616
|
+
responseEpoch: this.responseEpoch,
|
|
2617
|
+
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
2618
|
+
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
2619
|
+
committedMessagesChangedAt: this.committedMessagesChangedAt,
|
|
2620
|
+
},
|
|
2621
|
+
finish: {
|
|
2622
|
+
idleFinishCandidate: this.idleFinishCandidate,
|
|
2623
|
+
finishRetryCount: this.finishRetryCount,
|
|
2624
|
+
submitRetryUsed: this.submitRetryUsed,
|
|
2625
|
+
submitRetryPromptSnippet: this.submitRetryPromptSnippet,
|
|
2626
|
+
},
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2548
2630
|
getRuntimeMetadata(): PtyRuntimeMetadata | null {
|
|
2549
2631
|
if (!this.ptyProcess || typeof this.ptyProcess.getMetadata !== 'function') return null;
|
|
2550
2632
|
return this.ptyProcess.getMetadata();
|
|
@@ -277,7 +277,12 @@ export function findBinary(name: string): string {
|
|
|
277
277
|
const isWin = os.platform() === 'win32';
|
|
278
278
|
try {
|
|
279
279
|
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
280
|
-
return execSync(cmd, {
|
|
280
|
+
return execSync(cmd, {
|
|
281
|
+
encoding: 'utf-8',
|
|
282
|
+
timeout: 5000,
|
|
283
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
284
|
+
...(isWin ? { windowsHide: true } : {}),
|
|
285
|
+
}).trim().split('\n')[0].trim();
|
|
281
286
|
} catch {
|
|
282
287
|
return isWin ? `${trimmed}.cmd` : trimmed;
|
|
283
288
|
}
|
|
@@ -10,8 +10,8 @@ import { assertProviderSupportsDeclaredInput, assertTextOnlyInput } from '../pro
|
|
|
10
10
|
import { validateReadChatResultPayload } from '../providers/read-chat-contract.js';
|
|
11
11
|
import type { ProviderInstance } from '../providers/provider-instance.js';
|
|
12
12
|
import { readProviderChatHistory } from '../config/chat-history.js';
|
|
13
|
-
import { LOG } from '../logging/logger.js';
|
|
14
|
-
import { recordDebugTrace } from '../logging/debug-trace.js';
|
|
13
|
+
import { LOG, getRecentLogs } from '../logging/logger.js';
|
|
14
|
+
import { getRecentDebugTrace, recordDebugTrace } from '../logging/debug-trace.js';
|
|
15
15
|
import { buildChatMessageSignature } from '../chat/chat-signatures.js';
|
|
16
16
|
import type { ChatMessage } from '../types.js';
|
|
17
17
|
import type { ReadChatCursor, ReadChatSyncMode, SessionTransport } from '../shared-types.js';
|
|
@@ -489,6 +489,271 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
|
|
|
489
489
|
};
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
+
|
|
493
|
+
interface DebugSanitizeOptions {
|
|
494
|
+
maxDepth?: number;
|
|
495
|
+
maxArrayLength?: number;
|
|
496
|
+
maxObjectKeys?: number;
|
|
497
|
+
maxStringLength?: number;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const DEFAULT_DEBUG_SANITIZE_OPTIONS: Required<DebugSanitizeOptions> = {
|
|
501
|
+
maxDepth: 8,
|
|
502
|
+
maxArrayLength: 80,
|
|
503
|
+
maxObjectKeys: 120,
|
|
504
|
+
maxStringLength: 16_000,
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
const SECRET_KEY_PATTERN = /(?:token|secret|password|passwd|authorization|cookie|api[_-]?key|access[_-]?key|refresh[_-]?token|client[_-]?secret|private[_-]?key)/i;
|
|
508
|
+
|
|
509
|
+
function truncateDebugString(value: string, maxLength: number): string {
|
|
510
|
+
if (value.length <= maxLength) return value;
|
|
511
|
+
return `${value.slice(0, maxLength)}…[truncated ${value.length - maxLength} chars]`;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function redactDebugSecrets(value: string): string {
|
|
515
|
+
return value
|
|
516
|
+
.replace(/(Authorization\s*:\s*Bearer\s+)[^\s'"`]+/gi, '$1[REDACTED:bearer]')
|
|
517
|
+
.replace(/(Bearer\s+)[A-Za-z0-9._~+\/-]{16,}=*/gi, '$1[REDACTED:bearer]')
|
|
518
|
+
.replace(/\b(?:gh[pousr]|github_pat)_[A-Za-z0-9_]{20,}\b/g, '[REDACTED:github-token]')
|
|
519
|
+
.replace(/\bsk-[A-Za-z0-9_-]{16,}\b/g, '[REDACTED:api-key]')
|
|
520
|
+
.replace(/\bxox[baprs]-[A-Za-z0-9-]{12,}\b/g, '[REDACTED:slack-token]')
|
|
521
|
+
.replace(/\b(?:adk|adm)_[A-Za-z0-9_-]{16,}\b/g, '[REDACTED:adhdev-token]')
|
|
522
|
+
.replace(/((?:api[_-]?key|token|secret|password|passwd|client[_-]?secret)\s*[:=]\s*)[^\s,'"`}&]+/gi, '$1[REDACTED:secret]')
|
|
523
|
+
.replace(/([?&](?:api[_-]?key|token|secret|password|client_secret)=)[^&#\s]+/gi, '$1[REDACTED:secret]');
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
export function sanitizeDebugBundleValue(
|
|
527
|
+
value: unknown,
|
|
528
|
+
options: DebugSanitizeOptions = {},
|
|
529
|
+
depth = 0,
|
|
530
|
+
keyHint = '',
|
|
531
|
+
): unknown {
|
|
532
|
+
const normalizedOptions = { ...DEFAULT_DEBUG_SANITIZE_OPTIONS, ...options };
|
|
533
|
+
if (value === null || value === undefined) return value;
|
|
534
|
+
if (typeof value === 'number' || typeof value === 'boolean') return value;
|
|
535
|
+
if (typeof value === 'bigint') return String(value);
|
|
536
|
+
if (typeof value === 'string') {
|
|
537
|
+
if (SECRET_KEY_PATTERN.test(keyHint) && value.trim()) return '[REDACTED:secret-field]';
|
|
538
|
+
return truncateDebugString(redactDebugSecrets(value), normalizedOptions.maxStringLength);
|
|
539
|
+
}
|
|
540
|
+
if (typeof value === 'function') return `[Function ${value.name || 'anonymous'}]`;
|
|
541
|
+
if (typeof value !== 'object') return String(value);
|
|
542
|
+
if (depth >= normalizedOptions.maxDepth) return '[MaxDepth]';
|
|
543
|
+
|
|
544
|
+
if (Array.isArray(value)) {
|
|
545
|
+
const items = value
|
|
546
|
+
.slice(0, normalizedOptions.maxArrayLength)
|
|
547
|
+
.map((item) => sanitizeDebugBundleValue(item, normalizedOptions, depth + 1, keyHint));
|
|
548
|
+
if (value.length > normalizedOptions.maxArrayLength) {
|
|
549
|
+
items.push(`[truncated ${value.length - normalizedOptions.maxArrayLength} items]`);
|
|
550
|
+
}
|
|
551
|
+
return items;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const record = value as Record<string, unknown>;
|
|
555
|
+
const result: Record<string, unknown> = {};
|
|
556
|
+
const entries = Object.entries(record).slice(0, normalizedOptions.maxObjectKeys);
|
|
557
|
+
for (const [key, item] of entries) {
|
|
558
|
+
result[key] = sanitizeDebugBundleValue(item, normalizedOptions, depth + 1, key);
|
|
559
|
+
}
|
|
560
|
+
const remaining = Object.keys(record).length - entries.length;
|
|
561
|
+
if (remaining > 0) result.__truncatedKeys = remaining;
|
|
562
|
+
return result;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function summarizeProviderForDebug(provider: ProviderModule | undefined): Record<string, unknown> | null {
|
|
566
|
+
if (!provider) return null;
|
|
567
|
+
const scripts = provider.scripts && typeof provider.scripts === 'object'
|
|
568
|
+
? Object.keys(provider.scripts)
|
|
569
|
+
: [];
|
|
570
|
+
const controls = Array.isArray((provider as any).controls)
|
|
571
|
+
? (provider as any).controls.map((control: any) => ({
|
|
572
|
+
id: control?.id,
|
|
573
|
+
label: control?.label,
|
|
574
|
+
type: control?.type,
|
|
575
|
+
settingKey: control?.settingKey,
|
|
576
|
+
invokeScript: control?.invokeScript,
|
|
577
|
+
listScript: control?.listScript,
|
|
578
|
+
location: control?.location,
|
|
579
|
+
}))
|
|
580
|
+
: [];
|
|
581
|
+
return {
|
|
582
|
+
type: provider.type,
|
|
583
|
+
name: provider.name,
|
|
584
|
+
category: provider.category,
|
|
585
|
+
version: (provider as any).version,
|
|
586
|
+
canonicalHistory: provider.canonicalHistory,
|
|
587
|
+
historyBehavior: provider.historyBehavior,
|
|
588
|
+
webviewMatchText: provider.webviewMatchText,
|
|
589
|
+
scriptNames: scripts,
|
|
590
|
+
controls,
|
|
591
|
+
resume: provider.resume,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function summarizeSessionForDebug(session: any): Record<string, unknown> | null {
|
|
596
|
+
if (!session || typeof session !== 'object') return null;
|
|
597
|
+
return {
|
|
598
|
+
sessionId: session.sessionId,
|
|
599
|
+
instanceKey: session.instanceKey,
|
|
600
|
+
adapterKey: session.adapterKey,
|
|
601
|
+
providerType: session.providerType,
|
|
602
|
+
providerName: session.providerName,
|
|
603
|
+
transport: session.transport,
|
|
604
|
+
kind: session.kind,
|
|
605
|
+
cdpManagerKey: session.cdpManagerKey,
|
|
606
|
+
parentSessionId: session.parentSessionId,
|
|
607
|
+
providerSessionId: session.providerSessionId,
|
|
608
|
+
workspace: session.workspace,
|
|
609
|
+
title: session.title,
|
|
610
|
+
status: session.status,
|
|
611
|
+
mode: session.mode,
|
|
612
|
+
capabilities: session.capabilities,
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function summarizeStateForDebug(state: any): Record<string, unknown> | null {
|
|
617
|
+
if (!state || typeof state !== 'object') return null;
|
|
618
|
+
const activeChat = state.activeChat && typeof state.activeChat === 'object' ? state.activeChat : null;
|
|
619
|
+
return {
|
|
620
|
+
type: state.type,
|
|
621
|
+
name: state.name,
|
|
622
|
+
category: state.category,
|
|
623
|
+
status: state.status,
|
|
624
|
+
instanceId: state.instanceId,
|
|
625
|
+
providerSessionId: state.providerSessionId,
|
|
626
|
+
title: state.title,
|
|
627
|
+
transport: state.transport,
|
|
628
|
+
mode: state.mode,
|
|
629
|
+
workspace: state.workspace,
|
|
630
|
+
runtime: state.runtime,
|
|
631
|
+
errorMessage: state.errorMessage,
|
|
632
|
+
errorReason: state.errorReason,
|
|
633
|
+
activeChat: activeChat ? {
|
|
634
|
+
status: activeChat.status,
|
|
635
|
+
title: activeChat.title,
|
|
636
|
+
messageCount: Array.isArray(activeChat.messages) ? activeChat.messages.length : undefined,
|
|
637
|
+
activeModal: activeChat.activeModal,
|
|
638
|
+
messagesTail: Array.isArray(activeChat.messages) ? activeChat.messages.slice(-10) : undefined,
|
|
639
|
+
} : null,
|
|
640
|
+
controlValues: state.controlValues,
|
|
641
|
+
summaryMetadata: state.summaryMetadata,
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function buildDebugBundleText(bundle: Record<string, unknown>): string {
|
|
646
|
+
return [
|
|
647
|
+
'# ADHDev Chat Debug Bundle',
|
|
648
|
+
'',
|
|
649
|
+
'```json',
|
|
650
|
+
JSON.stringify(bundle, null, 2),
|
|
651
|
+
'```',
|
|
652
|
+
].join('\n');
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export async function handleGetChatDebugBundle(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
656
|
+
const provider = h.getProvider(args?.agentType);
|
|
657
|
+
const transport = getTargetTransport(h, provider);
|
|
658
|
+
const targetSessionId = typeof args?.targetSessionId === 'string' ? args.targetSessionId.trim() : '';
|
|
659
|
+
const providerType = provider?.type || getCurrentProviderType(h, args?.agentType || '');
|
|
660
|
+
const adapter = isCliLikeTransport(transport) ? getTargetedCliAdapter(h, args, provider?.type) : null;
|
|
661
|
+
const targetInstance = getTargetInstance(h, args);
|
|
662
|
+
|
|
663
|
+
let adapterStatus: unknown = null;
|
|
664
|
+
let parsedStatus: unknown = null;
|
|
665
|
+
let adapterDebugSnapshot: unknown = null;
|
|
666
|
+
let partialResponse = '';
|
|
667
|
+
if (adapter) {
|
|
668
|
+
try { adapterStatus = adapter.getStatus?.(); } catch (error: any) { adapterStatus = { error: error?.message || String(error) }; }
|
|
669
|
+
try { parsedStatus = typeof adapter.getScriptParsedStatus === 'function' ? parseMaybeJson(adapter.getScriptParsedStatus()) : null; } catch (error: any) { parsedStatus = { error: error?.message || String(error) }; }
|
|
670
|
+
try { adapterDebugSnapshot = typeof adapter.getDebugSnapshot === 'function' ? adapter.getDebugSnapshot() : null; } catch (error: any) { adapterDebugSnapshot = { error: error?.message || String(error) }; }
|
|
671
|
+
try { partialResponse = adapter.getPartialResponse?.() || ''; } catch { partialResponse = ''; }
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
let instanceState: unknown = null;
|
|
675
|
+
if (targetInstance?.getState) {
|
|
676
|
+
try { instanceState = summarizeStateForDebug(targetInstance.getState()); } catch (error: any) { instanceState = { error: error?.message || String(error) }; }
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
let readChat: unknown = null;
|
|
680
|
+
try {
|
|
681
|
+
const readResult = await handleReadChat(h, { ...args, tailLimit: Math.max(1, Math.min(40, Number(args?.tailLimit || 40))) });
|
|
682
|
+
readChat = readResult.success
|
|
683
|
+
? {
|
|
684
|
+
success: true,
|
|
685
|
+
status: readResult.status,
|
|
686
|
+
title: readResult.title,
|
|
687
|
+
totalMessages: readResult.totalMessages,
|
|
688
|
+
returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : undefined,
|
|
689
|
+
syncMode: readResult.syncMode,
|
|
690
|
+
replaceFrom: readResult.replaceFrom,
|
|
691
|
+
lastMessageSignature: readResult.lastMessageSignature,
|
|
692
|
+
providerSessionId: readResult.providerSessionId,
|
|
693
|
+
transcriptAuthority: readResult.transcriptAuthority,
|
|
694
|
+
coverage: readResult.coverage,
|
|
695
|
+
activeModal: readResult.activeModal,
|
|
696
|
+
messagesTail: Array.isArray(readResult.messages) ? readResult.messages.slice(-20) : [],
|
|
697
|
+
debugReadChat: readResult.debugReadChat,
|
|
698
|
+
}
|
|
699
|
+
: { success: false, error: readResult.error };
|
|
700
|
+
} catch (error: any) {
|
|
701
|
+
readChat = { success: false, error: error?.message || String(error) };
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const cdp = h.getCdp();
|
|
705
|
+
const rawBundle: Record<string, unknown> = {
|
|
706
|
+
version: 1,
|
|
707
|
+
createdAt: new Date().toISOString(),
|
|
708
|
+
target: {
|
|
709
|
+
targetSessionId,
|
|
710
|
+
providerType,
|
|
711
|
+
transport,
|
|
712
|
+
routeManagerKey: h.currentManagerKey,
|
|
713
|
+
currentIdeType: h.currentIdeType,
|
|
714
|
+
},
|
|
715
|
+
session: summarizeSessionForDebug(h.currentSession),
|
|
716
|
+
provider: summarizeProviderForDebug(provider),
|
|
717
|
+
daemon: {
|
|
718
|
+
pid: process.pid,
|
|
719
|
+
platform: process.platform,
|
|
720
|
+
nodeVersion: process.version,
|
|
721
|
+
cwd: process.cwd(),
|
|
722
|
+
},
|
|
723
|
+
cdp: {
|
|
724
|
+
requested: !!cdp,
|
|
725
|
+
connected: !!cdp?.isConnected,
|
|
726
|
+
managerKey: getCurrentManagerKey(h),
|
|
727
|
+
},
|
|
728
|
+
instanceState,
|
|
729
|
+
cli: adapter ? {
|
|
730
|
+
cliType: adapter.cliType,
|
|
731
|
+
cliName: adapter.cliName,
|
|
732
|
+
workingDir: adapter.workingDir,
|
|
733
|
+
status: (adapterStatus as any)?.status,
|
|
734
|
+
activeModal: (adapterStatus as any)?.activeModal,
|
|
735
|
+
messageCount: Array.isArray((adapterStatus as any)?.messages) ? (adapterStatus as any).messages.length : undefined,
|
|
736
|
+
messagesTail: Array.isArray((adapterStatus as any)?.messages) ? (adapterStatus as any).messages.slice(-20) : undefined,
|
|
737
|
+
parsedStatus,
|
|
738
|
+
partialResponse,
|
|
739
|
+
ready: typeof adapter.isReady === 'function' ? adapter.isReady() : undefined,
|
|
740
|
+
processing: typeof adapter.isProcessing === 'function' ? adapter.isProcessing() : undefined,
|
|
741
|
+
debugSnapshot: adapterDebugSnapshot,
|
|
742
|
+
} : null,
|
|
743
|
+
readChat,
|
|
744
|
+
frontend: args?.frontendSnapshot && typeof args.frontendSnapshot === 'object' ? args.frontendSnapshot : null,
|
|
745
|
+
recentLogs: getRecentLogs(80, 'debug'),
|
|
746
|
+
recentDebugTrace: getRecentDebugTrace({ limit: 120 }),
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
const bundle = sanitizeDebugBundleValue(rawBundle) as Record<string, unknown>;
|
|
750
|
+
return {
|
|
751
|
+
success: true,
|
|
752
|
+
bundle,
|
|
753
|
+
text: buildDebugBundleText(bundle),
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
|
|
492
757
|
function didProviderConfirmSend(result: any): boolean {
|
|
493
758
|
const parsed = parseMaybeJson(result);
|
|
494
759
|
if (parsed === true) return true;
|
|
@@ -52,7 +52,10 @@ function commandExists(command: string): boolean {
|
|
|
52
52
|
return existsSync(expandExecutable(trimmed));
|
|
53
53
|
}
|
|
54
54
|
try {
|
|
55
|
-
execFileSync(process.platform === 'win32' ? 'where' : 'which', [trimmed], {
|
|
55
|
+
execFileSync(process.platform === 'win32' ? 'where' : 'which', [trimmed], {
|
|
56
|
+
stdio: 'ignore',
|
|
57
|
+
...(process.platform === 'win32' ? { windowsHide: true } : {}),
|
|
58
|
+
});
|
|
56
59
|
return true;
|
|
57
60
|
} catch {
|
|
58
61
|
return false;
|
package/src/commands/handler.ts
CHANGED
|
@@ -431,6 +431,7 @@ export class DaemonCommandHandler implements CommandHelpers {
|
|
|
431
431
|
switch (cmd) {
|
|
432
432
|
// ─── Chat commands (chat-commands.ts) ───────────────
|
|
433
433
|
case 'read_chat': return Chat.handleReadChat(this, args);
|
|
434
|
+
case 'get_chat_debug_bundle': return Chat.handleGetChatDebugBundle(this, args);
|
|
434
435
|
case 'chat_history': return Chat.handleChatHistory(this, args);
|
|
435
436
|
case 'send_chat': return Chat.handleSendChat(this, args);
|
|
436
437
|
case 'list_chats': return Chat.handleListChats(this, args);
|
package/src/commands/router.ts
CHANGED
|
@@ -36,7 +36,7 @@ import { getSessionHostSurfaceKind, partitionSessionHostRecords } from '../sessi
|
|
|
36
36
|
import { buildSessionEntries } from '../status/builders.js';
|
|
37
37
|
import { buildMachineInfo, buildStatusSnapshot } from '../status/snapshot.js';
|
|
38
38
|
import { getSessionCompletionMarker } from '../status/snapshot.js';
|
|
39
|
-
import { spawnDetachedDaemonUpgradeHelper } from './upgrade-helper.js';
|
|
39
|
+
import { execNpmCommandSync, resolveCurrentGlobalInstallSurface, spawnDetachedDaemonUpgradeHelper } from './upgrade-helper.js';
|
|
40
40
|
import * as fs from 'fs';
|
|
41
41
|
|
|
42
42
|
// ─── Types ───
|
|
@@ -847,23 +847,22 @@ export class DaemonCommandRouter {
|
|
|
847
847
|
case 'daemon_upgrade': {
|
|
848
848
|
LOG.info('Upgrade', 'Remote upgrade requested from dashboard');
|
|
849
849
|
try {
|
|
850
|
-
const { execSync } = await import('child_process');
|
|
851
|
-
|
|
852
850
|
// Detect package name for upgrade
|
|
853
851
|
const isStandalone = this.deps.packageName === '@adhdev/daemon-standalone'
|
|
854
852
|
|| process.argv[1]?.includes('daemon-standalone');
|
|
855
853
|
const pkgName = isStandalone ? '@adhdev/daemon-standalone' : 'adhdev';
|
|
854
|
+
const npmSurface = resolveCurrentGlobalInstallSurface({ packageName: pkgName });
|
|
856
855
|
|
|
857
856
|
// Check latest version
|
|
858
|
-
const latest =
|
|
857
|
+
const latest = String(execNpmCommandSync(['view', pkgName, 'version'], { encoding: 'utf-8', timeout: 10000 }, npmSurface)).trim();
|
|
859
858
|
LOG.info('Upgrade', `Latest ${pkgName}: v${latest}`);
|
|
860
859
|
let currentInstalled: string | null = null;
|
|
861
860
|
try {
|
|
862
|
-
const currentJson =
|
|
861
|
+
const currentJson = String(execNpmCommandSync(['ls', '-g', pkgName, '--depth=0', '--json'], {
|
|
863
862
|
encoding: 'utf-8',
|
|
864
863
|
timeout: 10000,
|
|
865
864
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
866
|
-
}).trim();
|
|
865
|
+
}, npmSurface)).trim();
|
|
867
866
|
const parsed = JSON.parse(currentJson);
|
|
868
867
|
currentInstalled = parsed?.dependencies?.[pkgName]?.version || null;
|
|
869
868
|
} catch {
|
|
@@ -343,7 +343,12 @@ async function executeProviderScript(h: CommandHelpers, args: any, scriptName: s
|
|
|
343
343
|
if (cliCommand?.type === 'send_message' && cliCommand.text) {
|
|
344
344
|
await adapter.sendMessage(cliCommand.text);
|
|
345
345
|
} else if (cliCommand?.type === 'pty_write' && cliCommand.text && adapter.writeRaw) {
|
|
346
|
+
const enterCount = cliCommand.enterCount || 1;
|
|
346
347
|
await adapter.writeRaw(cliCommand.text + '\r');
|
|
348
|
+
for (let i = 1; i < enterCount; i += 1) {
|
|
349
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
350
|
+
await adapter.writeRaw('\r');
|
|
351
|
+
}
|
|
347
352
|
}
|
|
348
353
|
applyProviderPatch(h, args, parsed.payload);
|
|
349
354
|
return {
|
|
@@ -6,5 +6,31 @@ export interface DaemonUpgradeHelperPayload {
|
|
|
6
6
|
cwd?: string;
|
|
7
7
|
sessionHostAppName?: string;
|
|
8
8
|
}
|
|
9
|
+
export interface CurrentGlobalInstallSurface {
|
|
10
|
+
npmExecutable: string;
|
|
11
|
+
npmArgsPrefix?: string[];
|
|
12
|
+
packageRoot: string | null;
|
|
13
|
+
installPrefix: string | null;
|
|
14
|
+
execOptions?: { shell: boolean };
|
|
15
|
+
}
|
|
16
|
+
export interface PinnedGlobalInstallCommand {
|
|
17
|
+
command: string;
|
|
18
|
+
args: string[];
|
|
19
|
+
surface: CurrentGlobalInstallSurface;
|
|
20
|
+
execOptions: { shell: boolean };
|
|
21
|
+
}
|
|
22
|
+
export declare function resolveCurrentGlobalInstallSurface(options: {
|
|
23
|
+
packageName: string;
|
|
24
|
+
currentCliPath?: string;
|
|
25
|
+
nodeExecutable?: string;
|
|
26
|
+
platform?: NodeJS.Platform;
|
|
27
|
+
}): CurrentGlobalInstallSurface;
|
|
28
|
+
export declare function buildPinnedGlobalInstallCommand(options: {
|
|
29
|
+
packageName: string;
|
|
30
|
+
targetVersion: string;
|
|
31
|
+
currentCliPath?: string;
|
|
32
|
+
nodeExecutable?: string;
|
|
33
|
+
platform?: NodeJS.Platform;
|
|
34
|
+
}): PinnedGlobalInstallCommand;
|
|
9
35
|
export declare function spawnDetachedDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): void;
|
|
10
36
|
export declare function maybeRunDaemonUpgradeHelperFromEnv(): Promise<boolean>;
|