@adhdev/daemon-core 0.6.79 → 0.7.0
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 +84 -87
- package/dist/index.d.ts +84 -87
- package/dist/index.js +798 -706
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +797 -702
- package/dist/index.mjs.map +1 -1
- package/dist/{normalize-igHDb198.d.mts → normalize-S2PmiRgB.d.mts} +32 -53
- package/dist/{normalize-igHDb198.d.ts → normalize-S2PmiRgB.d.ts} +32 -53
- package/dist/status/normalize.d.mts +1 -1
- package/dist/status/normalize.d.ts +1 -1
- package/package.json +1 -1
- package/src/agent-stream/manager.ts +203 -180
- package/src/agent-stream/poller.ts +45 -22
- package/src/boot/daemon-lifecycle.ts +28 -9
- package/src/cdp/initializer.ts +47 -0
- package/src/cdp/manager.ts +19 -1
- package/src/cdp/setup.ts +26 -11
- package/src/commands/chat-commands.ts +136 -88
- package/src/commands/cli-manager.ts +31 -6
- package/src/commands/handler.ts +69 -138
- package/src/commands/router.ts +4 -20
- package/src/commands/stream-commands.ts +34 -162
- package/src/daemon-core.ts +3 -9
- package/src/index.ts +6 -5
- package/src/logging/command-log.ts +1 -1
- package/src/providers/acp-provider-instance.ts +4 -0
- package/src/providers/provider-instance-manager.ts +1 -0
- package/src/sessions/registry.ts +76 -0
- package/src/shared-types.ts +45 -54
- package/src/status/builders.ts +156 -120
- package/src/status/reporter.ts +16 -15
- package/src/status/snapshot.ts +3 -11
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { DaemonCdpManager, AgentWebviewTarget } from '../cdp/manager.js';
|
|
12
12
|
import { ProviderLoader } from '../providers/provider-loader.js';
|
|
13
13
|
import { ProviderStreamAdapter } from './provider-adapter.js';
|
|
14
|
+
import { SessionRegistry } from '../sessions/registry.js';
|
|
14
15
|
import { LOG } from '../logging/logger.js';
|
|
15
16
|
import type {
|
|
16
17
|
IAgentStreamAdapter,
|
|
@@ -21,7 +22,9 @@ import type {
|
|
|
21
22
|
|
|
22
23
|
export interface ManagedAgent {
|
|
23
24
|
adapter: IAgentStreamAdapter;
|
|
24
|
-
|
|
25
|
+
runtimeSessionId: string;
|
|
26
|
+
parentSessionId: string;
|
|
27
|
+
cdpSessionId: string;
|
|
25
28
|
target: AgentWebviewTarget;
|
|
26
29
|
lastState: AgentStreamState | null;
|
|
27
30
|
lastError: string | null;
|
|
@@ -29,15 +32,19 @@ export interface ManagedAgent {
|
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
export class DaemonAgentStreamManager {
|
|
32
|
-
private
|
|
33
|
-
private
|
|
35
|
+
private adaptersByType = new Map<string, IAgentStreamAdapter>();
|
|
36
|
+
private managedBySessionId = new Map<string, ManagedAgent>();
|
|
34
37
|
private enabled = true;
|
|
35
38
|
private logFn: (msg: string) => void;
|
|
36
|
-
private
|
|
37
|
-
private
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
constructor(
|
|
39
|
+
private lastDiscoveryTimeByParent = new Map<string, number>();
|
|
40
|
+
private discoveryIntervalMsByParent = new Map<string, number>();
|
|
41
|
+
private activeSessionIdByParent = new Map<string, string | null>();
|
|
42
|
+
|
|
43
|
+
constructor(
|
|
44
|
+
logFn?: (msg: string) => void,
|
|
45
|
+
providerLoader?: ProviderLoader,
|
|
46
|
+
private readonly sessionRegistry?: SessionRegistry,
|
|
47
|
+
) {
|
|
41
48
|
this.logFn = logFn || LOG.forComponent('AgentStream').asLogFn();
|
|
42
49
|
|
|
43
50
|
// Create adapter for all extension providers
|
|
@@ -48,7 +55,7 @@ export class DaemonAgentStreamManager {
|
|
|
48
55
|
const resolved = providerLoader.resolve(p.type);
|
|
49
56
|
if (!resolved) continue;
|
|
50
57
|
const adapter = new ProviderStreamAdapter(resolved);
|
|
51
|
-
this.
|
|
58
|
+
this.adaptersByType.set(p.type, adapter);
|
|
52
59
|
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name}) scripts=${Object.keys(resolved.scripts || {}).join(',') || 'none'}`);
|
|
53
60
|
}
|
|
54
61
|
}
|
|
@@ -56,274 +63,290 @@ export class DaemonAgentStreamManager {
|
|
|
56
63
|
|
|
57
64
|
setEnabled(enabled: boolean) { this.enabled = enabled; }
|
|
58
65
|
get isEnabled() { return this.enabled; }
|
|
59
|
-
|
|
60
|
-
return this.
|
|
66
|
+
getActiveSessionId(parentSessionId: string): string | null {
|
|
67
|
+
return this.activeSessionIdByParent.get(parentSessionId) || null;
|
|
61
68
|
}
|
|
62
69
|
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
if (!managed) {
|
|
66
|
-
managed = new Map<string, ManagedAgent>();
|
|
67
|
-
this.managedByScope.set(scopeKey, managed);
|
|
68
|
-
}
|
|
69
|
-
return managed;
|
|
70
|
+
private getSessionTarget(sessionId: string) {
|
|
71
|
+
return this.sessionRegistry?.get(sessionId);
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
76
|
-
|
|
74
|
+
resetParentSession(parentSessionId: string): void {
|
|
75
|
+
const activeSessionId = this.activeSessionIdByParent.get(parentSessionId);
|
|
76
|
+
if (activeSessionId) this.managedBySessionId.delete(activeSessionId);
|
|
77
|
+
for (const child of this.sessionRegistry?.listChildren(parentSessionId) || []) {
|
|
78
|
+
this.managedBySessionId.delete(child.sessionId);
|
|
79
|
+
}
|
|
80
|
+
this.activeSessionIdByParent.delete(parentSessionId);
|
|
81
|
+
this.lastDiscoveryTimeByParent.delete(parentSessionId);
|
|
82
|
+
this.discoveryIntervalMsByParent.delete(parentSessionId);
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
/** Panel focus based on provider.js focusPanel or extensionId (currently no-op) */
|
|
80
|
-
async
|
|
86
|
+
async ensureSessionPanelOpen(_sessionId: string): Promise<void> {
|
|
81
87
|
// Extension was removed, so localServer-based panel focus no longer works
|
|
82
88
|
// Can be replaced with CDP-based focus (future implementation)
|
|
83
89
|
}
|
|
84
90
|
|
|
85
|
-
async
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
if (previousAgentType === agentType) return;
|
|
91
|
+
async setActiveSession(cdp: DaemonCdpManager, parentSessionId: string, sessionId: string | null): Promise<void> {
|
|
92
|
+
const previousSessionId = this.getActiveSessionId(parentSessionId);
|
|
93
|
+
if (previousSessionId === sessionId) return;
|
|
89
94
|
|
|
90
|
-
if (
|
|
91
|
-
const prev =
|
|
95
|
+
if (previousSessionId) {
|
|
96
|
+
const prev = this.managedBySessionId.get(previousSessionId);
|
|
92
97
|
if (prev) {
|
|
93
|
-
try { await cdp.detachAgent(prev.
|
|
94
|
-
|
|
95
|
-
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName} (${
|
|
98
|
+
try { await cdp.detachAgent(prev.cdpSessionId); } catch { }
|
|
99
|
+
this.managedBySessionId.delete(previousSessionId);
|
|
100
|
+
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName} (${parentSessionId})`);
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
103
|
|
|
99
|
-
this.
|
|
100
|
-
this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
this.activeSessionIdByParent.set(parentSessionId, sessionId);
|
|
105
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
106
|
+
this.logFn(`[AgentStream] Active session (${parentSessionId}): ${sessionId || 'none'}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private resolveSessionIdForTarget(parentSessionId: string, agentType: string): string | null {
|
|
110
|
+
const child = (this.sessionRegistry?.listChildren(parentSessionId) || [])
|
|
111
|
+
.find((entry) => entry.providerCategory === 'extension' && entry.providerType === agentType);
|
|
112
|
+
return child?.sessionId || null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private async connectManagedSession(
|
|
116
|
+
cdp: DaemonCdpManager,
|
|
117
|
+
parentSessionId: string,
|
|
118
|
+
runtimeSessionId: string,
|
|
119
|
+
): Promise<ManagedAgent | null> {
|
|
120
|
+
const target = this.getSessionTarget(runtimeSessionId);
|
|
121
|
+
if (!target || target.providerCategory !== 'extension') return null;
|
|
122
|
+
const adapter = this.adaptersByType.get(target.providerType);
|
|
123
|
+
if (!adapter) return null;
|
|
124
|
+
const targets = await cdp.discoverAgentWebviews();
|
|
125
|
+
const activeTarget = targets.find((entry) => entry.agentType === target.providerType);
|
|
126
|
+
if (!activeTarget) return null;
|
|
127
|
+
const cdpSessionId = await cdp.attachToAgent(activeTarget);
|
|
128
|
+
if (!cdpSessionId) return null;
|
|
129
|
+
const managed: ManagedAgent = {
|
|
130
|
+
adapter,
|
|
131
|
+
runtimeSessionId,
|
|
132
|
+
parentSessionId,
|
|
133
|
+
cdpSessionId,
|
|
134
|
+
target: activeTarget,
|
|
135
|
+
lastState: null,
|
|
136
|
+
lastError: null,
|
|
137
|
+
lastHiddenCheckTime: 0,
|
|
138
|
+
};
|
|
139
|
+
this.managedBySessionId.set(runtimeSessionId, managed);
|
|
140
|
+
this.logFn(`[AgentStream] Connected: ${adapter.agentName} (${parentSessionId})`);
|
|
141
|
+
return managed;
|
|
105
142
|
}
|
|
106
143
|
|
|
107
|
-
|
|
108
|
-
async
|
|
109
|
-
const
|
|
110
|
-
if (!this.enabled || !
|
|
144
|
+
/** Agent webview discovery + session connection */
|
|
145
|
+
async syncActiveSession(cdp: DaemonCdpManager, parentSessionId: string): Promise<void> {
|
|
146
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
147
|
+
if (!this.enabled || !activeSessionId) return;
|
|
111
148
|
|
|
112
149
|
const now = Date.now();
|
|
113
|
-
const managed = this.
|
|
114
|
-
const lastDiscoveryTime = this.
|
|
115
|
-
const discoveryIntervalMs = this.
|
|
116
|
-
if (managed
|
|
150
|
+
const managed = this.managedBySessionId.get(activeSessionId);
|
|
151
|
+
const lastDiscoveryTime = this.lastDiscoveryTimeByParent.get(parentSessionId) || 0;
|
|
152
|
+
const discoveryIntervalMs = this.discoveryIntervalMsByParent.get(parentSessionId) || 10_000;
|
|
153
|
+
if (managed && (now - lastDiscoveryTime) < discoveryIntervalMs) {
|
|
117
154
|
return;
|
|
118
155
|
}
|
|
119
|
-
this.
|
|
156
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, now);
|
|
120
157
|
|
|
121
158
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (activeTarget && !managed.has(activeAgentType)) {
|
|
126
|
-
const adapter = this.allAdapters.find(a => a.agentType === activeAgentType);
|
|
127
|
-
if (adapter) {
|
|
128
|
-
const sessionId = await cdp.attachToAgent(activeTarget);
|
|
129
|
-
if (sessionId) {
|
|
130
|
-
managed.set(activeAgentType, {
|
|
131
|
-
adapter,
|
|
132
|
-
sessionId,
|
|
133
|
-
target: activeTarget,
|
|
134
|
-
lastState: null,
|
|
135
|
-
lastError: null,
|
|
136
|
-
lastHiddenCheckTime: 0,
|
|
137
|
-
});
|
|
138
|
-
this.logFn(`[AgentStream] Connected: ${adapter.agentName} (${scopeKey})`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Cleanup inactive agents
|
|
144
|
-
for (const [type, agent] of managed) {
|
|
145
|
-
if (type !== activeAgentType) {
|
|
146
|
-
await cdp.detachAgent(agent.sessionId);
|
|
147
|
-
managed.delete(type);
|
|
148
|
-
}
|
|
159
|
+
if (!managed) {
|
|
160
|
+
await this.connectManagedSession(cdp, parentSessionId, activeSessionId);
|
|
149
161
|
}
|
|
150
|
-
|
|
151
|
-
this.discoveryIntervalMsByScope.set(scopeKey, managed.has(activeAgentType) ? 30_000 : 10_000);
|
|
162
|
+
this.discoveryIntervalMsByParent.set(parentSessionId, this.managedBySessionId.has(activeSessionId) ? 30_000 : 10_000);
|
|
152
163
|
} catch (e) {
|
|
153
|
-
this.logFn(`[AgentStream] sync error (${
|
|
164
|
+
this.logFn(`[AgentStream] sync error (${parentSessionId}): ${(e as Error).message}`);
|
|
154
165
|
}
|
|
155
166
|
}
|
|
156
167
|
|
|
157
|
-
|
|
158
|
-
async
|
|
159
|
-
if (!this.enabled) return
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
/** Collect active extension session state */
|
|
169
|
+
async collectActiveSession(cdp: DaemonCdpManager, parentSessionId: string): Promise<AgentStreamState | null> {
|
|
170
|
+
if (!this.enabled) return null;
|
|
171
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
172
|
+
if (!activeSessionId) return null;
|
|
173
|
+
let agent = this.managedBySessionId.get(activeSessionId);
|
|
174
|
+
if (!agent) {
|
|
175
|
+
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || undefined;
|
|
176
|
+
}
|
|
177
|
+
if (!agent) return null;
|
|
178
|
+
const type = agent.adapter.agentType;
|
|
179
|
+
const isHidden = agent.lastState?.status === 'panel_hidden';
|
|
180
|
+
const hiddenCacheFresh = isHidden && (Date.now() - agent.lastHiddenCheckTime < 30000);
|
|
168
181
|
|
|
169
|
-
|
|
170
|
-
const hiddenCacheFresh = isHidden && (Date.now() - agent.lastHiddenCheckTime < 30000);
|
|
182
|
+
if (hiddenCacheFresh) return agent.lastState!;
|
|
171
183
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
agent.lastError = null;
|
|
182
|
-
if (state.status === 'panel_hidden') {
|
|
183
|
-
agent.lastHiddenCheckTime = Date.now();
|
|
184
|
-
}
|
|
185
|
-
results.push(state);
|
|
186
|
-
} catch (e) {
|
|
187
|
-
const errorMsg = (e as Error)?.message || String(e);
|
|
188
|
-
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
189
|
-
agent.lastError = errorMsg;
|
|
190
|
-
results.push({
|
|
191
|
-
agentType: type,
|
|
192
|
-
agentName: agent.adapter.agentName,
|
|
193
|
-
extensionId: agent.adapter.extensionId,
|
|
194
|
-
status: 'disconnected',
|
|
195
|
-
messages: agent.lastState?.messages || [],
|
|
196
|
-
inputContent: '',
|
|
197
|
-
});
|
|
198
|
-
if (errorMsg.includes('timeout') || errorMsg.includes('not connected') || errorMsg.includes('Session')) {
|
|
199
|
-
try { await cdp.detachAgent(agent.sessionId); } catch { }
|
|
200
|
-
managed.delete(type);
|
|
201
|
-
this.lastDiscoveryTimeByScope.set(scopeKey, 0);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
184
|
+
try {
|
|
185
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
186
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
187
|
+
const state = await agent.adapter.readChat(evaluate);
|
|
188
|
+
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') : ''}`);
|
|
189
|
+
agent.lastState = state;
|
|
190
|
+
agent.lastError = null;
|
|
191
|
+
if (state.status === 'panel_hidden') {
|
|
192
|
+
agent.lastHiddenCheckTime = Date.now();
|
|
204
193
|
}
|
|
194
|
+
return state;
|
|
195
|
+
} catch (e) {
|
|
196
|
+
const errorMsg = (e as Error)?.message || String(e);
|
|
197
|
+
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
198
|
+
agent.lastError = errorMsg;
|
|
199
|
+
if (errorMsg.includes('timeout') || errorMsg.includes('not connected') || errorMsg.includes('Session')) {
|
|
200
|
+
try { await cdp.detachAgent(agent.cdpSessionId); } catch { }
|
|
201
|
+
this.managedBySessionId.delete(activeSessionId);
|
|
202
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
agentType: type,
|
|
206
|
+
agentName: agent.adapter.agentName,
|
|
207
|
+
extensionId: agent.adapter.extensionId,
|
|
208
|
+
status: 'disconnected',
|
|
209
|
+
messages: agent.lastState?.messages || [],
|
|
210
|
+
inputContent: '',
|
|
211
|
+
};
|
|
205
212
|
}
|
|
206
|
-
|
|
207
|
-
return results;
|
|
208
213
|
}
|
|
209
214
|
|
|
210
|
-
async
|
|
211
|
-
await this.
|
|
212
|
-
const
|
|
215
|
+
async sendToSession(cdp: DaemonCdpManager, sessionId: string, text: string): Promise<boolean> {
|
|
216
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
217
|
+
const target = this.getSessionTarget(sessionId);
|
|
218
|
+
if (!target?.parentSessionId) return false;
|
|
219
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
220
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
221
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
213
222
|
if (!agent) return false;
|
|
214
223
|
try {
|
|
215
224
|
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
216
|
-
cdp.evaluateInSessionFrame(agent.
|
|
225
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
217
226
|
await agent.adapter.sendMessage(evaluate, text);
|
|
218
227
|
return true;
|
|
219
228
|
} catch (e) {
|
|
220
|
-
this.logFn(`[AgentStream]
|
|
229
|
+
this.logFn(`[AgentStream] sendToSession(${sessionId}) error: ${(e as Error).message}`);
|
|
221
230
|
return false;
|
|
222
231
|
}
|
|
223
232
|
}
|
|
224
233
|
|
|
225
|
-
async
|
|
226
|
-
await this.
|
|
227
|
-
const
|
|
234
|
+
async resolveSessionAction(cdp: DaemonCdpManager, sessionId: string, action: 'approve' | 'reject'): Promise<boolean> {
|
|
235
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
236
|
+
const target = this.getSessionTarget(sessionId);
|
|
237
|
+
if (!target?.parentSessionId) return false;
|
|
238
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
239
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
240
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
228
241
|
if (!agent) return false;
|
|
229
242
|
try {
|
|
230
243
|
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
231
|
-
cdp.evaluateInSessionFrame(agent.
|
|
244
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
232
245
|
return await agent.adapter.resolveAction(evaluate, action);
|
|
233
246
|
} catch (e) {
|
|
234
|
-
this.logFn(`[AgentStream] resolveAction(${
|
|
247
|
+
this.logFn(`[AgentStream] resolveAction(${sessionId}) error: ${(e as Error).message}`);
|
|
235
248
|
return false;
|
|
236
249
|
}
|
|
237
250
|
}
|
|
238
251
|
|
|
239
|
-
async
|
|
240
|
-
await this.
|
|
241
|
-
const
|
|
252
|
+
async newSession(cdp: DaemonCdpManager, sessionId: string): Promise<boolean> {
|
|
253
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
254
|
+
const target = this.getSessionTarget(sessionId);
|
|
255
|
+
if (!target?.parentSessionId) return false;
|
|
256
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
257
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
258
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
242
259
|
if (!agent) return false;
|
|
243
260
|
try {
|
|
244
261
|
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
245
|
-
cdp.evaluateInSessionFrame(agent.
|
|
262
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
246
263
|
await agent.adapter.newSession(evaluate);
|
|
247
264
|
return true;
|
|
248
265
|
} catch (e) {
|
|
249
|
-
this.logFn(`[AgentStream] newSession(${
|
|
266
|
+
this.logFn(`[AgentStream] newSession(${sessionId}) error: ${(e as Error).message}`);
|
|
250
267
|
return false;
|
|
251
268
|
}
|
|
252
269
|
}
|
|
253
270
|
|
|
254
|
-
async
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
await this.syncAgentSessions(cdp, scopeKey);
|
|
261
|
-
agent = this.getManagedAgent(agentType, scopeKey);
|
|
262
|
-
}
|
|
271
|
+
async listSessionChats(cdp: DaemonCdpManager, sessionId: string): Promise<AgentChatListItem[]> {
|
|
272
|
+
const target = this.getSessionTarget(sessionId);
|
|
273
|
+
if (!target?.parentSessionId) return [];
|
|
274
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
275
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
276
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
263
277
|
if (!agent || typeof agent.adapter.listChats !== 'function') return [];
|
|
264
278
|
try {
|
|
265
279
|
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
266
|
-
cdp.evaluateInSessionFrame(agent
|
|
280
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
267
281
|
return await agent.adapter.listChats(evaluate);
|
|
268
282
|
} catch (e) {
|
|
269
|
-
this.logFn(`[AgentStream] listChats(${
|
|
283
|
+
this.logFn(`[AgentStream] listChats(${sessionId}) error: ${(e as Error).message}`);
|
|
270
284
|
return [];
|
|
271
285
|
}
|
|
272
286
|
}
|
|
273
287
|
|
|
274
|
-
async
|
|
275
|
-
|
|
276
|
-
if (!
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
agent = this.getManagedAgent(agentType, scopeKey);
|
|
281
|
-
}
|
|
288
|
+
async switchConversation(cdp: DaemonCdpManager, sessionId: string, conversationId: string): Promise<boolean> {
|
|
289
|
+
const target = this.getSessionTarget(sessionId);
|
|
290
|
+
if (!target?.parentSessionId) return false;
|
|
291
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
292
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
293
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
282
294
|
if (!agent || typeof agent.adapter.switchSession !== 'function') return false;
|
|
283
295
|
try {
|
|
284
296
|
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
285
|
-
cdp.evaluateInSessionFrame(agent
|
|
286
|
-
return await agent.adapter.switchSession(evaluate,
|
|
297
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
298
|
+
return await agent.adapter.switchSession(evaluate, conversationId);
|
|
287
299
|
} catch (e) {
|
|
288
|
-
this.logFn(`[AgentStream] switchSession(${
|
|
300
|
+
this.logFn(`[AgentStream] switchSession(${sessionId}) error: ${(e as Error).message}`);
|
|
289
301
|
return false;
|
|
290
302
|
}
|
|
291
303
|
}
|
|
292
304
|
|
|
293
|
-
async
|
|
294
|
-
const
|
|
305
|
+
async focusSession(cdp: DaemonCdpManager, sessionId: string): Promise<boolean> {
|
|
306
|
+
const target = this.getSessionTarget(sessionId);
|
|
307
|
+
if (!target?.parentSessionId) return false;
|
|
308
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
309
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
310
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
295
311
|
if (!agent || typeof agent.adapter.focusEditor !== 'function') return false;
|
|
296
312
|
try {
|
|
297
313
|
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
298
|
-
cdp.evaluateInSessionFrame(agent.
|
|
314
|
+
cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
299
315
|
await agent.adapter.focusEditor(evaluate);
|
|
300
316
|
return true;
|
|
301
317
|
} catch (e) {
|
|
302
|
-
this.logFn(`[AgentStream] focusEditor(${
|
|
318
|
+
this.logFn(`[AgentStream] focusEditor(${sessionId}) error: ${(e as Error).message}`);
|
|
303
319
|
return false;
|
|
304
320
|
}
|
|
305
321
|
}
|
|
306
322
|
|
|
307
|
-
|
|
308
|
-
if (
|
|
309
|
-
|
|
323
|
+
getConnectedSessions(parentSessionId?: string): string[] {
|
|
324
|
+
if (parentSessionId) {
|
|
325
|
+
return [...this.managedBySessionId.values()]
|
|
326
|
+
.filter((entry) => entry.parentSessionId === parentSessionId)
|
|
327
|
+
.map((entry) => entry.runtimeSessionId);
|
|
328
|
+
}
|
|
329
|
+
return [...this.managedBySessionId.keys()];
|
|
310
330
|
}
|
|
311
331
|
|
|
312
|
-
|
|
313
|
-
return this.
|
|
332
|
+
getManagedSession(sessionId: string): ManagedAgent | undefined {
|
|
333
|
+
return this.managedBySessionId.get(sessionId);
|
|
314
334
|
}
|
|
315
335
|
|
|
316
336
|
async dispose(cdpManagers: Map<string, DaemonCdpManager>): Promise<void> {
|
|
317
|
-
for (const
|
|
318
|
-
const
|
|
337
|
+
for (const managed of this.managedBySessionId.values()) {
|
|
338
|
+
const managerKey = this.getSessionTarget(managed.runtimeSessionId)?.cdpManagerKey;
|
|
339
|
+
const cdp = managerKey ? cdpManagers.get(managerKey) : null;
|
|
319
340
|
if (!cdp) continue;
|
|
320
|
-
|
|
321
|
-
try { await cdp.detachAgent(agent.sessionId); } catch { }
|
|
322
|
-
}
|
|
341
|
+
try { await cdp.detachAgent(managed.cdpSessionId); } catch { }
|
|
323
342
|
}
|
|
324
|
-
this.
|
|
325
|
-
this.
|
|
326
|
-
this.
|
|
327
|
-
this.
|
|
343
|
+
this.managedBySessionId.clear();
|
|
344
|
+
this.activeSessionIdByParent.clear();
|
|
345
|
+
this.lastDiscoveryTimeByParent.clear();
|
|
346
|
+
this.discoveryIntervalMsByParent.clear();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
resolveSessionForAgent(parentSessionId: string, agentType: string): string | null {
|
|
350
|
+
return this.resolveSessionIdForTarget(parentSessionId, agentType);
|
|
328
351
|
}
|
|
329
352
|
}
|