@adhdev/daemon-core 0.6.79 → 0.7.1

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/src/index.ts CHANGED
@@ -20,10 +20,11 @@ export type {
20
20
 
21
21
  // ── Shared Types (cross-package) ──
22
22
  export type {
23
- ManagedIdeEntry,
24
- ManagedCliEntry,
25
- ManagedAcpEntry,
26
- ManagedAgentStream,
23
+ SessionEntry,
24
+ SessionTransport,
25
+ SessionKind,
26
+ SessionCapability,
27
+ AgentSessionStream,
27
28
  AvailableProviderInfo,
28
29
  AcpConfigOption,
29
30
  AcpMode,
@@ -74,7 +75,7 @@ export type { CommandRouterDeps, CommandRouterResult } from './commands/router.j
74
75
 
75
76
  // ── Status ──
76
77
  export { DaemonStatusReporter } from './status/reporter.js';
77
- export { buildManagedIdes, buildManagedClis, buildManagedAcps, buildAllManagedEntries, findCdpManager, hasCdpManager, isCdpConnected } from './status/builders.js';
78
+ export { buildSessionEntries, findCdpManager, hasCdpManager, isCdpConnected } from './status/builders.js';
78
79
  export { buildStatusSnapshot } from './status/snapshot.js';
79
80
  export { normalizeManagedStatus, isManagedStatusWorking, isManagedStatusWaiting, normalizeActiveChatData } from './status/normalize.js';
80
81
  export type { ManagedStatus } from './status/normalize.js';
@@ -50,7 +50,7 @@ function maskArgs(args: any): Record<string, unknown> | undefined {
50
50
  ? `[${value.length} chars]`
51
51
  : '[masked]';
52
52
  } else if (key.startsWith('_')) {
53
- // internal fields: keep as-is (e.g. _targetType, _targetInstance)
53
+ // internal fields: keep as-is (e.g. targetSessionId)
54
54
  masked[key] = value;
55
55
  } else if (typeof value === 'object' && value !== null) {
56
56
  // Don't recurse deeply — just note the type
@@ -259,6 +259,10 @@ export class AcpProviderInstance implements ProviderInstance {
259
259
  }
260
260
  }
261
261
 
262
+ getInstanceId(): string {
263
+ return this.instanceId;
264
+ }
265
+
262
266
  // ─── ACP Config Options & Modes ─────────────────────
263
267
 
264
268
  private parseConfigOptions(raw: any): void {
@@ -83,6 +83,7 @@ export class ProviderInstanceManager {
83
83
  ...event,
84
84
  providerType: instance.type,
85
85
  instanceId: state.instanceId,
86
+ targetSessionId: state.instanceId,
86
87
  providerCategory: state.category,
87
88
  });
88
89
  }
@@ -0,0 +1,76 @@
1
+ import type { SessionTransport } from '../shared-types.js';
2
+
3
+ export interface SessionRuntimeTarget {
4
+ sessionId: string;
5
+ parentSessionId: string | null;
6
+ providerType: string;
7
+ providerCategory: 'ide' | 'extension' | 'cli' | 'acp';
8
+ transport: SessionTransport;
9
+ cdpManagerKey?: string;
10
+ adapterKey?: string;
11
+ instanceKey?: string;
12
+ }
13
+
14
+ export class SessionRegistry {
15
+ private readonly bySessionId = new Map<string, SessionRuntimeTarget>();
16
+ private readonly byManagerKey = new Map<string, Set<string>>();
17
+ private readonly byInstanceKey = new Map<string, Set<string>>();
18
+ private readonly byParentSessionId = new Map<string, Set<string>>();
19
+
20
+ register(target: SessionRuntimeTarget): void {
21
+ this.unregister(target.sessionId);
22
+ this.bySessionId.set(target.sessionId, target);
23
+ if (target.cdpManagerKey) this.addIndex(this.byManagerKey, target.cdpManagerKey, target.sessionId);
24
+ if (target.instanceKey) this.addIndex(this.byInstanceKey, target.instanceKey, target.sessionId);
25
+ if (target.parentSessionId) this.addIndex(this.byParentSessionId, target.parentSessionId, target.sessionId);
26
+ }
27
+
28
+ get(sessionId: string | undefined | null): SessionRuntimeTarget | undefined {
29
+ if (!sessionId) return undefined;
30
+ return this.bySessionId.get(sessionId);
31
+ }
32
+
33
+ unregister(sessionId: string | undefined | null): void {
34
+ if (!sessionId) return;
35
+ const target = this.bySessionId.get(sessionId);
36
+ if (!target) return;
37
+ this.bySessionId.delete(sessionId);
38
+ if (target.cdpManagerKey) this.removeIndex(this.byManagerKey, target.cdpManagerKey, sessionId);
39
+ if (target.instanceKey) this.removeIndex(this.byInstanceKey, target.instanceKey, sessionId);
40
+ if (target.parentSessionId) this.removeIndex(this.byParentSessionId, target.parentSessionId, sessionId);
41
+ }
42
+
43
+ unregisterByManagerKey(managerKey: string): void {
44
+ for (const sessionId of [...(this.byManagerKey.get(managerKey) || [])]) {
45
+ this.unregister(sessionId);
46
+ }
47
+ }
48
+
49
+ unregisterByInstanceKey(instanceKey: string): void {
50
+ for (const sessionId of [...(this.byInstanceKey.get(instanceKey) || [])]) {
51
+ this.unregister(sessionId);
52
+ }
53
+ }
54
+
55
+ listChildren(parentSessionId: string): SessionRuntimeTarget[] {
56
+ const ids = this.byParentSessionId.get(parentSessionId);
57
+ if (!ids) return [];
58
+ return [...ids].map((id) => this.bySessionId.get(id)).filter(Boolean) as SessionRuntimeTarget[];
59
+ }
60
+
61
+ private addIndex(index: Map<string, Set<string>>, key: string, sessionId: string): void {
62
+ let set = index.get(key);
63
+ if (!set) {
64
+ set = new Set<string>();
65
+ index.set(key, set);
66
+ }
67
+ set.add(sessionId);
68
+ }
69
+
70
+ private removeIndex(index: Map<string, Set<string>>, key: string, sessionId: string): void {
71
+ const set = index.get(key);
72
+ if (!set) return;
73
+ set.delete(sessionId);
74
+ if (set.size === 0) index.delete(key);
75
+ }
76
+ }
@@ -41,7 +41,7 @@ export type {
41
41
  export type { ProviderErrorReason } from './providers/provider-instance.js';
42
42
 
43
43
  // Local import for use in Managed*Entry types below
44
- import type { ActiveChatData as _ActiveChatData } from './providers/provider-instance.js';
44
+ import type { ActiveChatData as _ActiveChatData, ProviderErrorReason as _ProviderErrorReason } from './providers/provider-instance.js';
45
45
  import type { WorkspaceEntry } from './config/workspaces.js';
46
46
 
47
47
  // Re-export WorkspaceEntry for downstream consumers
@@ -51,63 +51,58 @@ export type { WorkspaceEntry } from './config/workspaces.js';
51
51
  // These define the shape of data sent by DaemonStatusReporter
52
52
  // and consumed by web-core and downstream consumers.
53
53
 
54
- /** IDE entry as reported by daemon to dashboard */
55
- export interface ManagedIdeEntry {
56
- ideType: string;
57
- ideVersion: string;
58
- instanceId: string;
59
- workspace: string | null;
60
- terminals: number;
61
- aiAgents: unknown[];
62
- activeChat: _ActiveChatData | null;
63
- chats: unknown[];
64
- agentStreams: ManagedAgentStream[];
65
- cdpConnected: boolean;
66
- currentModel?: string;
67
- currentPlan?: string;
68
- currentAutoApprove?: string;
69
- }
70
-
71
- /** CLI entry as reported by daemon to dashboard */
72
- export interface ManagedCliEntry {
73
- id: string;
74
- instanceId: string;
75
- cliType: string;
76
- cliName: string;
54
+ /** Agent stream snapshot carried by flattened UI entries. */
55
+ export interface AgentSessionStream {
56
+ sessionId?: string;
57
+ parentSessionId?: string | null;
58
+ agentType: string;
59
+ agentName: string;
60
+ extensionId: string;
61
+ transport?: SessionTransport;
77
62
  status: string;
78
- mode: 'terminal';
79
- workspace: string;
80
- activeChat: _ActiveChatData | null;
63
+ messages: ChatMessage[];
64
+ inputContent: string;
65
+ model?: string;
66
+ activeModal: { message: string; buttons: string[] } | null;
81
67
  }
82
68
 
83
- /** ACP entry as reported by daemon to dashboard */
84
- export interface ManagedAcpEntry {
69
+ export type SessionTransport = 'cdp-page' | 'cdp-webview' | 'pty' | 'acp';
70
+
71
+ export type SessionKind = 'workspace' | 'agent';
72
+
73
+ export type SessionCapability =
74
+ | 'read_chat'
75
+ | 'send_message'
76
+ | 'new_session'
77
+ | 'list_sessions'
78
+ | 'switch_session'
79
+ | 'resolve_action'
80
+ | 'terminal_io'
81
+ | 'resize_terminal'
82
+ | 'change_model'
83
+ | 'set_mode'
84
+ | 'set_thought_level';
85
+
86
+ export interface SessionEntry {
85
87
  id: string;
86
- acpType: string;
87
- acpName: string;
88
- status: string;
89
- mode: 'chat';
90
- workspace: string;
88
+ parentId: string | null;
89
+ providerType: string;
90
+ providerName: string;
91
+ kind: SessionKind;
92
+ transport: SessionTransport;
93
+ status: 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
94
+ title: string;
95
+ workspace: string | null;
91
96
  activeChat: _ActiveChatData | null;
97
+ capabilities: SessionCapability[];
98
+ cdpConnected?: boolean;
92
99
  currentModel?: string;
93
100
  currentPlan?: string;
101
+ currentAutoApprove?: string;
94
102
  acpConfigOptions?: AcpConfigOption[];
95
103
  acpModes?: AcpMode[];
96
- /** Error details */
97
104
  errorMessage?: string;
98
- errorReason?: 'not_installed' | 'auth_failed' | 'spawn_error' | 'init_failed' | 'crash' | 'timeout' | 'cdp_error' | 'disconnected';
99
- }
100
-
101
- /** Agent stream within an IDE (extension status) */
102
- export interface ManagedAgentStream {
103
- agentType: string;
104
- agentName: string;
105
- extensionId: string;
106
- status: string;
107
- messages: ChatMessage[];
108
- inputContent: string;
109
- model?: string;
110
- activeModal: { message: string; buttons: string[] } | null;
105
+ errorReason?: _ProviderErrorReason;
111
106
  }
112
107
 
113
108
  /** Available provider information */
@@ -188,12 +183,8 @@ export interface StatusReportPayload {
188
183
  detectedIdes: DetectedIdeInfo[];
189
184
  /** P2P state */
190
185
  p2p?: { available: boolean; state: string; peers: number; screenshotActive?: boolean };
191
- /** Managed IDE instances */
192
- managedIdes: ManagedIdeEntry[];
193
- /** Managed CLI instances */
194
- managedClis: ManagedCliEntry[];
195
- /** Managed ACP instances */
196
- managedAcps: ManagedAcpEntry[];
186
+ /** Canonical daemon runtime sessions */
187
+ sessions: SessionEntry[];
197
188
  /** Saved workspaces */
198
189
  workspaces?: WorkspaceEntry[];
199
190
  defaultWorkspaceId?: string | null;
@@ -9,11 +9,12 @@
9
9
  */
10
10
 
11
11
  import type { DaemonCdpManager } from '../cdp/manager.js';
12
- import type { ManagedIdeEntry, ManagedCliEntry, ManagedAcpEntry } from '../shared-types.js';
12
+ import type { SessionEntry, SessionCapability } from '../shared-types.js';
13
13
  import type {
14
14
  IdeProviderState,
15
15
  CliProviderState,
16
16
  AcpProviderState,
17
+ ExtensionProviderState,
17
18
  ProviderState,
18
19
  } from '../providers/provider-instance.js';
19
20
  import { normalizeActiveChatData, normalizeManagedStatus } from './normalize.js';
@@ -74,137 +75,172 @@ export function isCdpConnected(
74
75
  return m?.isConnected ?? false;
75
76
  }
76
77
 
77
- // ─── ProviderState ManagedEntry builders ───────────
78
-
79
- /**
80
- * Convert IdeProviderState[] → ManagedIdeEntry[]
81
- *
82
- * @param ideStates - from instanceManager.collectAllStates() filtered to ide
83
- * @param cdpManagers - for cdpConnected lookup
84
- * @param opts.detectedIdes - include CDPs that have no instance yet
85
- */
86
- export function buildManagedIdes(
87
- ideStates: IdeProviderState[],
78
+ const IDE_SESSION_CAPABILITIES: SessionCapability[] = [
79
+ 'read_chat',
80
+ 'send_message',
81
+ 'new_session',
82
+ 'list_sessions',
83
+ 'switch_session',
84
+ 'resolve_action',
85
+ 'change_model',
86
+ 'set_mode',
87
+ 'set_thought_level',
88
+ ];
89
+
90
+ const EXTENSION_SESSION_CAPABILITIES: SessionCapability[] = [
91
+ 'read_chat',
92
+ 'send_message',
93
+ 'new_session',
94
+ 'list_sessions',
95
+ 'switch_session',
96
+ 'resolve_action',
97
+ 'change_model',
98
+ 'set_mode',
99
+ ];
100
+
101
+ const PTY_SESSION_CAPABILITIES: SessionCapability[] = [
102
+ 'read_chat',
103
+ 'send_message',
104
+ 'resolve_action',
105
+ 'terminal_io',
106
+ 'resize_terminal',
107
+ ];
108
+
109
+ const ACP_SESSION_CAPABILITIES: SessionCapability[] = [
110
+ 'read_chat',
111
+ 'send_message',
112
+ 'new_session',
113
+ 'resolve_action',
114
+ 'change_model',
115
+ 'set_mode',
116
+ 'set_thought_level',
117
+ ];
118
+
119
+ function buildIdeWorkspaceSession(
120
+ state: IdeProviderState,
88
121
  cdpManagers: Map<string, DaemonCdpManager>,
89
- opts?: { detectedIdes?: { id: string; installed: boolean }[] },
90
- ): ManagedIdeEntry[] {
91
- const result: ManagedIdeEntry[] = [];
92
-
93
- for (const state of ideStates) {
94
- // Use cdpConnected from IdeProviderState if available (it checks internally),
95
- // otherwise fall back to CDP manager lookup
96
- const cdpConnected = state.cdpConnected ?? isCdpConnected(cdpManagers, state.type);
97
- result.push({
98
- ideType: state.type,
99
- ideVersion: '',
100
- instanceId: state.instanceId || state.type,
101
- workspace: state.workspace || null,
102
- terminals: 0,
103
- aiAgents: [],
104
- activeChat: normalizeActiveChatData(state.activeChat),
105
- chats: [],
106
- agentStreams: state.extensions.map((ext) => ({
107
- agentType: ext.type,
108
- agentName: ext.name,
109
- extensionId: ext.type,
110
- status: normalizeManagedStatus(ext.status, { activeModal: ext.activeChat?.activeModal || null }),
111
- messages: ext.activeChat?.messages || [],
112
- inputContent: ext.activeChat?.inputContent || '',
113
- activeModal: ext.activeChat?.activeModal || null,
114
- })),
115
- cdpConnected,
116
- currentModel: state.currentModel,
117
- currentPlan: state.currentPlan,
118
- currentAutoApprove: state.currentAutoApprove,
119
- });
120
- }
121
-
122
- // Include CDPs with no ProviderInstance yet (newly detected IDEs)
123
- if (opts?.detectedIdes) {
124
- const coveredTypes = new Set(ideStates.map((s) => s.type));
125
- for (const ide of opts.detectedIdes) {
126
- if (!ide.installed || coveredTypes.has(ide.id)) continue;
127
- if (!isCdpConnected(cdpManagers, ide.id)) continue;
128
- result.push({
129
- ideType: ide.id,
130
- ideVersion: '',
131
- instanceId: ide.id,
132
- workspace: null,
133
- terminals: 0,
134
- aiAgents: [],
135
- activeChat: null,
136
- chats: [],
137
- agentStreams: [],
138
- cdpConnected: true,
139
- currentModel: undefined,
140
- currentPlan: undefined,
141
- });
142
- }
143
- }
122
+ ): SessionEntry {
123
+ const activeChat = normalizeActiveChatData(state.activeChat);
124
+ const title = activeChat?.title || state.name;
125
+ return {
126
+ id: state.instanceId || state.type,
127
+ parentId: null,
128
+ providerType: state.type,
129
+ providerName: state.name,
130
+ kind: 'workspace',
131
+ transport: 'cdp-page',
132
+ status: normalizeManagedStatus(activeChat?.status || state.status, {
133
+ activeModal: activeChat?.activeModal || null,
134
+ }),
135
+ title,
136
+ workspace: state.workspace || null,
137
+ activeChat,
138
+ capabilities: IDE_SESSION_CAPABILITIES,
139
+ cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
140
+ currentModel: state.currentModel,
141
+ currentPlan: state.currentPlan,
142
+ currentAutoApprove: state.currentAutoApprove,
143
+ errorMessage: state.errorMessage,
144
+ errorReason: state.errorReason,
145
+ };
146
+ }
144
147
 
145
- return result;
148
+ function buildExtensionAgentSession(
149
+ parent: IdeProviderState,
150
+ ext: ExtensionProviderState,
151
+ ): SessionEntry {
152
+ const activeChat = normalizeActiveChatData(ext.activeChat);
153
+ return {
154
+ id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
155
+ parentId: parent.instanceId || parent.type,
156
+ providerType: ext.type,
157
+ providerName: ext.name,
158
+ kind: 'agent',
159
+ transport: 'cdp-webview',
160
+ status: normalizeManagedStatus(activeChat?.status || ext.status, {
161
+ activeModal: activeChat?.activeModal || null,
162
+ }),
163
+ title: activeChat?.title || ext.name,
164
+ workspace: parent.workspace || null,
165
+ activeChat,
166
+ capabilities: EXTENSION_SESSION_CAPABILITIES,
167
+ currentModel: ext.currentModel,
168
+ currentPlan: ext.currentPlan,
169
+ errorMessage: ext.errorMessage,
170
+ errorReason: ext.errorReason,
171
+ };
146
172
  }
147
173
 
148
- /**
149
- * Convert CliProviderState[] → ManagedCliEntry[]
150
- */
151
- export function buildManagedClis(
152
- cliStates: CliProviderState[],
153
- ): ManagedCliEntry[] {
154
- return cliStates.map((s) => ({
155
- id: s.instanceId,
156
- instanceId: s.instanceId,
157
- cliType: s.type,
158
- cliName: s.name,
159
- status: normalizeManagedStatus(s.status, { activeModal: s.activeChat?.activeModal || null }),
160
- mode: 'terminal' as const,
161
- workspace: s.workspace || '',
162
- activeChat: normalizeActiveChatData(s.activeChat),
163
- }));
174
+ function buildCliSession(state: CliProviderState): SessionEntry {
175
+ const activeChat = normalizeActiveChatData(state.activeChat);
176
+ return {
177
+ id: state.instanceId,
178
+ parentId: null,
179
+ providerType: state.type,
180
+ providerName: state.name,
181
+ kind: 'agent',
182
+ transport: 'pty',
183
+ status: normalizeManagedStatus(activeChat?.status || state.status, {
184
+ activeModal: activeChat?.activeModal || null,
185
+ }),
186
+ title: activeChat?.title || state.name,
187
+ workspace: state.workspace || null,
188
+ activeChat,
189
+ capabilities: PTY_SESSION_CAPABILITIES,
190
+ errorMessage: state.errorMessage,
191
+ errorReason: state.errorReason,
192
+ };
164
193
  }
165
194
 
166
- /**
167
- * Convert AcpProviderState[] → ManagedAcpEntry[]
168
- */
169
- export function buildManagedAcps(
170
- acpStates: AcpProviderState[],
171
- ): ManagedAcpEntry[] {
172
- return acpStates.map((s) => ({
173
- id: s.instanceId,
174
- acpType: s.type,
175
- acpName: s.name,
176
- status: normalizeManagedStatus(s.status, { activeModal: s.activeChat?.activeModal || null }),
177
- mode: 'chat' as const,
178
- workspace: s.workspace || '',
179
- activeChat: normalizeActiveChatData(s.activeChat),
180
- currentModel: s.currentModel,
181
- currentPlan: s.currentPlan,
182
- acpConfigOptions: s.acpConfigOptions,
183
- acpModes: s.acpModes,
184
- errorMessage: s.errorMessage,
185
- errorReason: s.errorReason,
186
- }));
195
+ function buildAcpSession(state: AcpProviderState): SessionEntry {
196
+ const activeChat = normalizeActiveChatData(state.activeChat);
197
+ return {
198
+ id: state.instanceId,
199
+ parentId: null,
200
+ providerType: state.type,
201
+ providerName: state.name,
202
+ kind: 'agent',
203
+ transport: 'acp',
204
+ status: normalizeManagedStatus(activeChat?.status || state.status, {
205
+ activeModal: activeChat?.activeModal || null,
206
+ }),
207
+ title: activeChat?.title || state.name,
208
+ workspace: state.workspace || null,
209
+ activeChat,
210
+ capabilities: ACP_SESSION_CAPABILITIES,
211
+ currentModel: state.currentModel,
212
+ currentPlan: state.currentPlan,
213
+ acpConfigOptions: state.acpConfigOptions,
214
+ acpModes: state.acpModes,
215
+ errorMessage: state.errorMessage,
216
+ errorReason: state.errorReason,
217
+ };
187
218
  }
188
219
 
189
- /**
190
- * Convenience: collect & build all managed entries from instanceManager
191
- */
192
- export function buildAllManagedEntries(
220
+ export function buildSessionEntries(
193
221
  allStates: ProviderState[],
194
222
  cdpManagers: Map<string, DaemonCdpManager>,
195
- opts?: { detectedIdes?: { id: string; installed: boolean }[] },
196
- ): {
197
- managedIdes: ManagedIdeEntry[];
198
- managedClis: ManagedCliEntry[];
199
- managedAcps: ManagedAcpEntry[];
200
- } {
223
+ ): SessionEntry[] {
224
+ const sessions: SessionEntry[] = [];
225
+
201
226
  const ideStates = allStates.filter((s): s is IdeProviderState => s.category === 'ide');
202
227
  const cliStates = allStates.filter((s): s is CliProviderState => s.category === 'cli');
203
228
  const acpStates = allStates.filter((s): s is AcpProviderState => s.category === 'acp');
204
229
 
205
- return {
206
- managedIdes: buildManagedIdes(ideStates, cdpManagers, opts),
207
- managedClis: buildManagedClis(cliStates),
208
- managedAcps: buildManagedAcps(acpStates),
209
- };
230
+ for (const state of ideStates) {
231
+ sessions.push(buildIdeWorkspaceSession(state, cdpManagers));
232
+ for (const ext of state.extensions as ExtensionProviderState[]) {
233
+ sessions.push(buildExtensionAgentSession(state, ext));
234
+ }
235
+ }
236
+
237
+ for (const state of cliStates) {
238
+ sessions.push(buildCliSession(state));
239
+ }
240
+
241
+ for (const state of acpStates) {
242
+ sessions.push(buildAcpSession(state));
243
+ }
244
+
245
+ return sessions;
210
246
  }
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { LOG } from '../logging/logger.js';
9
- import { buildAllManagedEntries } from './builders.js';
9
+ import { buildSessionEntries } from './builders.js';
10
10
  import { buildStatusSnapshot } from './snapshot.js';
11
11
  import type {
12
12
  ProviderState,
@@ -152,7 +152,7 @@ export class DaemonStatusReporter {
152
152
  }
153
153
 
154
154
  // IDE/CLI/ACP states → managed entries (shared builder)
155
- const { managedIdes, managedClis, managedAcps } = buildAllManagedEntries(
155
+ const sessions = buildSessionEntries(
156
156
  allStates,
157
157
  this.deps.cdpManagers as Map<string, any>,
158
158
  );
@@ -189,19 +189,20 @@ export class DaemonStatusReporter {
189
189
  if (opts?.p2pOnly) return;
190
190
  const wsPayload = {
191
191
  daemonMode: true,
192
- // managedIdes: server only saves id, type, cdpConnected
193
- managedIdes: managedIdes.map(ide => ({
194
- ideType: ide.ideType,
195
- instanceId: ide.instanceId,
196
- cdpConnected: ide.cdpConnected,
197
- })),
198
- // managedClis: server only saves id, type, name
199
- managedClis: managedClis.map(c => ({
200
- id: c.id, cliType: c.cliType, cliName: c.cliName,
201
- })),
202
- // managedAcps: server only saves id, type, name
203
- managedAcps: managedAcps?.map((a: any) => ({
204
- id: a.id, acpType: a.acpType, acpName: a.acpName,
192
+ sessions: sessions.map((session) => ({
193
+ id: session.id,
194
+ parentId: session.parentId,
195
+ providerType: session.providerType,
196
+ providerName: session.providerName,
197
+ kind: session.kind,
198
+ transport: session.transport,
199
+ status: session.status,
200
+ workspace: session.workspace,
201
+ title: session.title,
202
+ cdpConnected: session.cdpConnected,
203
+ currentModel: session.currentModel,
204
+ currentPlan: session.currentPlan,
205
+ currentAutoApprove: session.currentAutoApprove,
205
206
  })),
206
207
  p2p: payload.p2p,
207
208
  timestamp: now,
@@ -11,7 +11,7 @@ import { loadConfig } from '../config/config.js';
11
11
  import { getWorkspaceState } from '../config/workspaces.js';
12
12
  import { getWorkspaceActivity } from '../config/workspace-activity.js';
13
13
  import { getHostMemorySnapshot } from '../system/host-memory.js';
14
- import { buildAllManagedEntries, isCdpConnected } from './builders.js';
14
+ import { buildSessionEntries, isCdpConnected } from './builders.js';
15
15
  import type { ProviderState } from '../providers/provider-instance.js';
16
16
  import type {
17
17
  AvailableProviderInfo,
@@ -80,15 +80,9 @@ export function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnaps
80
80
  const cfg = loadConfig();
81
81
  const wsState = getWorkspaceState(cfg);
82
82
  const memSnap = getHostMemorySnapshot();
83
- const { managedIdes, managedClis, managedAcps } = buildAllManagedEntries(
83
+ const sessions = buildSessionEntries(
84
84
  options.allStates,
85
85
  options.cdpManagers as Map<string, any>,
86
- {
87
- detectedIdes: options.detectedIdes.map((ide) => ({
88
- id: ide.id,
89
- installed: ide.installed !== false,
90
- })),
91
- },
92
86
  );
93
87
 
94
88
  return {
@@ -111,9 +105,7 @@ export function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnaps
111
105
  timestamp: options.timestamp ?? Date.now(),
112
106
  detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
113
107
  ...(options.p2p ? { p2p: options.p2p } : {}),
114
- managedIdes,
115
- managedClis,
116
- managedAcps,
108
+ sessions,
117
109
  workspaces: wsState.workspaces,
118
110
  defaultWorkspaceId: wsState.defaultWorkspaceId,
119
111
  defaultWorkspacePath: wsState.defaultWorkspacePath,