@adhdev/daemon-core 0.7.35 → 0.7.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/index.d.mts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +637 -253
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +637 -255
- package/dist/index.mjs.map +1 -1
- package/dist/{normalize-auJAPmKy.d.mts → normalize-DVI4Lo5I.d.mts} +63 -1
- package/dist/{normalize-auJAPmKy.d.ts → normalize-DVI4Lo5I.d.ts} +63 -1
- package/dist/status/normalize.d.mts +1 -1
- package/dist/status/normalize.d.ts +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/manager.ts +14 -1
- package/src/agent-stream/provider-adapter.ts +45 -3
- package/src/agent-stream/types.ts +4 -0
- package/src/cli-adapters/terminal-screen.ts +15 -0
- package/src/commands/cli-manager.ts +35 -0
- package/src/commands/router.ts +44 -1
- package/src/commands/workspace-commands.ts +2 -1
- package/src/config/config.d.ts +4 -0
- package/src/config/config.ts +9 -1
- package/src/config/recent-activity.ts +83 -0
- package/src/config/workspaces.d.ts +3 -1
- package/src/config/workspaces.ts +15 -1
- package/src/index.ts +16 -0
- package/src/providers/acp-provider-instance.ts +5 -0
- package/src/providers/cli-provider-instance.ts +2 -0
- package/src/providers/contracts.ts +94 -0
- package/src/providers/extension-provider-instance.ts +4 -0
- package/src/providers/ide-provider-instance.ts +2 -0
- package/src/providers/provider-instance.ts +5 -1
- package/src/shared-types.d.ts +35 -0
- package/src/shared-types.ts +70 -0
- package/src/status/builders.ts +90 -1
- package/src/status/reporter.ts +8 -0
- package/src/status/snapshot.ts +162 -0
|
@@ -469,6 +469,31 @@ interface WorkspaceActivityEntry {
|
|
|
469
469
|
}
|
|
470
470
|
declare function getWorkspaceActivity(config: ADHDevConfig, limit?: number): WorkspaceActivityEntry[];
|
|
471
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Unified recent activity — machine-facing "pick up where you left off".
|
|
474
|
+
*
|
|
475
|
+
* Unlike cliHistory or workspaceActivity, this is task/session oriented:
|
|
476
|
+
* - one normalized row shape for IDE / CLI / ACP
|
|
477
|
+
* - deduped by kind + providerType + workspace
|
|
478
|
+
* - optionally linked to a live sessionId when known
|
|
479
|
+
*/
|
|
480
|
+
|
|
481
|
+
interface RecentActivityEntry {
|
|
482
|
+
id: string;
|
|
483
|
+
kind: 'ide' | 'cli' | 'acp';
|
|
484
|
+
providerType: string;
|
|
485
|
+
providerName: string;
|
|
486
|
+
workspace?: string | null;
|
|
487
|
+
currentModel?: string;
|
|
488
|
+
sessionId?: string | null;
|
|
489
|
+
title?: string;
|
|
490
|
+
lastUsedAt: number;
|
|
491
|
+
}
|
|
492
|
+
declare function appendRecentActivity(config: ADHDevConfig, entry: Omit<RecentActivityEntry, 'id' | 'lastUsedAt'> & {
|
|
493
|
+
lastUsedAt?: number;
|
|
494
|
+
}): ADHDevConfig;
|
|
495
|
+
declare function getRecentActivity(config: ADHDevConfig, limit?: number): RecentActivityEntry[];
|
|
496
|
+
|
|
472
497
|
/**
|
|
473
498
|
* ADHDev Launcher — Configuration
|
|
474
499
|
*
|
|
@@ -503,6 +528,8 @@ interface ADHDevConfig {
|
|
|
503
528
|
defaultWorkspaceId?: string | null;
|
|
504
529
|
/** Recently used workspaces (IDE / CLI / ACP / default) for quick resume */
|
|
505
530
|
recentWorkspaceActivity?: WorkspaceActivityEntry[];
|
|
531
|
+
/** Unified recent activity across IDE / CLI / ACP launch flows */
|
|
532
|
+
recentActivity?: RecentActivityEntry[];
|
|
506
533
|
machineNickname: string | null;
|
|
507
534
|
/**
|
|
508
535
|
* Stable local machine ID (prefix: `mach_`) — generated locally on first run.
|
|
@@ -651,6 +678,8 @@ interface SessionEntry {
|
|
|
651
678
|
currentAutoApprove?: string;
|
|
652
679
|
acpConfigOptions?: AcpConfigOption[];
|
|
653
680
|
acpModes?: AcpMode[];
|
|
681
|
+
controlValues?: Record<string, string | number | boolean>;
|
|
682
|
+
providerControls?: ProviderControlSchema[];
|
|
654
683
|
errorMessage?: string;
|
|
655
684
|
errorReason?: ProviderErrorReason;
|
|
656
685
|
}
|
|
@@ -680,6 +709,26 @@ interface AcpMode {
|
|
|
680
709
|
name: string;
|
|
681
710
|
description?: string;
|
|
682
711
|
}
|
|
712
|
+
/** Provider control schema (daemon → frontend) */
|
|
713
|
+
interface ProviderControlSchema {
|
|
714
|
+
id: string;
|
|
715
|
+
type: 'select' | 'toggle' | 'cycle' | 'slider' | 'action';
|
|
716
|
+
label: string;
|
|
717
|
+
icon?: string;
|
|
718
|
+
placement: 'bar' | 'header' | 'menu';
|
|
719
|
+
options?: { value: string; label: string; description?: string; group?: string }[];
|
|
720
|
+
dynamic?: boolean;
|
|
721
|
+
listScript?: string;
|
|
722
|
+
setScript?: string;
|
|
723
|
+
readFrom?: string;
|
|
724
|
+
defaultValue?: string | number | boolean;
|
|
725
|
+
invokeScript?: string;
|
|
726
|
+
resultDisplay?: 'toast' | 'inline' | 'none';
|
|
727
|
+
min?: number;
|
|
728
|
+
max?: number;
|
|
729
|
+
step?: number;
|
|
730
|
+
order?: number;
|
|
731
|
+
}
|
|
683
732
|
/** Machine hardware/OS info (reported by daemon, displayed by web) */
|
|
684
733
|
interface MachineInfo {
|
|
685
734
|
hostname: string;
|
|
@@ -709,6 +758,18 @@ interface WorkspaceActivity {
|
|
|
709
758
|
kind?: string;
|
|
710
759
|
agentType?: string;
|
|
711
760
|
}
|
|
761
|
+
interface RecentSessionEntry {
|
|
762
|
+
id: string;
|
|
763
|
+
sessionId?: string | null;
|
|
764
|
+
providerType: string;
|
|
765
|
+
providerName: string;
|
|
766
|
+
kind: 'ide' | 'cli' | 'acp';
|
|
767
|
+
title: string;
|
|
768
|
+
workspace?: string | null;
|
|
769
|
+
currentModel?: string;
|
|
770
|
+
status?: SessionEntry['status'];
|
|
771
|
+
lastUsedAt: number;
|
|
772
|
+
}
|
|
712
773
|
interface StatusReportPayload {
|
|
713
774
|
/** Daemon instance ID */
|
|
714
775
|
instanceId: string;
|
|
@@ -738,6 +799,7 @@ interface StatusReportPayload {
|
|
|
738
799
|
defaultWorkspaceId?: string | null;
|
|
739
800
|
defaultWorkspacePath?: string | null;
|
|
740
801
|
workspaceActivity?: WorkspaceActivity[];
|
|
802
|
+
recentSessions?: RecentSessionEntry[];
|
|
741
803
|
}
|
|
742
804
|
|
|
743
805
|
/**
|
|
@@ -882,4 +944,4 @@ declare function isManagedStatusWaiting(status?: string | null, opts?: {
|
|
|
882
944
|
}): boolean;
|
|
883
945
|
declare function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(activeChat: T): T;
|
|
884
946
|
|
|
885
|
-
export {
|
|
947
|
+
export { markSetupComplete as $, type AvailableProviderInfo as A, type ProviderErrorReason as B, type CommandResult as C, type DaemonEvent as D, type ExtensionInfo as E, type ProviderInfo as F, type ProviderStatus as G, type RecentActivityEntry as H, type InstanceContext as I, type SessionCapability as J, type SessionKind as K, type SystemInfo as L, type MachineInfo as M, type WorkspaceEntry as N, addCliHistory as O, type ProviderCategory as P, appendRecentActivity as Q, type ResolvedProvider as R, type StatusResponse as S, getRecentActivity as T, getWorkspaceActivity as U, getWorkspaceState as V, type WorkspaceActivity as W, isManagedStatusWaiting as X, isManagedStatusWorking as Y, isSetupComplete as Z, loadConfig as _, type SessionEntry as a, normalizeActiveChatData as a0, normalizeManagedStatus as a1, resetConfig as a2, saveConfig as a3, updateConfig as a4, type ProviderModule as b, type ProviderSettingSchema as c, type CdpTargetFilter as d, type ProviderInstance as e, type ProviderState as f, type ProviderEvent as g, type SessionTransport as h, type StatusReportPayload as i, type ProviderResumeCapability as j, type AcpProviderState as k, type ContentBlock as l, type AcpConfigOption as m, type AcpMode as n, type ActiveChatData as o, type AgentEntry as p, type AgentSessionStream as q, type ChatMessage as r, type CliProviderState as s, type DetectedIde as t, type DetectedIdeInfo as u, type ExtensionProviderState as v, type IdeProviderState as w, type ManagedStatus as x, type ProviderConfig as y, type ProviderControlSchema as z };
|
|
@@ -469,6 +469,31 @@ interface WorkspaceActivityEntry {
|
|
|
469
469
|
}
|
|
470
470
|
declare function getWorkspaceActivity(config: ADHDevConfig, limit?: number): WorkspaceActivityEntry[];
|
|
471
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Unified recent activity — machine-facing "pick up where you left off".
|
|
474
|
+
*
|
|
475
|
+
* Unlike cliHistory or workspaceActivity, this is task/session oriented:
|
|
476
|
+
* - one normalized row shape for IDE / CLI / ACP
|
|
477
|
+
* - deduped by kind + providerType + workspace
|
|
478
|
+
* - optionally linked to a live sessionId when known
|
|
479
|
+
*/
|
|
480
|
+
|
|
481
|
+
interface RecentActivityEntry {
|
|
482
|
+
id: string;
|
|
483
|
+
kind: 'ide' | 'cli' | 'acp';
|
|
484
|
+
providerType: string;
|
|
485
|
+
providerName: string;
|
|
486
|
+
workspace?: string | null;
|
|
487
|
+
currentModel?: string;
|
|
488
|
+
sessionId?: string | null;
|
|
489
|
+
title?: string;
|
|
490
|
+
lastUsedAt: number;
|
|
491
|
+
}
|
|
492
|
+
declare function appendRecentActivity(config: ADHDevConfig, entry: Omit<RecentActivityEntry, 'id' | 'lastUsedAt'> & {
|
|
493
|
+
lastUsedAt?: number;
|
|
494
|
+
}): ADHDevConfig;
|
|
495
|
+
declare function getRecentActivity(config: ADHDevConfig, limit?: number): RecentActivityEntry[];
|
|
496
|
+
|
|
472
497
|
/**
|
|
473
498
|
* ADHDev Launcher — Configuration
|
|
474
499
|
*
|
|
@@ -503,6 +528,8 @@ interface ADHDevConfig {
|
|
|
503
528
|
defaultWorkspaceId?: string | null;
|
|
504
529
|
/** Recently used workspaces (IDE / CLI / ACP / default) for quick resume */
|
|
505
530
|
recentWorkspaceActivity?: WorkspaceActivityEntry[];
|
|
531
|
+
/** Unified recent activity across IDE / CLI / ACP launch flows */
|
|
532
|
+
recentActivity?: RecentActivityEntry[];
|
|
506
533
|
machineNickname: string | null;
|
|
507
534
|
/**
|
|
508
535
|
* Stable local machine ID (prefix: `mach_`) — generated locally on first run.
|
|
@@ -651,6 +678,8 @@ interface SessionEntry {
|
|
|
651
678
|
currentAutoApprove?: string;
|
|
652
679
|
acpConfigOptions?: AcpConfigOption[];
|
|
653
680
|
acpModes?: AcpMode[];
|
|
681
|
+
controlValues?: Record<string, string | number | boolean>;
|
|
682
|
+
providerControls?: ProviderControlSchema[];
|
|
654
683
|
errorMessage?: string;
|
|
655
684
|
errorReason?: ProviderErrorReason;
|
|
656
685
|
}
|
|
@@ -680,6 +709,26 @@ interface AcpMode {
|
|
|
680
709
|
name: string;
|
|
681
710
|
description?: string;
|
|
682
711
|
}
|
|
712
|
+
/** Provider control schema (daemon → frontend) */
|
|
713
|
+
interface ProviderControlSchema {
|
|
714
|
+
id: string;
|
|
715
|
+
type: 'select' | 'toggle' | 'cycle' | 'slider' | 'action';
|
|
716
|
+
label: string;
|
|
717
|
+
icon?: string;
|
|
718
|
+
placement: 'bar' | 'header' | 'menu';
|
|
719
|
+
options?: { value: string; label: string; description?: string; group?: string }[];
|
|
720
|
+
dynamic?: boolean;
|
|
721
|
+
listScript?: string;
|
|
722
|
+
setScript?: string;
|
|
723
|
+
readFrom?: string;
|
|
724
|
+
defaultValue?: string | number | boolean;
|
|
725
|
+
invokeScript?: string;
|
|
726
|
+
resultDisplay?: 'toast' | 'inline' | 'none';
|
|
727
|
+
min?: number;
|
|
728
|
+
max?: number;
|
|
729
|
+
step?: number;
|
|
730
|
+
order?: number;
|
|
731
|
+
}
|
|
683
732
|
/** Machine hardware/OS info (reported by daemon, displayed by web) */
|
|
684
733
|
interface MachineInfo {
|
|
685
734
|
hostname: string;
|
|
@@ -709,6 +758,18 @@ interface WorkspaceActivity {
|
|
|
709
758
|
kind?: string;
|
|
710
759
|
agentType?: string;
|
|
711
760
|
}
|
|
761
|
+
interface RecentSessionEntry {
|
|
762
|
+
id: string;
|
|
763
|
+
sessionId?: string | null;
|
|
764
|
+
providerType: string;
|
|
765
|
+
providerName: string;
|
|
766
|
+
kind: 'ide' | 'cli' | 'acp';
|
|
767
|
+
title: string;
|
|
768
|
+
workspace?: string | null;
|
|
769
|
+
currentModel?: string;
|
|
770
|
+
status?: SessionEntry['status'];
|
|
771
|
+
lastUsedAt: number;
|
|
772
|
+
}
|
|
712
773
|
interface StatusReportPayload {
|
|
713
774
|
/** Daemon instance ID */
|
|
714
775
|
instanceId: string;
|
|
@@ -738,6 +799,7 @@ interface StatusReportPayload {
|
|
|
738
799
|
defaultWorkspaceId?: string | null;
|
|
739
800
|
defaultWorkspacePath?: string | null;
|
|
740
801
|
workspaceActivity?: WorkspaceActivity[];
|
|
802
|
+
recentSessions?: RecentSessionEntry[];
|
|
741
803
|
}
|
|
742
804
|
|
|
743
805
|
/**
|
|
@@ -882,4 +944,4 @@ declare function isManagedStatusWaiting(status?: string | null, opts?: {
|
|
|
882
944
|
}): boolean;
|
|
883
945
|
declare function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(activeChat: T): T;
|
|
884
946
|
|
|
885
|
-
export {
|
|
947
|
+
export { markSetupComplete as $, type AvailableProviderInfo as A, type ProviderErrorReason as B, type CommandResult as C, type DaemonEvent as D, type ExtensionInfo as E, type ProviderInfo as F, type ProviderStatus as G, type RecentActivityEntry as H, type InstanceContext as I, type SessionCapability as J, type SessionKind as K, type SystemInfo as L, type MachineInfo as M, type WorkspaceEntry as N, addCliHistory as O, type ProviderCategory as P, appendRecentActivity as Q, type ResolvedProvider as R, type StatusResponse as S, getRecentActivity as T, getWorkspaceActivity as U, getWorkspaceState as V, type WorkspaceActivity as W, isManagedStatusWaiting as X, isManagedStatusWorking as Y, isSetupComplete as Z, loadConfig as _, type SessionEntry as a, normalizeActiveChatData as a0, normalizeManagedStatus as a1, resetConfig as a2, saveConfig as a3, updateConfig as a4, type ProviderModule as b, type ProviderSettingSchema as c, type CdpTargetFilter as d, type ProviderInstance as e, type ProviderState as f, type ProviderEvent as g, type SessionTransport as h, type StatusReportPayload as i, type ProviderResumeCapability as j, type AcpProviderState as k, type ContentBlock as l, type AcpConfigOption as m, type AcpMode as n, type ActiveChatData as o, type AgentEntry as p, type AgentSessionStream as q, type ChatMessage as r, type CliProviderState as s, type DetectedIde as t, type DetectedIdeInfo as u, type ExtensionProviderState as v, type IdeProviderState as w, type ManagedStatus as x, type ProviderConfig as y, type ProviderControlSchema as z };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { x as ManagedStatus,
|
|
1
|
+
export { x as ManagedStatus, X as isManagedStatusWaiting, Y as isManagedStatusWorking, a0 as normalizeActiveChatData, a1 as normalizeManagedStatus } from '../normalize-DVI4Lo5I.mjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { x as ManagedStatus,
|
|
1
|
+
export { x as ManagedStatus, X as isManagedStatusWaiting, Y as isManagedStatusWorking, a0 as normalizeActiveChatData, a1 as normalizeManagedStatus } from '../normalize-DVI4Lo5I.js';
|
package/package.json
CHANGED
|
@@ -67,6 +67,15 @@ export class DaemonAgentStreamManager {
|
|
|
67
67
|
return this.activeSessionIdByParent.get(parentSessionId) || null;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
private isRecoverableSessionError(message: string): boolean {
|
|
71
|
+
return message.includes('timeout')
|
|
72
|
+
|| message.includes('not connected')
|
|
73
|
+
|| message.includes('Session')
|
|
74
|
+
|| message.includes('Target closed')
|
|
75
|
+
|| message.includes('execution context')
|
|
76
|
+
|| message.includes('context with specified id');
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
private getSessionTarget(sessionId: string) {
|
|
71
80
|
return this.sessionRegistry?.get(sessionId);
|
|
72
81
|
}
|
|
@@ -186,6 +195,10 @@ export class DaemonAgentStreamManager {
|
|
|
186
195
|
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
187
196
|
const state = await agent.adapter.readChat(evaluate);
|
|
188
197
|
LOG.debug('AgentStream', `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ''}${state.status === 'error' ? ' error=' + JSON.stringify((state as any).error || (state as any)._error || 'unknown') : ''}`);
|
|
198
|
+
const stateError = String((state as any).error || (state as any)._error || '');
|
|
199
|
+
if (state.status === 'error' && this.isRecoverableSessionError(stateError)) {
|
|
200
|
+
throw new Error(stateError);
|
|
201
|
+
}
|
|
189
202
|
agent.lastState = state;
|
|
190
203
|
agent.lastError = null;
|
|
191
204
|
if (state.status === 'panel_hidden') {
|
|
@@ -196,7 +209,7 @@ export class DaemonAgentStreamManager {
|
|
|
196
209
|
const errorMsg = (e as Error)?.message || String(e);
|
|
197
210
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
198
211
|
agent.lastError = errorMsg;
|
|
199
|
-
if (
|
|
212
|
+
if (this.isRecoverableSessionError(errorMsg)) {
|
|
200
213
|
try { await cdp.detachAgent(agent.cdpSessionId); } catch { }
|
|
201
214
|
this.managedBySessionId.delete(activeSessionId);
|
|
202
215
|
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
@@ -40,12 +40,33 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
|
|
|
40
40
|
return typeof (this.provider.scripts as any)?.[name] === 'function';
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
private summarizeRaw(raw: unknown): string {
|
|
44
|
+
try {
|
|
45
|
+
if (typeof raw === 'string') return raw.replace(/\s+/g, ' ').trim().slice(0, 240);
|
|
46
|
+
if (raw == null) return String(raw);
|
|
47
|
+
return JSON.stringify(raw).replace(/\s+/g, ' ').trim().slice(0, 240);
|
|
48
|
+
} catch {
|
|
49
|
+
return Object.prototype.toString.call(raw);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private isTransportError(reason: string): boolean {
|
|
54
|
+
return /Session with given id not found/i.test(reason)
|
|
55
|
+
|| /CDP not connected/i.test(reason)
|
|
56
|
+
|| /Target closed/i.test(reason)
|
|
57
|
+
|| /WebSocket not open/i.test(reason)
|
|
58
|
+
|| /not connected/i.test(reason)
|
|
59
|
+
|| /execution context/i.test(reason)
|
|
60
|
+
|| /Cannot find context with specified id/i.test(reason);
|
|
61
|
+
}
|
|
62
|
+
|
|
43
63
|
async readChat(evaluate: AgentEvaluateFn): Promise<AgentStreamState> {
|
|
44
64
|
const script = this.callScript('readChat');
|
|
45
65
|
if (!script) return this.errorState('readChat script not available');
|
|
46
66
|
|
|
67
|
+
let raw: unknown = null;
|
|
47
68
|
try {
|
|
48
|
-
|
|
69
|
+
raw = await evaluate(script) as string;
|
|
49
70
|
const data = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
50
71
|
if (data?.error) {
|
|
51
72
|
const state = this.errorState(data.error);
|
|
@@ -65,12 +86,33 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
|
|
|
65
86
|
mode: data.mode,
|
|
66
87
|
activeModal: data.activeModal,
|
|
67
88
|
};
|
|
89
|
+
// Build controlValues from provider controls schema
|
|
90
|
+
if (this.provider.controls?.length) {
|
|
91
|
+
const cv: Record<string, string | number | boolean> = {};
|
|
92
|
+
for (const ctrl of this.provider.controls) {
|
|
93
|
+
if (!ctrl.readFrom) continue; // action type — no value
|
|
94
|
+
const val = data[ctrl.readFrom];
|
|
95
|
+
if (val !== undefined && val !== null) {
|
|
96
|
+
cv[ctrl.id] = typeof val === 'object' ? (val.name || val.id || String(val)) : val;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Also include model/mode as fallback controls
|
|
100
|
+
if (data.model && !cv['model']) cv['model'] = data.model;
|
|
101
|
+
if (data.mode && !cv['mode']) cv['mode'] = data.mode;
|
|
102
|
+
if (Object.keys(cv).length > 0) state.controlValues = cv;
|
|
103
|
+
}
|
|
68
104
|
if (state.messages.length > 0) {
|
|
69
105
|
this.lastSuccessState = state;
|
|
70
106
|
}
|
|
71
107
|
return state;
|
|
72
|
-
} catch {
|
|
73
|
-
const
|
|
108
|
+
} catch (error) {
|
|
109
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
110
|
+
if (this.isTransportError(reason)) {
|
|
111
|
+
throw (error instanceof Error ? error : new Error(reason));
|
|
112
|
+
}
|
|
113
|
+
const preview = this.summarizeRaw(raw);
|
|
114
|
+
const detail = preview ? ` (reason=${reason}; raw=${preview})` : ` (reason=${reason})`;
|
|
115
|
+
const state = this.errorState(`Failed to parse ${this.agentName} state${detail}`);
|
|
74
116
|
if (this.lastSuccessState?.messages?.length) {
|
|
75
117
|
state.messages = this.lastSuccessState.messages;
|
|
76
118
|
}
|
|
@@ -29,9 +29,13 @@ export interface AgentStreamState {
|
|
|
29
29
|
status: 'idle' | 'streaming' | 'waiting_approval' | 'error' | 'disconnected' | 'panel_hidden' | 'not_monitored';
|
|
30
30
|
messages: AgentChatMessage[];
|
|
31
31
|
inputContent: string;
|
|
32
|
+
/** @deprecated Use controlValues['model'] — kept for backward compatibility */
|
|
32
33
|
model?: string;
|
|
34
|
+
/** @deprecated Use controlValues['mode'] — kept for backward compatibility */
|
|
33
35
|
mode?: string;
|
|
34
36
|
activeModal?: { message: string; buttons: string[] };
|
|
37
|
+
/** Dynamic control current values (populated from readChat + provider controls schema) */
|
|
38
|
+
controlValues?: Record<string, string | number | boolean>;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
/** Agent webview target info */
|
|
@@ -19,6 +19,21 @@ import { XtermTerminalBackend } from './terminal-backends/xterm-backend.js';
|
|
|
19
19
|
const DEFAULT_SCROLLBACK = 2000;
|
|
20
20
|
const loggedTerminalBackends = new Set<string>();
|
|
21
21
|
|
|
22
|
+
export function getTerminalBackendRuntimeStatus(): {
|
|
23
|
+
backend: TerminalViewportBackendKind;
|
|
24
|
+
preference: TerminalViewportBackendPreference;
|
|
25
|
+
ghosttyAvailable: boolean;
|
|
26
|
+
} {
|
|
27
|
+
const preference = resolveTerminalBackendPreference();
|
|
28
|
+
const ghosttyAvailable = isGhosttyVtBackendAvailable();
|
|
29
|
+
const backend: TerminalViewportBackendKind = (
|
|
30
|
+
preference === 'ghostty-vt' || (preference === 'auto' && ghosttyAvailable)
|
|
31
|
+
? 'ghostty-vt'
|
|
32
|
+
: 'xterm'
|
|
33
|
+
);
|
|
34
|
+
return { backend, preference, ghosttyAvailable };
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
function createTerminalBackend(
|
|
23
38
|
options: TerminalViewportBackendOptions,
|
|
24
39
|
preference: TerminalViewportBackendPreference,
|
|
@@ -14,6 +14,7 @@ import { detectCLI } from '../detection/cli-detector.js';
|
|
|
14
14
|
import { loadConfig, saveConfig, addCliHistory } from '../config/config.js';
|
|
15
15
|
import { getWorkspaceState, resolveLaunchDirectory } from '../config/workspaces.js';
|
|
16
16
|
import { appendWorkspaceActivity } from '../config/workspace-activity.js';
|
|
17
|
+
import { appendRecentActivity } from '../config/recent-activity.js';
|
|
17
18
|
import { CliProviderInstance } from '../providers/cli-provider-instance.js';
|
|
18
19
|
import { AcpProviderInstance } from '../providers/acp-provider-instance.js';
|
|
19
20
|
import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
|
|
@@ -109,6 +110,22 @@ export class DaemonCliManager {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
private persistRecentActivity(entry: {
|
|
114
|
+
kind: 'ide' | 'cli' | 'acp';
|
|
115
|
+
providerType: string;
|
|
116
|
+
providerName: string;
|
|
117
|
+
workspace?: string;
|
|
118
|
+
currentModel?: string;
|
|
119
|
+
sessionId?: string;
|
|
120
|
+
title?: string;
|
|
121
|
+
}): void {
|
|
122
|
+
try {
|
|
123
|
+
saveConfig(appendRecentActivity(loadConfig(), entry));
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.error(colorize('red', ` ✗ Failed to save recent activity: ${e}`));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
112
129
|
private getTransportFactory(
|
|
113
130
|
runtimeId: string,
|
|
114
131
|
providerType: string,
|
|
@@ -300,6 +317,15 @@ export class DaemonCliManager {
|
|
|
300
317
|
}
|
|
301
318
|
|
|
302
319
|
try { addCliHistory({ category: 'acp', cliType: normalizedType, dir: resolvedDir, workspace: resolvedDir, cliArgs, model: initialModel }); } catch (e) { LOG.warn('CLI', `ACP history save failed: ${(e as Error)?.message}`); }
|
|
320
|
+
this.persistRecentActivity({
|
|
321
|
+
kind: 'acp',
|
|
322
|
+
providerType: normalizedType,
|
|
323
|
+
providerName: provider.displayName || provider.name || normalizedType,
|
|
324
|
+
workspace: resolvedDir,
|
|
325
|
+
currentModel: initialModel,
|
|
326
|
+
sessionId,
|
|
327
|
+
title: provider.displayName || provider.name || normalizedType,
|
|
328
|
+
});
|
|
303
329
|
this.deps.onStatusChange();
|
|
304
330
|
return;
|
|
305
331
|
}
|
|
@@ -368,6 +394,15 @@ export class DaemonCliManager {
|
|
|
368
394
|
}
|
|
369
395
|
|
|
370
396
|
try { addCliHistory({ category: 'cli', cliType, dir: resolvedDir, workspace: resolvedDir, cliArgs, model: initialModel }); } catch (e) { LOG.warn('CLI', `CLI history save failed: ${(e as Error)?.message}`); }
|
|
397
|
+
this.persistRecentActivity({
|
|
398
|
+
kind: 'cli',
|
|
399
|
+
providerType: normalizedType,
|
|
400
|
+
providerName: provider?.displayName || provider?.name || normalizedType,
|
|
401
|
+
workspace: resolvedDir,
|
|
402
|
+
currentModel: initialModel,
|
|
403
|
+
sessionId: key,
|
|
404
|
+
title: provider?.displayName || provider?.name || normalizedType,
|
|
405
|
+
});
|
|
371
406
|
|
|
372
407
|
this.deps.onStatusChange();
|
|
373
408
|
}
|
package/src/commands/router.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { loadConfig, saveConfig, updateConfig } from '../config/config.js';
|
|
|
20
20
|
import { resolveIdeLaunchWorkspace } from '../config/workspaces.js';
|
|
21
21
|
import { appendWorkspaceActivity } from '../config/workspace-activity.js';
|
|
22
22
|
import { addCliHistory } from '../config/config.js';
|
|
23
|
+
import { appendRecentActivity, buildRecentActivityKey, markRecentSessionSeen } from '../config/recent-activity.js';
|
|
23
24
|
import { detectIDEs } from '../detection/ide-detector.js';
|
|
24
25
|
import { SessionRegistry } from '../sessions/registry.js';
|
|
25
26
|
import { LOG } from '../logging/logger.js';
|
|
@@ -240,9 +241,26 @@ export class DaemonCommandRouter {
|
|
|
240
241
|
this.deps.onIdeConnected?.();
|
|
241
242
|
if (result.success && resolvedWorkspace) {
|
|
242
243
|
try {
|
|
243
|
-
|
|
244
|
+
let next = appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
|
|
244
245
|
kind: 'ide',
|
|
245
246
|
agentType: result.ideId,
|
|
247
|
+
});
|
|
248
|
+
next = appendRecentActivity(next, {
|
|
249
|
+
kind: 'ide',
|
|
250
|
+
providerType: result.ideId || ideKey,
|
|
251
|
+
providerName: result.ideId || ideKey,
|
|
252
|
+
workspace: resolvedWorkspace,
|
|
253
|
+
title: result.ideId || ideKey,
|
|
254
|
+
});
|
|
255
|
+
saveConfig(next);
|
|
256
|
+
} catch { /* ignore activity persist errors */ }
|
|
257
|
+
} else if (result.success && (result.ideId || ideKey)) {
|
|
258
|
+
try {
|
|
259
|
+
saveConfig(appendRecentActivity(loadConfig(), {
|
|
260
|
+
kind: 'ide',
|
|
261
|
+
providerType: result.ideId || ideKey,
|
|
262
|
+
providerName: result.ideId || ideKey,
|
|
263
|
+
title: result.ideId || ideKey,
|
|
246
264
|
}));
|
|
247
265
|
} catch { /* ignore activity persist errors */ }
|
|
248
266
|
}
|
|
@@ -264,6 +282,31 @@ export class DaemonCommandRouter {
|
|
|
264
282
|
return { success: true, userName: name };
|
|
265
283
|
}
|
|
266
284
|
|
|
285
|
+
case 'mark_recent_seen': {
|
|
286
|
+
const kind = args?.kind;
|
|
287
|
+
const providerType = args?.providerType;
|
|
288
|
+
if (!kind || !providerType) {
|
|
289
|
+
return { success: false, error: 'kind and providerType are required' };
|
|
290
|
+
}
|
|
291
|
+
const recentKey = args?.recentKey || buildRecentActivityKey({
|
|
292
|
+
kind,
|
|
293
|
+
providerType,
|
|
294
|
+
workspace: args?.workspace || null,
|
|
295
|
+
});
|
|
296
|
+
const next = markRecentSessionSeen(
|
|
297
|
+
loadConfig(),
|
|
298
|
+
recentKey,
|
|
299
|
+
typeof args?.seenAt === 'number' ? args.seenAt : Date.now(),
|
|
300
|
+
);
|
|
301
|
+
saveConfig(next);
|
|
302
|
+
this.deps.onStatusChange?.();
|
|
303
|
+
return {
|
|
304
|
+
success: true,
|
|
305
|
+
recentKey,
|
|
306
|
+
seenAt: next.recentSessionReads?.[recentKey] || Date.now(),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
267
310
|
// ─── Daemon Self-Upgrade ───
|
|
268
311
|
case 'daemon_upgrade': {
|
|
269
312
|
LOG.info('Upgrade', 'Remote upgrade requested from dashboard');
|
|
@@ -24,10 +24,11 @@ export function handleWorkspaceList(): WorkspaceCommandResult {
|
|
|
24
24
|
export function handleWorkspaceAdd(args: any): WorkspaceCommandResult {
|
|
25
25
|
const rawPath = (args?.path || args?.dir || '').trim();
|
|
26
26
|
const label = (args?.label || '').trim() || undefined;
|
|
27
|
+
const createIfMissing = args?.createIfMissing === true;
|
|
27
28
|
if (!rawPath) return { success: false, error: 'path required' };
|
|
28
29
|
|
|
29
30
|
const config = loadConfig();
|
|
30
|
-
const result = W.addWorkspaceEntry(config, rawPath, label);
|
|
31
|
+
const result = W.addWorkspaceEntry(config, rawPath, label, { createIfMissing });
|
|
31
32
|
if ('error' in result) return { success: false, error: result.error };
|
|
32
33
|
|
|
33
34
|
let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
|
package/src/config/config.d.ts
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { WorkspaceEntry } from './workspaces.js';
|
|
7
7
|
import type { WorkspaceActivityEntry } from './workspace-activity.js';
|
|
8
|
+
import type { RecentActivityEntry } from './recent-activity.js';
|
|
8
9
|
export type { WorkspaceEntry } from './workspaces.js';
|
|
9
10
|
export type { WorkspaceActivityEntry } from './workspace-activity.js';
|
|
11
|
+
export type { RecentActivityEntry } from './recent-activity.js';
|
|
10
12
|
export interface ADHDevConfig {
|
|
11
13
|
serverUrl: string;
|
|
12
14
|
apiToken: string | null;
|
|
@@ -35,6 +37,8 @@ export interface ADHDevConfig {
|
|
|
35
37
|
defaultWorkspaceId?: string | null;
|
|
36
38
|
/** Recently used workspaces (IDE / CLI / ACP / default) for quick resume */
|
|
37
39
|
recentWorkspaceActivity?: WorkspaceActivityEntry[];
|
|
40
|
+
/** Unified recent activity across IDE / CLI / ACP launch flows */
|
|
41
|
+
recentActivity?: RecentActivityEntry[];
|
|
38
42
|
machineNickname: string | null;
|
|
39
43
|
/**
|
|
40
44
|
* Stable local machine ID (prefix: `mach_`) — generated locally on first run.
|
package/src/config/config.ts
CHANGED
|
@@ -11,8 +11,10 @@ import { randomUUID } from 'crypto';
|
|
|
11
11
|
import { migrateWorkspacesFromRecent } from './workspaces.js';
|
|
12
12
|
import type { WorkspaceEntry } from './workspaces.js';
|
|
13
13
|
import type { WorkspaceActivityEntry } from './workspace-activity.js';
|
|
14
|
+
import type { RecentActivityEntry } from './recent-activity.js';
|
|
14
15
|
export type { WorkspaceEntry } from './workspaces.js';
|
|
15
16
|
export type { WorkspaceActivityEntry } from './workspace-activity.js';
|
|
17
|
+
export type { RecentActivityEntry } from './recent-activity.js';
|
|
16
18
|
|
|
17
19
|
export interface ADHDevConfig {
|
|
18
20
|
// Server connection
|
|
@@ -59,8 +61,12 @@ export interface ADHDevConfig {
|
|
|
59
61
|
/** Default workspace id (from workspaces[]) — never used implicitly for launch */
|
|
60
62
|
defaultWorkspaceId?: string | null;
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
/** Recently used workspaces (IDE / CLI / ACP / default) for quick resume */
|
|
63
65
|
recentWorkspaceActivity?: WorkspaceActivityEntry[];
|
|
66
|
+
/** Unified recent activity across IDE / CLI / ACP launch flows */
|
|
67
|
+
recentActivity?: RecentActivityEntry[];
|
|
68
|
+
/** Last seen timestamps for machine-facing recent/session entries */
|
|
69
|
+
recentSessionReads?: Record<string, number>;
|
|
64
70
|
|
|
65
71
|
// Machine nickname (user-customizable label for this machine)
|
|
66
72
|
machineNickname: string | null;
|
|
@@ -138,6 +144,8 @@ const DEFAULT_CONFIG: ADHDevConfig = {
|
|
|
138
144
|
workspaces: [],
|
|
139
145
|
defaultWorkspaceId: null,
|
|
140
146
|
recentWorkspaceActivity: [],
|
|
147
|
+
recentActivity: [],
|
|
148
|
+
recentSessionReads: {},
|
|
141
149
|
machineNickname: null,
|
|
142
150
|
machineId: undefined,
|
|
143
151
|
machineSecret: null,
|