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