@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/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
package/dist/index.js
CHANGED
|
@@ -1788,10 +1788,7 @@ __export(index_exports, {
|
|
|
1788
1788
|
ProviderLoader: () => ProviderLoader,
|
|
1789
1789
|
VersionArchive: () => VersionArchive,
|
|
1790
1790
|
addCliHistory: () => addCliHistory,
|
|
1791
|
-
|
|
1792
|
-
buildManagedAcps: () => buildManagedAcps,
|
|
1793
|
-
buildManagedClis: () => buildManagedClis,
|
|
1794
|
-
buildManagedIdes: () => buildManagedIdes,
|
|
1791
|
+
buildSessionEntries: () => buildSessionEntries,
|
|
1795
1792
|
buildStatusSnapshot: () => buildStatusSnapshot,
|
|
1796
1793
|
connectCdpManager: () => connectCdpManager,
|
|
1797
1794
|
detectAllVersions: () => detectAllVersions,
|
|
@@ -2859,7 +2856,11 @@ var DaemonCdpManager = class {
|
|
|
2859
2856
|
async attachToAgent(target) {
|
|
2860
2857
|
if (!this.isConnected) return null;
|
|
2861
2858
|
for (const [sid, t] of this.agentSessions) {
|
|
2862
|
-
if (t.
|
|
2859
|
+
if (t.targetId === target.targetId) return sid;
|
|
2860
|
+
if (t.agentType === target.agentType && t.targetId !== target.targetId) {
|
|
2861
|
+
await this.detachAgent(sid).catch(() => {
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2863
2864
|
}
|
|
2864
2865
|
try {
|
|
2865
2866
|
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
@@ -2983,6 +2984,20 @@ var DaemonCdpManager = class {
|
|
|
2983
2984
|
}
|
|
2984
2985
|
async getCurrentPageWebviewUrls() {
|
|
2985
2986
|
if (!this.isConnected) return /* @__PURE__ */ new Set();
|
|
2987
|
+
try {
|
|
2988
|
+
const urls = /* @__PURE__ */ new Set();
|
|
2989
|
+
const { frameTree } = await this.sendInternal("Page.getFrameTree", {}, 5e3);
|
|
2990
|
+
const visit = (node) => {
|
|
2991
|
+
const url = node?.frame?.url;
|
|
2992
|
+
if (typeof url === "string" && url.includes("vscode-webview")) {
|
|
2993
|
+
urls.add(url);
|
|
2994
|
+
}
|
|
2995
|
+
for (const child of node?.childFrames || []) visit(child);
|
|
2996
|
+
};
|
|
2997
|
+
if (frameTree) visit(frameTree);
|
|
2998
|
+
if (urls.size > 0) return urls;
|
|
2999
|
+
} catch {
|
|
3000
|
+
}
|
|
2986
3001
|
try {
|
|
2987
3002
|
const raw = await this.evaluate(
|
|
2988
3003
|
`JSON.stringify(Array.from(document.querySelectorAll('iframe,webview'))
|
|
@@ -4134,7 +4149,7 @@ function registerExtensionProviders(providerLoader, manager, ideType) {
|
|
|
4134
4149
|
manager.setExtensionProviders(enabledExtProviders);
|
|
4135
4150
|
}
|
|
4136
4151
|
async function setupIdeInstance(ctx, opts) {
|
|
4137
|
-
const { providerLoader, instanceManager,
|
|
4152
|
+
const { providerLoader, instanceManager, sessionRegistry } = ctx;
|
|
4138
4153
|
const { ideType, manager, settings } = opts;
|
|
4139
4154
|
const managerKey = opts.managerKey || ideType;
|
|
4140
4155
|
registerExtensionProviders(providerLoader, manager, ideType);
|
|
@@ -4150,14 +4165,30 @@ async function setupIdeInstance(ctx, opts) {
|
|
|
4150
4165
|
serverConn: ctx.serverConn,
|
|
4151
4166
|
settings: resolvedSettings
|
|
4152
4167
|
});
|
|
4153
|
-
|
|
4168
|
+
sessionRegistry.register({
|
|
4169
|
+
sessionId: ideInstance.getInstanceId(),
|
|
4170
|
+
parentSessionId: null,
|
|
4171
|
+
providerType: ideType,
|
|
4172
|
+
providerCategory: "ide",
|
|
4173
|
+
transport: "cdp-page",
|
|
4174
|
+
cdpManagerKey: managerKey,
|
|
4175
|
+
instanceKey: `ide:${managerKey}`
|
|
4176
|
+
});
|
|
4154
4177
|
const extensionProviders = providerLoader.getEnabledByCategory("extension", ideType);
|
|
4155
4178
|
for (const extProvider of extensionProviders) {
|
|
4156
4179
|
const extSettings = providerLoader.getSettings(extProvider.type);
|
|
4157
4180
|
await ideInstance.addExtension(extProvider, extSettings);
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4181
|
+
}
|
|
4182
|
+
for (const ext of ideInstance.getExtensionInstances()) {
|
|
4183
|
+
sessionRegistry.register({
|
|
4184
|
+
sessionId: ext.getInstanceId(),
|
|
4185
|
+
parentSessionId: ideInstance.getInstanceId(),
|
|
4186
|
+
providerType: ext.type,
|
|
4187
|
+
providerCategory: "extension",
|
|
4188
|
+
transport: "cdp-webview",
|
|
4189
|
+
cdpManagerKey: managerKey,
|
|
4190
|
+
instanceKey: `ide:${managerKey}`
|
|
4191
|
+
});
|
|
4161
4192
|
}
|
|
4162
4193
|
return ideInstance;
|
|
4163
4194
|
}
|
|
@@ -4374,6 +4405,7 @@ var DaemonCdpInitializer = class {
|
|
|
4374
4405
|
async connectIdePort(port, ide) {
|
|
4375
4406
|
const { providerLoader, cdpManagers } = this.config;
|
|
4376
4407
|
const targets = await DaemonCdpManager.listAllTargets(port);
|
|
4408
|
+
await this.pruneStaleManagers(port, ide, targets);
|
|
4377
4409
|
if (targets.length === 0) {
|
|
4378
4410
|
if (cdpManagers.has(ide)) return;
|
|
4379
4411
|
if (!await probeCdpPort(port)) return;
|
|
@@ -4426,6 +4458,34 @@ var DaemonCdpInitializer = class {
|
|
|
4426
4458
|
}
|
|
4427
4459
|
}
|
|
4428
4460
|
}
|
|
4461
|
+
async pruneStaleManagers(port, ide, targets) {
|
|
4462
|
+
const trackedTargetIds = new Set(targets.map((target) => target.id));
|
|
4463
|
+
const removals = [];
|
|
4464
|
+
for (const [key, manager] of this.config.cdpManagers.entries()) {
|
|
4465
|
+
if (!(key === ide || key.startsWith(`${ide}_`))) continue;
|
|
4466
|
+
if (manager.getPort() !== port) continue;
|
|
4467
|
+
if (targets.length === 0) {
|
|
4468
|
+
removals.push({ key, manager, reason: "ide_closed" });
|
|
4469
|
+
continue;
|
|
4470
|
+
}
|
|
4471
|
+
if (manager.targetId && !trackedTargetIds.has(manager.targetId)) {
|
|
4472
|
+
removals.push({ key, manager, reason: "target_closed" });
|
|
4473
|
+
continue;
|
|
4474
|
+
}
|
|
4475
|
+
if (key === ide && !manager.targetId && targets.length > 1) {
|
|
4476
|
+
removals.push({ key, manager, reason: "target_rekeyed" });
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
4479
|
+
for (const { key, manager, reason } of removals) {
|
|
4480
|
+
try {
|
|
4481
|
+
manager.disconnect();
|
|
4482
|
+
} catch {
|
|
4483
|
+
}
|
|
4484
|
+
this.config.cdpManagers.delete(key);
|
|
4485
|
+
LOG.info("CDP", `Removed stale manager: ${key} (${reason})`);
|
|
4486
|
+
await this.config.onDisconnected?.(ide, manager, key, reason);
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4429
4489
|
// ─── Periodic scanning ───
|
|
4430
4490
|
/**
|
|
4431
4491
|
* Start periodic scanning for newly opened IDEs.
|
|
@@ -4529,95 +4589,152 @@ function isCdpConnected(cdpManagers, key) {
|
|
|
4529
4589
|
const m = findCdpManager(cdpManagers, key);
|
|
4530
4590
|
return m?.isConnected ?? false;
|
|
4531
4591
|
}
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4592
|
+
var IDE_SESSION_CAPABILITIES = [
|
|
4593
|
+
"read_chat",
|
|
4594
|
+
"send_message",
|
|
4595
|
+
"new_session",
|
|
4596
|
+
"list_sessions",
|
|
4597
|
+
"switch_session",
|
|
4598
|
+
"resolve_action",
|
|
4599
|
+
"change_model",
|
|
4600
|
+
"set_mode",
|
|
4601
|
+
"set_thought_level"
|
|
4602
|
+
];
|
|
4603
|
+
var EXTENSION_SESSION_CAPABILITIES = [
|
|
4604
|
+
"read_chat",
|
|
4605
|
+
"send_message",
|
|
4606
|
+
"new_session",
|
|
4607
|
+
"list_sessions",
|
|
4608
|
+
"switch_session",
|
|
4609
|
+
"resolve_action",
|
|
4610
|
+
"change_model",
|
|
4611
|
+
"set_mode"
|
|
4612
|
+
];
|
|
4613
|
+
var PTY_SESSION_CAPABILITIES = [
|
|
4614
|
+
"read_chat",
|
|
4615
|
+
"send_message",
|
|
4616
|
+
"resolve_action",
|
|
4617
|
+
"terminal_io",
|
|
4618
|
+
"resize_terminal"
|
|
4619
|
+
];
|
|
4620
|
+
var ACP_SESSION_CAPABILITIES = [
|
|
4621
|
+
"read_chat",
|
|
4622
|
+
"send_message",
|
|
4623
|
+
"new_session",
|
|
4624
|
+
"resolve_action",
|
|
4625
|
+
"change_model",
|
|
4626
|
+
"set_mode",
|
|
4627
|
+
"set_thought_level"
|
|
4628
|
+
];
|
|
4629
|
+
function buildIdeWorkspaceSession(state, cdpManagers) {
|
|
4630
|
+
const activeChat = normalizeActiveChatData(state.activeChat);
|
|
4631
|
+
const title = activeChat?.title || state.name;
|
|
4632
|
+
return {
|
|
4633
|
+
id: state.instanceId || state.type,
|
|
4634
|
+
parentId: null,
|
|
4635
|
+
providerType: state.type,
|
|
4636
|
+
providerName: state.name,
|
|
4637
|
+
kind: "workspace",
|
|
4638
|
+
transport: "cdp-page",
|
|
4639
|
+
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
4640
|
+
activeModal: activeChat?.activeModal || null
|
|
4641
|
+
}),
|
|
4642
|
+
title,
|
|
4643
|
+
workspace: state.workspace || null,
|
|
4644
|
+
activeChat,
|
|
4645
|
+
capabilities: IDE_SESSION_CAPABILITIES,
|
|
4646
|
+
cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
|
|
4647
|
+
currentModel: state.currentModel,
|
|
4648
|
+
currentPlan: state.currentPlan,
|
|
4649
|
+
currentAutoApprove: state.currentAutoApprove,
|
|
4650
|
+
errorMessage: state.errorMessage,
|
|
4651
|
+
errorReason: state.errorReason
|
|
4652
|
+
};
|
|
4582
4653
|
}
|
|
4583
|
-
function
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4654
|
+
function buildExtensionAgentSession(parent, ext) {
|
|
4655
|
+
const activeChat = normalizeActiveChatData(ext.activeChat);
|
|
4656
|
+
return {
|
|
4657
|
+
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
4658
|
+
parentId: parent.instanceId || parent.type,
|
|
4659
|
+
providerType: ext.type,
|
|
4660
|
+
providerName: ext.name,
|
|
4661
|
+
kind: "agent",
|
|
4662
|
+
transport: "cdp-webview",
|
|
4663
|
+
status: normalizeManagedStatus(activeChat?.status || ext.status, {
|
|
4664
|
+
activeModal: activeChat?.activeModal || null
|
|
4665
|
+
}),
|
|
4666
|
+
title: activeChat?.title || ext.name,
|
|
4667
|
+
workspace: parent.workspace || null,
|
|
4668
|
+
activeChat,
|
|
4669
|
+
capabilities: EXTENSION_SESSION_CAPABILITIES,
|
|
4670
|
+
currentModel: ext.currentModel,
|
|
4671
|
+
currentPlan: ext.currentPlan,
|
|
4672
|
+
errorMessage: ext.errorMessage,
|
|
4673
|
+
errorReason: ext.errorReason
|
|
4674
|
+
};
|
|
4594
4675
|
}
|
|
4595
|
-
function
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4676
|
+
function buildCliSession(state) {
|
|
4677
|
+
const activeChat = normalizeActiveChatData(state.activeChat);
|
|
4678
|
+
return {
|
|
4679
|
+
id: state.instanceId,
|
|
4680
|
+
parentId: null,
|
|
4681
|
+
providerType: state.type,
|
|
4682
|
+
providerName: state.name,
|
|
4683
|
+
kind: "agent",
|
|
4684
|
+
transport: "pty",
|
|
4685
|
+
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
4686
|
+
activeModal: activeChat?.activeModal || null
|
|
4687
|
+
}),
|
|
4688
|
+
title: activeChat?.title || state.name,
|
|
4689
|
+
workspace: state.workspace || null,
|
|
4690
|
+
activeChat,
|
|
4691
|
+
capabilities: PTY_SESSION_CAPABILITIES,
|
|
4692
|
+
errorMessage: state.errorMessage,
|
|
4693
|
+
errorReason: state.errorReason
|
|
4694
|
+
};
|
|
4611
4695
|
}
|
|
4612
|
-
function
|
|
4696
|
+
function buildAcpSession(state) {
|
|
4697
|
+
const activeChat = normalizeActiveChatData(state.activeChat);
|
|
4698
|
+
return {
|
|
4699
|
+
id: state.instanceId,
|
|
4700
|
+
parentId: null,
|
|
4701
|
+
providerType: state.type,
|
|
4702
|
+
providerName: state.name,
|
|
4703
|
+
kind: "agent",
|
|
4704
|
+
transport: "acp",
|
|
4705
|
+
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
4706
|
+
activeModal: activeChat?.activeModal || null
|
|
4707
|
+
}),
|
|
4708
|
+
title: activeChat?.title || state.name,
|
|
4709
|
+
workspace: state.workspace || null,
|
|
4710
|
+
activeChat,
|
|
4711
|
+
capabilities: ACP_SESSION_CAPABILITIES,
|
|
4712
|
+
currentModel: state.currentModel,
|
|
4713
|
+
currentPlan: state.currentPlan,
|
|
4714
|
+
acpConfigOptions: state.acpConfigOptions,
|
|
4715
|
+
acpModes: state.acpModes,
|
|
4716
|
+
errorMessage: state.errorMessage,
|
|
4717
|
+
errorReason: state.errorReason
|
|
4718
|
+
};
|
|
4719
|
+
}
|
|
4720
|
+
function buildSessionEntries(allStates, cdpManagers) {
|
|
4721
|
+
const sessions = [];
|
|
4613
4722
|
const ideStates = allStates.filter((s) => s.category === "ide");
|
|
4614
4723
|
const cliStates = allStates.filter((s) => s.category === "cli");
|
|
4615
4724
|
const acpStates = allStates.filter((s) => s.category === "acp");
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4725
|
+
for (const state of ideStates) {
|
|
4726
|
+
sessions.push(buildIdeWorkspaceSession(state, cdpManagers));
|
|
4727
|
+
for (const ext of state.extensions) {
|
|
4728
|
+
sessions.push(buildExtensionAgentSession(state, ext));
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
for (const state of cliStates) {
|
|
4732
|
+
sessions.push(buildCliSession(state));
|
|
4733
|
+
}
|
|
4734
|
+
for (const state of acpStates) {
|
|
4735
|
+
sessions.push(buildAcpSession(state));
|
|
4736
|
+
}
|
|
4737
|
+
return sessions;
|
|
4621
4738
|
}
|
|
4622
4739
|
|
|
4623
4740
|
// src/commands/handler.ts
|
|
@@ -4626,14 +4743,37 @@ init_logger();
|
|
|
4626
4743
|
|
|
4627
4744
|
// src/commands/chat-commands.ts
|
|
4628
4745
|
init_logger();
|
|
4746
|
+
var RECENT_SEND_WINDOW_MS = 1200;
|
|
4747
|
+
var recentSendByTarget = /* @__PURE__ */ new Map();
|
|
4748
|
+
function getCurrentProviderType(h, fallback = "") {
|
|
4749
|
+
return h.currentSession?.providerType || h.currentProviderType || fallback;
|
|
4750
|
+
}
|
|
4751
|
+
function getCurrentManagerKey(h) {
|
|
4752
|
+
return h.currentSession?.cdpManagerKey || h.currentManagerKey || "";
|
|
4753
|
+
}
|
|
4629
4754
|
function getTargetedCliAdapter(h, args, providerType) {
|
|
4630
|
-
return h.getCliAdapter(args?.
|
|
4755
|
+
return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
|
|
4756
|
+
}
|
|
4757
|
+
function buildRecentSendKey(h, args, provider, text) {
|
|
4758
|
+
const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
|
|
4759
|
+
return `${provider?.category || "unknown"}:${target}:${text.trim()}`;
|
|
4760
|
+
}
|
|
4761
|
+
function isRecentDuplicateSend(key) {
|
|
4762
|
+
const now = Date.now();
|
|
4763
|
+
for (const [candidate, ts2] of recentSendByTarget.entries()) {
|
|
4764
|
+
if (now - ts2 > RECENT_SEND_WINDOW_MS) recentSendByTarget.delete(candidate);
|
|
4765
|
+
}
|
|
4766
|
+
const previous = recentSendByTarget.get(key);
|
|
4767
|
+
if (previous && now - previous <= RECENT_SEND_WINDOW_MS) return true;
|
|
4768
|
+
recentSendByTarget.set(key, now);
|
|
4769
|
+
return false;
|
|
4631
4770
|
}
|
|
4632
4771
|
async function handleChatHistory(h, args) {
|
|
4633
|
-
const { agentType, offset, limit
|
|
4772
|
+
const { agentType, offset, limit } = args;
|
|
4773
|
+
const instanceId = args?.targetSessionId;
|
|
4634
4774
|
try {
|
|
4635
4775
|
const provider = h.getProvider(agentType);
|
|
4636
|
-
const agentStr = provider?.type || agentType || h
|
|
4776
|
+
const agentStr = provider?.type || agentType || getCurrentProviderType(h);
|
|
4637
4777
|
const result = readChatHistory(agentStr, offset || 0, limit || 30, instanceId);
|
|
4638
4778
|
return { success: true, ...result, agent: agentStr };
|
|
4639
4779
|
} catch (e) {
|
|
@@ -4677,7 +4817,7 @@ async function handleReadChat(h, args) {
|
|
|
4677
4817
|
provider.type || "unknown_extension",
|
|
4678
4818
|
parsed.messages || [],
|
|
4679
4819
|
parsed.title,
|
|
4680
|
-
args?.
|
|
4820
|
+
args?.targetSessionId
|
|
4681
4821
|
);
|
|
4682
4822
|
return { success: true, ...parsed };
|
|
4683
4823
|
}
|
|
@@ -4687,15 +4827,18 @@ async function handleReadChat(h, args) {
|
|
|
4687
4827
|
}
|
|
4688
4828
|
if (h.agentStream) {
|
|
4689
4829
|
const cdp2 = h.getCdp();
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
const stream =
|
|
4830
|
+
const parentSessionId = h.currentSession?.parentSessionId;
|
|
4831
|
+
if (cdp2 && parentSessionId) {
|
|
4832
|
+
const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
|
|
4833
|
+
if (stream?.agentType !== provider.type) {
|
|
4834
|
+
return { success: true, messages: [], status: "idle" };
|
|
4835
|
+
}
|
|
4693
4836
|
if (stream) {
|
|
4694
4837
|
h.historyWriter.appendNewMessages(
|
|
4695
4838
|
stream.agentType,
|
|
4696
4839
|
stream.messages || [],
|
|
4697
4840
|
void 0,
|
|
4698
|
-
args?.
|
|
4841
|
+
args?.targetSessionId
|
|
4699
4842
|
);
|
|
4700
4843
|
return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
|
|
4701
4844
|
}
|
|
@@ -4722,10 +4865,10 @@ async function handleReadChat(h, args) {
|
|
|
4722
4865
|
if (parsed && typeof parsed === "object") {
|
|
4723
4866
|
_log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
|
|
4724
4867
|
h.historyWriter.appendNewMessages(
|
|
4725
|
-
provider?.type || h
|
|
4868
|
+
provider?.type || getCurrentProviderType(h, "unknown_webview"),
|
|
4726
4869
|
parsed.messages || [],
|
|
4727
4870
|
parsed.title,
|
|
4728
|
-
args?.
|
|
4871
|
+
args?.targetSessionId
|
|
4729
4872
|
);
|
|
4730
4873
|
return { success: true, ...parsed };
|
|
4731
4874
|
}
|
|
@@ -4749,10 +4892,10 @@ async function handleReadChat(h, args) {
|
|
|
4749
4892
|
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
4750
4893
|
_log(`OK: ${parsed.messages?.length} msgs`);
|
|
4751
4894
|
h.historyWriter.appendNewMessages(
|
|
4752
|
-
provider?.type || h
|
|
4895
|
+
provider?.type || getCurrentProviderType(h, "unknown_ide"),
|
|
4753
4896
|
parsed.messages || [],
|
|
4754
4897
|
parsed.title,
|
|
4755
|
-
args?.
|
|
4898
|
+
args?.targetSessionId
|
|
4756
4899
|
);
|
|
4757
4900
|
return { success: true, ...parsed };
|
|
4758
4901
|
}
|
|
@@ -4767,16 +4910,21 @@ async function handleSendChat(h, args) {
|
|
|
4767
4910
|
if (!text) return { success: false, error: "text required" };
|
|
4768
4911
|
const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
|
|
4769
4912
|
const provider = h.getProvider(args?.agentType);
|
|
4913
|
+
const dedupeKey = buildRecentSendKey(h, args, provider, text);
|
|
4770
4914
|
const _logSendSuccess = (method, targetAgent) => {
|
|
4771
4915
|
h.historyWriter.appendNewMessages(
|
|
4772
|
-
targetAgent || provider?.type || h
|
|
4916
|
+
targetAgent || provider?.type || getCurrentProviderType(h, "unknown_agent"),
|
|
4773
4917
|
[{ role: "user", content: text, receivedAt: Date.now() }],
|
|
4774
4918
|
void 0,
|
|
4775
4919
|
// title
|
|
4776
|
-
args?.
|
|
4920
|
+
args?.targetSessionId
|
|
4777
4921
|
);
|
|
4778
4922
|
return { success: true, sent: true, method, targetAgent };
|
|
4779
4923
|
};
|
|
4924
|
+
if (isRecentDuplicateSend(dedupeKey)) {
|
|
4925
|
+
_log(`Suppressed duplicate send for ${dedupeKey}`);
|
|
4926
|
+
return { success: true, sent: false, deduplicated: true };
|
|
4927
|
+
}
|
|
4780
4928
|
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
4781
4929
|
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
4782
4930
|
if (adapter) {
|
|
@@ -4812,8 +4960,9 @@ async function handleSendChat(h, args) {
|
|
|
4812
4960
|
} catch (e) {
|
|
4813
4961
|
_log(`Extension script error: ${e.message}`);
|
|
4814
4962
|
}
|
|
4815
|
-
|
|
4816
|
-
|
|
4963
|
+
const extensionSessionId = h.currentSession?.sessionId;
|
|
4964
|
+
if (h.agentStream && h.getCdp() && extensionSessionId) {
|
|
4965
|
+
const ok = await h.agentStream.sendToSession(h.getCdp(), extensionSessionId, text);
|
|
4817
4966
|
if (ok) {
|
|
4818
4967
|
_log(`AgentStreamManager sent OK`);
|
|
4819
4968
|
return _logSendSuccess("agent-stream");
|
|
@@ -4823,45 +4972,11 @@ async function handleSendChat(h, args) {
|
|
|
4823
4972
|
}
|
|
4824
4973
|
const targetCdp = h.getCdp();
|
|
4825
4974
|
if (!targetCdp?.isConnected) {
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
_log(`Targeting IDE: ${h.currentIdeType}`);
|
|
4830
|
-
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
4831
|
-
try {
|
|
4832
|
-
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4833
|
-
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
4834
|
-
const matchText = provider.webviewMatchText;
|
|
4835
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4836
|
-
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
4837
|
-
let wvParsed = wvResult;
|
|
4838
|
-
if (typeof wvResult === "string") {
|
|
4839
|
-
try {
|
|
4840
|
-
wvParsed = JSON.parse(wvResult);
|
|
4841
|
-
} catch {
|
|
4842
|
-
}
|
|
4843
|
-
}
|
|
4844
|
-
if (wvParsed?.sent) {
|
|
4845
|
-
_log(`webviewSendMessage (priority) OK`);
|
|
4846
|
-
return _logSendSuccess("webview-script-priority");
|
|
4847
|
-
}
|
|
4848
|
-
_log(`webviewSendMessage (priority) did not confirm sent, falling through`);
|
|
4849
|
-
}
|
|
4850
|
-
} catch (e) {
|
|
4851
|
-
_log(`webviewSendMessage (priority) failed: ${e.message}, falling through`);
|
|
4852
|
-
}
|
|
4853
|
-
}
|
|
4854
|
-
if (provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
4855
|
-
try {
|
|
4856
|
-
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
4857
|
-
if (sent) {
|
|
4858
|
-
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
4859
|
-
return _logSendSuccess("typeAndSend-provider");
|
|
4860
|
-
}
|
|
4861
|
-
} catch (e) {
|
|
4862
|
-
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
4863
|
-
}
|
|
4975
|
+
const managerKey = getCurrentManagerKey(h);
|
|
4976
|
+
_log(`No CDP for ${managerKey}`);
|
|
4977
|
+
return { success: false, error: `CDP for ${managerKey || "unknown"} not connected` };
|
|
4864
4978
|
}
|
|
4979
|
+
_log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
|
|
4865
4980
|
const sendScript = h.getProviderScript("sendMessage", { MESSAGE: text });
|
|
4866
4981
|
if (sendScript) {
|
|
4867
4982
|
try {
|
|
@@ -4888,7 +5003,30 @@ async function handleSendChat(h, args) {
|
|
|
4888
5003
|
_log(`typeAndSend(script.selector) failed: ${e.message}`);
|
|
4889
5004
|
}
|
|
4890
5005
|
}
|
|
4891
|
-
if (parsed?.needsTypeAndSend &&
|
|
5006
|
+
if (parsed?.needsTypeAndSend && parsed?.clickCoords) {
|
|
5007
|
+
try {
|
|
5008
|
+
const { x, y } = parsed.clickCoords;
|
|
5009
|
+
const sent = await targetCdp.typeAndSendAt(x, y, text);
|
|
5010
|
+
if (sent) {
|
|
5011
|
+
_log(`typeAndSendAt(${x},${y}) success`);
|
|
5012
|
+
return _logSendSuccess("typeAndSendAt-script");
|
|
5013
|
+
}
|
|
5014
|
+
} catch (e) {
|
|
5015
|
+
_log(`typeAndSendAt failed: ${e.message}`);
|
|
5016
|
+
}
|
|
5017
|
+
}
|
|
5018
|
+
if (parsed?.needsTypeAndSend && provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
5019
|
+
try {
|
|
5020
|
+
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
5021
|
+
if (sent) {
|
|
5022
|
+
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
5023
|
+
return _logSendSuccess("typeAndSend-provider");
|
|
5024
|
+
}
|
|
5025
|
+
} catch (e) {
|
|
5026
|
+
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
5027
|
+
}
|
|
5028
|
+
}
|
|
5029
|
+
if (parsed?.needsTypeAndSend && provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
4892
5030
|
try {
|
|
4893
5031
|
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4894
5032
|
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
@@ -4911,20 +5049,44 @@ async function handleSendChat(h, args) {
|
|
|
4911
5049
|
_log(`webviewSendMessage failed: ${e.message}`);
|
|
4912
5050
|
}
|
|
4913
5051
|
}
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
5052
|
+
return { success: false, error: parsed?.error || "Provider sendMessage did not confirm send" };
|
|
5053
|
+
} catch (e) {
|
|
5054
|
+
_log(`sendMessage script failed: ${e.message}`);
|
|
5055
|
+
return { success: false, error: `Provider sendMessage failed: ${e.message}` };
|
|
5056
|
+
}
|
|
5057
|
+
}
|
|
5058
|
+
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
5059
|
+
try {
|
|
5060
|
+
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
5061
|
+
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
5062
|
+
const matchText = provider.webviewMatchText;
|
|
5063
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
5064
|
+
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
5065
|
+
let wvParsed = wvResult;
|
|
5066
|
+
if (typeof wvResult === "string") {
|
|
5067
|
+
try {
|
|
5068
|
+
wvParsed = JSON.parse(wvResult);
|
|
5069
|
+
} catch {
|
|
4921
5070
|
}
|
|
4922
|
-
}
|
|
4923
|
-
|
|
5071
|
+
}
|
|
5072
|
+
if (wvParsed?.sent) {
|
|
5073
|
+
_log(`webviewSendMessage OK`);
|
|
5074
|
+
return _logSendSuccess("webview-script");
|
|
4924
5075
|
}
|
|
4925
5076
|
}
|
|
4926
5077
|
} catch (e) {
|
|
4927
|
-
_log(`
|
|
5078
|
+
_log(`webviewSendMessage failed: ${e.message}`);
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
if (provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
5082
|
+
try {
|
|
5083
|
+
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
5084
|
+
if (sent) {
|
|
5085
|
+
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
5086
|
+
return _logSendSuccess("typeAndSend-provider");
|
|
5087
|
+
}
|
|
5088
|
+
} catch (e) {
|
|
5089
|
+
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
4928
5090
|
}
|
|
4929
5091
|
}
|
|
4930
5092
|
_log("All methods failed");
|
|
@@ -4932,9 +5094,9 @@ async function handleSendChat(h, args) {
|
|
|
4932
5094
|
}
|
|
4933
5095
|
async function handleListChats(h, args) {
|
|
4934
5096
|
const provider = h.getProvider(args?.agentType);
|
|
4935
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
5097
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
4936
5098
|
try {
|
|
4937
|
-
const chats = await h.agentStream.
|
|
5099
|
+
const chats = await h.agentStream.listSessionChats(h.getCdp(), h.currentSession.sessionId);
|
|
4938
5100
|
LOG.info("Command", `[list_chats] Extension: ${chats.length} chats`);
|
|
4939
5101
|
return { success: true, chats };
|
|
4940
5102
|
} catch (e) {
|
|
@@ -4993,8 +5155,8 @@ async function handleNewChat(h, args) {
|
|
|
4993
5155
|
}
|
|
4994
5156
|
return { success: false, error: "new_chat not supported by this CLI provider" };
|
|
4995
5157
|
}
|
|
4996
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
4997
|
-
const ok = await h.agentStream.
|
|
5158
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
5159
|
+
const ok = await h.agentStream.newSession(h.getCdp(), h.currentSession.sessionId);
|
|
4998
5160
|
return { success: ok };
|
|
4999
5161
|
}
|
|
5000
5162
|
try {
|
|
@@ -5018,15 +5180,15 @@ async function handleNewChat(h, args) {
|
|
|
5018
5180
|
}
|
|
5019
5181
|
async function handleSwitchChat(h, args) {
|
|
5020
5182
|
const provider = h.getProvider(args?.agentType);
|
|
5021
|
-
const
|
|
5183
|
+
const managerKey = getCurrentManagerKey(h);
|
|
5022
5184
|
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
5023
5185
|
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
5024
|
-
LOG.info("Command", `[switch_chat] sessionId=${sessionId},
|
|
5025
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
5026
|
-
const ok = await h.agentStream.
|
|
5186
|
+
LOG.info("Command", `[switch_chat] sessionId=${sessionId}, manager=${managerKey}`);
|
|
5187
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
5188
|
+
const ok = await h.agentStream.switchConversation(h.getCdp(), h.currentSession.sessionId, sessionId);
|
|
5027
5189
|
return { success: ok, result: ok ? "switched" : "failed" };
|
|
5028
5190
|
}
|
|
5029
|
-
const cdp = h.getCdp(
|
|
5191
|
+
const cdp = h.getCdp(managerKey);
|
|
5030
5192
|
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
5031
5193
|
try {
|
|
5032
5194
|
const webviewScript = h.getProviderScript("webviewSwitchSession", { SESSION_ID: JSON.stringify(sessionId) });
|
|
@@ -5168,7 +5330,7 @@ async function handleSetMode(h, args) {
|
|
|
5168
5330
|
async function handleChangeModel(h, args) {
|
|
5169
5331
|
const provider = h.getProvider(args?.agentType);
|
|
5170
5332
|
const model = args?.model;
|
|
5171
|
-
LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category}
|
|
5333
|
+
LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
|
|
5172
5334
|
if (provider?.category === "acp") {
|
|
5173
5335
|
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
5174
5336
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
@@ -5289,14 +5451,8 @@ async function handleResolveAction(h, args) {
|
|
|
5289
5451
|
LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
5290
5452
|
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
5291
5453
|
}
|
|
5292
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
5293
|
-
const ok = await h.agentStream.
|
|
5294
|
-
h.getCdp(),
|
|
5295
|
-
h.currentIdeType,
|
|
5296
|
-
provider.type,
|
|
5297
|
-
action,
|
|
5298
|
-
h.currentIdeType
|
|
5299
|
-
);
|
|
5454
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
5455
|
+
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
|
|
5300
5456
|
return { success: ok };
|
|
5301
5457
|
}
|
|
5302
5458
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
@@ -5656,157 +5812,37 @@ async function handleFileListBrowse(h, args) {
|
|
|
5656
5812
|
// src/commands/stream-commands.ts
|
|
5657
5813
|
init_config();
|
|
5658
5814
|
init_logger();
|
|
5659
|
-
async function
|
|
5660
|
-
if (!h.agentStream || !h.getCdp() || !h.currentIdeType) return { success: false, error: "AgentStream or CDP not available" };
|
|
5661
|
-
const agentType = args?.agentType || args?.agent || null;
|
|
5662
|
-
await h.agentStream.switchActiveAgent(h.getCdp(), h.currentIdeType, agentType);
|
|
5663
|
-
return { success: true, activeAgent: agentType };
|
|
5664
|
-
}
|
|
5665
|
-
async function handleAgentStreamRead(h, args) {
|
|
5666
|
-
if (!h.agentStream || !h.getCdp() || !h.currentIdeType) return { success: false, error: "AgentStream or CDP not available" };
|
|
5667
|
-
const streams = await h.agentStream.collectAgentStreams(h.getCdp(), h.currentIdeType);
|
|
5668
|
-
return { success: true, streams };
|
|
5669
|
-
}
|
|
5670
|
-
async function handleAgentStreamSend(h, args) {
|
|
5671
|
-
const agentType = args?.agentType || args?.agent;
|
|
5672
|
-
const text = args?.text || args?.message;
|
|
5673
|
-
if (!text) return { success: false, error: "text required" };
|
|
5674
|
-
if (agentType && h.ctx.adapters) {
|
|
5675
|
-
for (const [key, adapter] of h.ctx.adapters.entries()) {
|
|
5676
|
-
if (adapter.cliType === agentType || key.includes(agentType)) {
|
|
5677
|
-
LOG.info("Command", `[agent_stream_send] Routing to CLI adapter: ${adapter.cliType}`);
|
|
5678
|
-
try {
|
|
5679
|
-
await adapter.sendMessage(text);
|
|
5680
|
-
return { success: true, sent: true, targetAgent: adapter.cliType };
|
|
5681
|
-
} catch (e) {
|
|
5682
|
-
LOG.info("Command", `[agent_stream_send] CLI adapter failed: ${e.message}`);
|
|
5683
|
-
return { success: false, error: `CLI send failed: ${e.message}` };
|
|
5684
|
-
}
|
|
5685
|
-
}
|
|
5686
|
-
}
|
|
5687
|
-
}
|
|
5688
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5689
|
-
const resolvedAgent = agentType || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5690
|
-
if (!resolvedAgent) return { success: false, error: "agentType required" };
|
|
5691
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5692
|
-
const ok = await h.agentStream.sendToAgent(h.getCdp(), h.currentIdeType, resolvedAgent, text, h.currentIdeType);
|
|
5693
|
-
return { success: ok };
|
|
5694
|
-
}
|
|
5695
|
-
async function handleAgentStreamResolve(h, args) {
|
|
5696
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5697
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5698
|
-
const action = args?.action || "approve";
|
|
5699
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5700
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5701
|
-
const ok = await h.agentStream.resolveAgentAction(h.getCdp(), h.currentIdeType, agentType, action, h.currentIdeType);
|
|
5702
|
-
return { success: ok };
|
|
5703
|
-
}
|
|
5704
|
-
async function handleAgentStreamNew(h, args) {
|
|
5705
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5706
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5707
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5708
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5709
|
-
const ok = await h.agentStream.newAgentSession(h.getCdp(), h.currentIdeType, agentType, h.currentIdeType);
|
|
5710
|
-
return { success: ok };
|
|
5711
|
-
}
|
|
5712
|
-
async function handleAgentStreamListChats(h, args) {
|
|
5713
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5714
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5715
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5716
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5717
|
-
const chats = await h.agentStream.listAgentChats(h.getCdp(), h.currentIdeType, agentType);
|
|
5718
|
-
return { success: true, chats };
|
|
5719
|
-
}
|
|
5720
|
-
async function handleAgentStreamSwitchSession(h, args) {
|
|
5721
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5722
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5723
|
-
const sessionId = args?.sessionId || args?.id;
|
|
5724
|
-
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
5725
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5726
|
-
const ok = await h.agentStream.switchAgentSession(h.getCdp(), h.currentIdeType, agentType, sessionId);
|
|
5727
|
-
return { success: ok };
|
|
5728
|
-
}
|
|
5729
|
-
async function handleAgentStreamFocus(h, args) {
|
|
5815
|
+
async function handleFocusSession(h, args) {
|
|
5730
5816
|
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5731
|
-
const
|
|
5732
|
-
if (!
|
|
5733
|
-
await h.agentStream.
|
|
5734
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5735
|
-
const ok = await h.agentStream.focusAgentEditor(h.getCdp(), h.currentIdeType, agentType);
|
|
5817
|
+
const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
|
|
5818
|
+
if (!sessionId) return { success: false, error: "targetSessionId required" };
|
|
5819
|
+
const ok = await h.agentStream.focusSession(h.getCdp(), sessionId);
|
|
5736
5820
|
return { success: ok };
|
|
5737
5821
|
}
|
|
5738
5822
|
function handlePtyInput(h, args) {
|
|
5739
|
-
const { cliType, data } = args || {};
|
|
5823
|
+
const { cliType, data, targetSessionId } = args || {};
|
|
5740
5824
|
if (!data) return { success: false, error: "data required" };
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
const first = h.ctx.adapters.values().next().value;
|
|
5745
|
-
if (first && typeof first.writeRaw === "function") {
|
|
5746
|
-
first.writeRaw(data);
|
|
5747
|
-
return { success: true };
|
|
5748
|
-
}
|
|
5749
|
-
}
|
|
5750
|
-
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
5751
|
-
if (directAdapter && typeof directAdapter.writeRaw === "function") {
|
|
5752
|
-
directAdapter.writeRaw(data);
|
|
5753
|
-
return { success: true };
|
|
5754
|
-
}
|
|
5755
|
-
for (const [, adapter] of h.ctx.adapters) {
|
|
5756
|
-
if (adapter.cliType === targetCli && typeof adapter.writeRaw === "function") {
|
|
5757
|
-
adapter.writeRaw(data);
|
|
5758
|
-
return { success: true };
|
|
5759
|
-
}
|
|
5760
|
-
}
|
|
5761
|
-
for (const [key, adapter] of h.ctx.adapters) {
|
|
5762
|
-
if ((key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.writeRaw === "function") {
|
|
5763
|
-
adapter.writeRaw(data);
|
|
5764
|
-
return { success: true };
|
|
5765
|
-
}
|
|
5766
|
-
}
|
|
5825
|
+
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
5826
|
+
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
5827
|
+
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
5767
5828
|
}
|
|
5768
|
-
|
|
5829
|
+
adapter.writeRaw(data);
|
|
5830
|
+
return { success: true };
|
|
5769
5831
|
}
|
|
5770
5832
|
function handlePtyResize(h, args) {
|
|
5771
|
-
const { cliType, cols, rows, force } = args || {};
|
|
5833
|
+
const { cliType, cols, rows, force, targetSessionId } = args || {};
|
|
5772
5834
|
if (!cols || !rows) return { success: false, error: "cols and rows required" };
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
first.resize(cols, rows);
|
|
5783
|
-
}
|
|
5784
|
-
return { success: true };
|
|
5785
|
-
}
|
|
5786
|
-
}
|
|
5787
|
-
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
5788
|
-
if (directAdapter && typeof directAdapter.resize === "function") {
|
|
5789
|
-
if (force) {
|
|
5790
|
-
directAdapter.resize(cols - 1, rows);
|
|
5791
|
-
setTimeout(() => directAdapter.resize(cols, rows), 50);
|
|
5792
|
-
} else {
|
|
5793
|
-
directAdapter.resize(cols, rows);
|
|
5794
|
-
}
|
|
5795
|
-
return { success: true };
|
|
5796
|
-
}
|
|
5797
|
-
for (const [key, adapter] of h.ctx.adapters) {
|
|
5798
|
-
if ((adapter.cliType === targetCli || key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.resize === "function") {
|
|
5799
|
-
if (force) {
|
|
5800
|
-
adapter.resize(cols - 1, rows);
|
|
5801
|
-
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
5802
|
-
} else {
|
|
5803
|
-
adapter.resize(cols, rows);
|
|
5804
|
-
}
|
|
5805
|
-
return { success: true };
|
|
5806
|
-
}
|
|
5807
|
-
}
|
|
5835
|
+
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
5836
|
+
if (!adapter || typeof adapter.resize !== "function") {
|
|
5837
|
+
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
5838
|
+
}
|
|
5839
|
+
if (force) {
|
|
5840
|
+
adapter.resize(cols - 1, rows);
|
|
5841
|
+
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
5842
|
+
} else {
|
|
5843
|
+
adapter.resize(cols, rows);
|
|
5808
5844
|
}
|
|
5809
|
-
return { success:
|
|
5845
|
+
return { success: true };
|
|
5810
5846
|
}
|
|
5811
5847
|
function handleGetProviderSettings(h, args) {
|
|
5812
5848
|
const loader = h.ctx.providerLoader;
|
|
@@ -5842,7 +5878,7 @@ function handleSetProviderSetting(h, args) {
|
|
|
5842
5878
|
}
|
|
5843
5879
|
async function handleExtensionScript(h, args, scriptName) {
|
|
5844
5880
|
const { agentType, ideType } = args || {};
|
|
5845
|
-
LOG.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType}
|
|
5881
|
+
LOG.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType} session=${h.currentSession?.sessionId || ""}`);
|
|
5846
5882
|
if (!agentType) return { success: false, error: "agentType is required" };
|
|
5847
5883
|
const loader = h.ctx.providerLoader;
|
|
5848
5884
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -5863,21 +5899,22 @@ async function handleExtensionScript(h, args, scriptName) {
|
|
|
5863
5899
|
}
|
|
5864
5900
|
const scriptCode = scriptFn(normalizedArgs);
|
|
5865
5901
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
5866
|
-
const cdpKey = provider.category === "ide" ? h.
|
|
5902
|
+
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
|
|
5867
5903
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
5868
5904
|
const cdp = h.getCdp(cdpKey);
|
|
5869
5905
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
5870
5906
|
try {
|
|
5871
5907
|
let result;
|
|
5872
5908
|
if (provider.category === "extension") {
|
|
5873
|
-
const
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5909
|
+
const runtimeSessionId = h.currentSession?.sessionId || args?.targetSessionId;
|
|
5910
|
+
if (!runtimeSessionId) return { success: false, error: `No target session found for ${agentType}` };
|
|
5911
|
+
const parentSessionId = h.currentSession?.parentSessionId;
|
|
5912
|
+
if (parentSessionId) {
|
|
5913
|
+
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
5914
|
+
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
5915
|
+
}
|
|
5916
|
+
const managed = runtimeSessionId ? h.agentStream?.getManagedSession(runtimeSessionId) : null;
|
|
5917
|
+
const targetSessionId = managed?.cdpSessionId || null;
|
|
5881
5918
|
const IDE_LEVEL_SCRIPTS = ["listModes", "setMode", "listModels", "setModel"];
|
|
5882
5919
|
if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
|
|
5883
5920
|
if (targetSessionId) {
|
|
@@ -5948,7 +5985,7 @@ function handleGetIdeExtensions(h, args) {
|
|
|
5948
5985
|
enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
|
|
5949
5986
|
}));
|
|
5950
5987
|
}
|
|
5951
|
-
return { success: true,
|
|
5988
|
+
return { success: true, ideExtensions: result };
|
|
5952
5989
|
}
|
|
5953
5990
|
function handleSetIdeExtension(h, args) {
|
|
5954
5991
|
const { ideType, extensionType, enabled } = args || {};
|
|
@@ -6060,10 +6097,8 @@ var DaemonCommandHandler = class {
|
|
|
6060
6097
|
_agentStream = null;
|
|
6061
6098
|
domHandlers;
|
|
6062
6099
|
_historyWriter;
|
|
6063
|
-
/** Current
|
|
6064
|
-
|
|
6065
|
-
/** Current provider type — agentType priority, ideType use */
|
|
6066
|
-
_currentProviderType;
|
|
6100
|
+
/** Current request route context */
|
|
6101
|
+
_currentRoute = {};
|
|
6067
6102
|
constructor(ctx) {
|
|
6068
6103
|
this._ctx = ctx;
|
|
6069
6104
|
this.domHandlers = new CdpDomHandlers((ideType) => this.getCdp(ideType));
|
|
@@ -6079,20 +6114,25 @@ var DaemonCommandHandler = class {
|
|
|
6079
6114
|
get historyWriter() {
|
|
6080
6115
|
return this._historyWriter;
|
|
6081
6116
|
}
|
|
6117
|
+
get currentManagerKey() {
|
|
6118
|
+
return this._currentRoute.managerKey;
|
|
6119
|
+
}
|
|
6082
6120
|
get currentIdeType() {
|
|
6083
|
-
return this.
|
|
6121
|
+
return this._currentRoute.managerKey;
|
|
6084
6122
|
}
|
|
6085
6123
|
get currentProviderType() {
|
|
6086
|
-
return this.
|
|
6124
|
+
return this._currentRoute.providerType;
|
|
6125
|
+
}
|
|
6126
|
+
get currentSession() {
|
|
6127
|
+
return this._currentRoute.session;
|
|
6087
6128
|
}
|
|
6088
|
-
/** Get CDP manager for a specific
|
|
6089
|
-
* Supports exact match, multi-window prefix match, and instanceIdMap UUID lookup.
|
|
6090
|
-
* Returns null if no match — never falls back to another IDE. */
|
|
6129
|
+
/** Get CDP manager for a specific session or manager key. */
|
|
6091
6130
|
getCdp(ideType) {
|
|
6092
|
-
const
|
|
6093
|
-
if (!
|
|
6094
|
-
const
|
|
6095
|
-
const
|
|
6131
|
+
const requested = ideType || this._currentRoute.session?.sessionId || this._currentRoute.managerKey;
|
|
6132
|
+
if (!requested) return null;
|
|
6133
|
+
const session = this._ctx.sessionRegistry?.get(requested);
|
|
6134
|
+
const managerKey = session?.cdpManagerKey || requested;
|
|
6135
|
+
const m = findCdpManager(this._ctx.cdpManagers, managerKey);
|
|
6096
6136
|
if (m?.isConnected) return m;
|
|
6097
6137
|
return null;
|
|
6098
6138
|
}
|
|
@@ -6100,7 +6140,7 @@ var DaemonCommandHandler = class {
|
|
|
6100
6140
|
* Get provider module — _currentProviderType (agentType priority) use.
|
|
6101
6141
|
*/
|
|
6102
6142
|
getProvider(overrideType) {
|
|
6103
|
-
const key = overrideType || this.
|
|
6143
|
+
const key = overrideType || this._currentRoute.providerType || this._currentRoute.session?.providerType || this._currentRoute.managerKey;
|
|
6104
6144
|
if (!key || !this._ctx.providerLoader) return void 0;
|
|
6105
6145
|
const result = this._ctx.providerLoader.resolve(key);
|
|
6106
6146
|
if (result) return result;
|
|
@@ -6133,14 +6173,22 @@ var DaemonCommandHandler = class {
|
|
|
6133
6173
|
const cdp = this.getCdp();
|
|
6134
6174
|
if (!cdp?.isConnected) return null;
|
|
6135
6175
|
if (provider?.category === "extension") {
|
|
6136
|
-
let sessionId = this.
|
|
6137
|
-
if (!sessionId && this.
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6176
|
+
let sessionId = this._currentRoute.session?.sessionId || null;
|
|
6177
|
+
if (!sessionId && this._currentRoute.session?.parentSessionId) {
|
|
6178
|
+
sessionId = this._agentStream?.resolveSessionForAgent(this._currentRoute.session.parentSessionId, provider.type) || null;
|
|
6179
|
+
}
|
|
6180
|
+
if (sessionId && this._agentStream) {
|
|
6181
|
+
const target = this._ctx.sessionRegistry?.get(sessionId);
|
|
6182
|
+
if (target?.parentSessionId) {
|
|
6183
|
+
await this._agentStream.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
6184
|
+
await this._agentStream.syncActiveSession(cdp, target.parentSessionId);
|
|
6185
|
+
}
|
|
6141
6186
|
}
|
|
6142
6187
|
if (!sessionId) return null;
|
|
6143
|
-
const
|
|
6188
|
+
const managed = this._agentStream?.getManagedSession(sessionId);
|
|
6189
|
+
const cdpSessionId = managed?.cdpSessionId;
|
|
6190
|
+
if (!cdpSessionId) return null;
|
|
6191
|
+
const result2 = await cdp.evaluateInSessionFrame(cdpSessionId, script, timeout);
|
|
6144
6192
|
return { result: result2, category: "extension" };
|
|
6145
6193
|
}
|
|
6146
6194
|
const result = await cdp.evaluate(script, timeout);
|
|
@@ -6148,57 +6196,37 @@ var DaemonCommandHandler = class {
|
|
|
6148
6196
|
}
|
|
6149
6197
|
/** CLI adapter search */
|
|
6150
6198
|
getCliAdapter(type) {
|
|
6151
|
-
const target = type || this.
|
|
6199
|
+
const target = type || this._currentRoute.session?.sessionId || this._currentRoute.providerType || this._currentRoute.managerKey;
|
|
6152
6200
|
if (!target || !this._ctx.adapters) return null;
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
const direct = this._ctx.adapters.get(normalizedTarget);
|
|
6157
|
-
if (direct) return direct;
|
|
6158
|
-
for (const [key, adapter] of this._ctx.adapters.entries()) {
|
|
6159
|
-
if (adapter.cliType === target || adapter.cliType === normalizedTarget || key === normalizedTarget || key.startsWith(target) || key.startsWith(normalizedTarget)) {
|
|
6160
|
-
return adapter;
|
|
6161
|
-
}
|
|
6201
|
+
const session = this._ctx.sessionRegistry?.get(target);
|
|
6202
|
+
if (session?.adapterKey) {
|
|
6203
|
+
return this._ctx.adapters.get(session.adapterKey) || null;
|
|
6162
6204
|
}
|
|
6163
|
-
return null;
|
|
6205
|
+
return this._ctx.adapters.get(target) || null;
|
|
6164
6206
|
}
|
|
6165
6207
|
// ─── Private helpers ──────────────────────────────
|
|
6166
|
-
|
|
6167
|
-
if (
|
|
6168
|
-
const
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
const
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
const managerKey = instanceKey.slice(4);
|
|
6180
|
-
this._ctx.instanceIdMap?.set(instanceId, managerKey);
|
|
6181
|
-
return managerKey;
|
|
6182
|
-
}
|
|
6183
|
-
if (typeof instance?.getExtensionInstances === "function") {
|
|
6184
|
-
for (const ext of instance.getExtensionInstances() || []) {
|
|
6185
|
-
if (typeof ext?.getInstanceId === "function" && ext.getInstanceId() === instanceId) {
|
|
6186
|
-
const managerKey = instanceKey.slice(4);
|
|
6187
|
-
this._ctx.instanceIdMap?.set(instanceId, managerKey);
|
|
6188
|
-
return managerKey;
|
|
6189
|
-
}
|
|
6190
|
-
}
|
|
6191
|
-
}
|
|
6192
|
-
}
|
|
6193
|
-
return void 0;
|
|
6194
|
-
}
|
|
6195
|
-
/** Extract ideType from _targetInstance or explicit ideType */
|
|
6208
|
+
inferProviderType(key) {
|
|
6209
|
+
if (!key) return void 0;
|
|
6210
|
+
const session = this._ctx.sessionRegistry?.get(key);
|
|
6211
|
+
if (session?.providerType) return session.providerType;
|
|
6212
|
+
return key.split("_")[0];
|
|
6213
|
+
}
|
|
6214
|
+
resolveRoute(args) {
|
|
6215
|
+
const session = this._ctx.sessionRegistry?.get(args?.targetSessionId);
|
|
6216
|
+
const managerKey = this.extractIdeType(args);
|
|
6217
|
+
const providerType = args?.agentType || args?.providerType || session?.providerType || this.inferProviderType(managerKey);
|
|
6218
|
+
return { session, managerKey, providerType };
|
|
6219
|
+
}
|
|
6220
|
+
/** Extract CDP scope key from target session or explicit ideType */
|
|
6196
6221
|
extractIdeType(args) {
|
|
6222
|
+
if (args?.targetSessionId) {
|
|
6223
|
+
const target = this._ctx.sessionRegistry?.get(args.targetSessionId);
|
|
6224
|
+
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
6225
|
+
if (this._ctx.cdpManagers.has(args.targetSessionId)) return args.targetSessionId;
|
|
6226
|
+
}
|
|
6197
6227
|
if (args?.ideType) {
|
|
6198
|
-
const
|
|
6199
|
-
if (
|
|
6200
|
-
return mappedKey;
|
|
6201
|
-
}
|
|
6228
|
+
const target = this._ctx.sessionRegistry?.get(args.ideType);
|
|
6229
|
+
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
6202
6230
|
if (this._ctx.cdpManagers.has(args.ideType)) {
|
|
6203
6231
|
return args.ideType;
|
|
6204
6232
|
}
|
|
@@ -6209,34 +6237,6 @@ var DaemonCommandHandler = class {
|
|
|
6209
6237
|
}
|
|
6210
6238
|
}
|
|
6211
6239
|
}
|
|
6212
|
-
if (args?._targetInstance) {
|
|
6213
|
-
let raw = args._targetInstance;
|
|
6214
|
-
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
6215
|
-
const cliMatch = raw.match(/:cli:(.+)$/);
|
|
6216
|
-
const acpMatch = raw.match(/:acp:(.+)$/);
|
|
6217
|
-
if (ideMatch) raw = ideMatch[1];
|
|
6218
|
-
else if (cliMatch) raw = cliMatch[1];
|
|
6219
|
-
else if (acpMatch) raw = acpMatch[1];
|
|
6220
|
-
const mappedKey = this.resolveManagerKeyFromInstanceId(raw);
|
|
6221
|
-
if (mappedKey) {
|
|
6222
|
-
return mappedKey;
|
|
6223
|
-
}
|
|
6224
|
-
if (this._ctx.cdpManagers.has(raw)) {
|
|
6225
|
-
return raw;
|
|
6226
|
-
}
|
|
6227
|
-
const found = findCdpManager(this._ctx.cdpManagers, raw);
|
|
6228
|
-
if (found) {
|
|
6229
|
-
for (const [k, m] of this._ctx.cdpManagers.entries()) {
|
|
6230
|
-
if (m === found) return k;
|
|
6231
|
-
}
|
|
6232
|
-
}
|
|
6233
|
-
const lastUnderscore = raw.lastIndexOf("_");
|
|
6234
|
-
if (lastUnderscore > 0) {
|
|
6235
|
-
const stripped = raw.substring(0, lastUnderscore);
|
|
6236
|
-
if (this._ctx.cdpManagers.has(stripped)) return stripped;
|
|
6237
|
-
}
|
|
6238
|
-
return raw;
|
|
6239
|
-
}
|
|
6240
6240
|
return void 0;
|
|
6241
6241
|
}
|
|
6242
6242
|
setAgentStreamManager(manager) {
|
|
@@ -6244,12 +6244,11 @@ var DaemonCommandHandler = class {
|
|
|
6244
6244
|
}
|
|
6245
6245
|
// ─── Command Dispatcher ──────────────────────────
|
|
6246
6246
|
async handle(cmd, args) {
|
|
6247
|
-
this.
|
|
6248
|
-
this.
|
|
6249
|
-
if (!this._currentIdeType && !this._currentProviderType) {
|
|
6247
|
+
this._currentRoute = this.resolveRoute(args);
|
|
6248
|
+
if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
|
|
6250
6249
|
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
6251
6250
|
if (cdpCommands.includes(cmd)) {
|
|
6252
|
-
return { success: false, error: "No
|
|
6251
|
+
return { success: false, error: "No targetSessionId specified \u2014 cannot route command" };
|
|
6253
6252
|
}
|
|
6254
6253
|
}
|
|
6255
6254
|
try {
|
|
@@ -6340,22 +6339,8 @@ var DaemonCommandHandler = class {
|
|
|
6340
6339
|
case "refresh_scripts":
|
|
6341
6340
|
return this.handleRefreshScripts(args);
|
|
6342
6341
|
// ─── Stream commands (stream-commands.ts) ───────────
|
|
6343
|
-
case "
|
|
6344
|
-
return
|
|
6345
|
-
case "agent_stream_read":
|
|
6346
|
-
return handleAgentStreamRead(this, args);
|
|
6347
|
-
case "agent_stream_send":
|
|
6348
|
-
return handleAgentStreamSend(this, args);
|
|
6349
|
-
case "agent_stream_resolve":
|
|
6350
|
-
return handleAgentStreamResolve(this, args);
|
|
6351
|
-
case "agent_stream_new":
|
|
6352
|
-
return handleAgentStreamNew(this, args);
|
|
6353
|
-
case "agent_stream_list_chats":
|
|
6354
|
-
return handleAgentStreamListChats(this, args);
|
|
6355
|
-
case "agent_stream_switch_session":
|
|
6356
|
-
return handleAgentStreamSwitchSession(this, args);
|
|
6357
|
-
case "agent_stream_focus":
|
|
6358
|
-
return handleAgentStreamFocus(this, args);
|
|
6342
|
+
case "focus_session":
|
|
6343
|
+
return handleFocusSession(this, args);
|
|
6359
6344
|
// ─── PTY Raw I/O (stream-commands.ts) ─────────
|
|
6360
6345
|
case "pty_input":
|
|
6361
6346
|
return handlePtyInput(this, args);
|
|
@@ -8003,8 +7988,7 @@ var CHAT_COMMANDS = [
|
|
|
8003
7988
|
"new_chat",
|
|
8004
7989
|
"switch_chat",
|
|
8005
7990
|
"set_mode",
|
|
8006
|
-
"change_model"
|
|
8007
|
-
"agent_stream_send"
|
|
7991
|
+
"change_model"
|
|
8008
7992
|
];
|
|
8009
7993
|
var DaemonCommandRouter = class {
|
|
8010
7994
|
deps;
|
|
@@ -8242,6 +8226,7 @@ var DaemonCommandRouter = class {
|
|
|
8242
8226
|
} catch {
|
|
8243
8227
|
}
|
|
8244
8228
|
this.deps.cdpManagers.delete(key);
|
|
8229
|
+
this.deps.sessionRegistry.unregisterByManagerKey(key);
|
|
8245
8230
|
LOG.info("StopIDE", `CDP disconnected: ${key}`);
|
|
8246
8231
|
}
|
|
8247
8232
|
}
|
|
@@ -8254,14 +8239,6 @@ var DaemonCommandRouter = class {
|
|
|
8254
8239
|
for (const instanceKey of keysToRemove) {
|
|
8255
8240
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
8256
8241
|
if (ideInstance) {
|
|
8257
|
-
if (ideInstance.getInstanceId) {
|
|
8258
|
-
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
8259
|
-
}
|
|
8260
|
-
if (ideInstance.getExtensionInstances) {
|
|
8261
|
-
for (const ext of ideInstance.getExtensionInstances()) {
|
|
8262
|
-
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
8263
|
-
}
|
|
8264
|
-
}
|
|
8265
8242
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
8266
8243
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
8267
8244
|
}
|
|
@@ -8270,14 +8247,6 @@ var DaemonCommandRouter = class {
|
|
|
8270
8247
|
const instanceKey = `ide:${ideType}`;
|
|
8271
8248
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
8272
8249
|
if (ideInstance) {
|
|
8273
|
-
if (ideInstance.getInstanceId) {
|
|
8274
|
-
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
8275
|
-
}
|
|
8276
|
-
if (ideInstance.getExtensionInstances) {
|
|
8277
|
-
for (const ext of ideInstance.getExtensionInstances()) {
|
|
8278
|
-
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
8279
|
-
}
|
|
8280
|
-
}
|
|
8281
8250
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
8282
8251
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
8283
8252
|
}
|
|
@@ -8330,15 +8299,9 @@ function buildStatusSnapshot(options) {
|
|
|
8330
8299
|
const cfg = loadConfig();
|
|
8331
8300
|
const wsState = getWorkspaceState(cfg);
|
|
8332
8301
|
const memSnap = getHostMemorySnapshot();
|
|
8333
|
-
const
|
|
8302
|
+
const sessions = buildSessionEntries(
|
|
8334
8303
|
options.allStates,
|
|
8335
|
-
options.cdpManagers
|
|
8336
|
-
{
|
|
8337
|
-
detectedIdes: options.detectedIdes.map((ide) => ({
|
|
8338
|
-
id: ide.id,
|
|
8339
|
-
installed: ide.installed !== false
|
|
8340
|
-
}))
|
|
8341
|
-
}
|
|
8304
|
+
options.cdpManagers
|
|
8342
8305
|
);
|
|
8343
8306
|
return {
|
|
8344
8307
|
instanceId: options.instanceId,
|
|
@@ -8360,9 +8323,7 @@ function buildStatusSnapshot(options) {
|
|
|
8360
8323
|
timestamp: options.timestamp ?? Date.now(),
|
|
8361
8324
|
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8362
8325
|
...options.p2p ? { p2p: options.p2p } : {},
|
|
8363
|
-
|
|
8364
|
-
managedClis,
|
|
8365
|
-
managedAcps,
|
|
8326
|
+
sessions,
|
|
8366
8327
|
workspaces: wsState.workspaces,
|
|
8367
8328
|
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8368
8329
|
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
@@ -8474,7 +8435,7 @@ var DaemonStatusReporter = class {
|
|
|
8474
8435
|
LOG.info("StatusReport", `\u2192${target} ${baseSummary}`);
|
|
8475
8436
|
}
|
|
8476
8437
|
}
|
|
8477
|
-
const
|
|
8438
|
+
const sessions = buildSessionEntries(
|
|
8478
8439
|
allStates,
|
|
8479
8440
|
this.deps.cdpManagers
|
|
8480
8441
|
);
|
|
@@ -8505,23 +8466,20 @@ var DaemonStatusReporter = class {
|
|
|
8505
8466
|
if (opts?.p2pOnly) return;
|
|
8506
8467
|
const wsPayload = {
|
|
8507
8468
|
daemonMode: true,
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
id: a.id,
|
|
8523
|
-
acpType: a.acpType,
|
|
8524
|
-
acpName: a.acpName
|
|
8469
|
+
sessions: sessions.map((session) => ({
|
|
8470
|
+
id: session.id,
|
|
8471
|
+
parentId: session.parentId,
|
|
8472
|
+
providerType: session.providerType,
|
|
8473
|
+
providerName: session.providerName,
|
|
8474
|
+
kind: session.kind,
|
|
8475
|
+
transport: session.transport,
|
|
8476
|
+
status: session.status,
|
|
8477
|
+
workspace: session.workspace,
|
|
8478
|
+
title: session.title,
|
|
8479
|
+
cdpConnected: session.cdpConnected,
|
|
8480
|
+
currentModel: session.currentModel,
|
|
8481
|
+
currentPlan: session.currentPlan,
|
|
8482
|
+
currentAutoApprove: session.currentAutoApprove
|
|
8525
8483
|
})),
|
|
8526
8484
|
p2p: payload.p2p,
|
|
8527
8485
|
timestamp: now
|
|
@@ -8952,6 +8910,9 @@ var AcpProviderInstance = class {
|
|
|
8952
8910
|
);
|
|
8953
8911
|
}
|
|
8954
8912
|
}
|
|
8913
|
+
getInstanceId() {
|
|
8914
|
+
return this.instanceId;
|
|
8915
|
+
}
|
|
8955
8916
|
// ─── ACP Config Options & Modes ─────────────────────
|
|
8956
8917
|
parseConfigOptions(raw) {
|
|
8957
8918
|
if (!Array.isArray(raw)) return;
|
|
@@ -9731,6 +9692,7 @@ var DaemonCliManager = class {
|
|
|
9731
9692
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
9732
9693
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
9733
9694
|
const key = crypto4.randomUUID();
|
|
9695
|
+
const sessionRegistry = this.deps.getSessionRegistry?.() || null;
|
|
9734
9696
|
if (provider && provider.category === "acp") {
|
|
9735
9697
|
const instanceManager2 = this.deps.getInstanceManager();
|
|
9736
9698
|
if (!instanceManager2) throw new Error("InstanceManager not available");
|
|
@@ -9754,6 +9716,16 @@ ${installInfo}`
|
|
|
9754
9716
|
await instanceManager2.addInstance(key, acpInstance, {
|
|
9755
9717
|
settings: this.providerLoader.getSettings(normalizedType)
|
|
9756
9718
|
});
|
|
9719
|
+
const sessionId = acpInstance.getInstanceId();
|
|
9720
|
+
sessionRegistry?.register({
|
|
9721
|
+
sessionId,
|
|
9722
|
+
parentSessionId: null,
|
|
9723
|
+
providerType: normalizedType,
|
|
9724
|
+
providerCategory: "acp",
|
|
9725
|
+
transport: "acp",
|
|
9726
|
+
adapterKey: key,
|
|
9727
|
+
instanceKey: key
|
|
9728
|
+
});
|
|
9757
9729
|
this.adapters.set(key, {
|
|
9758
9730
|
cliType: normalizedType,
|
|
9759
9731
|
workingDir: resolvedDir,
|
|
@@ -9811,9 +9783,18 @@ ${installInfo}`
|
|
|
9811
9783
|
serverConn: this.deps.getServerConn(),
|
|
9812
9784
|
settings: {},
|
|
9813
9785
|
onPtyData: (data) => {
|
|
9814
|
-
this.deps.getP2p()?.broadcastPtyOutput(
|
|
9786
|
+
this.deps.getP2p()?.broadcastPtyOutput(cliInstance.instanceId, data);
|
|
9815
9787
|
}
|
|
9816
9788
|
});
|
|
9789
|
+
sessionRegistry?.register({
|
|
9790
|
+
sessionId: cliInstance.instanceId,
|
|
9791
|
+
parentSessionId: null,
|
|
9792
|
+
providerType: normalizedType,
|
|
9793
|
+
providerCategory: "cli",
|
|
9794
|
+
transport: "pty",
|
|
9795
|
+
adapterKey: key,
|
|
9796
|
+
instanceKey: key
|
|
9797
|
+
});
|
|
9817
9798
|
} catch (spawnErr) {
|
|
9818
9799
|
LOG.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
9819
9800
|
instanceManager.removeInstance(key);
|
|
@@ -9835,6 +9816,7 @@ ${installInfo}`
|
|
|
9835
9816
|
if (this.adapters.has(key)) {
|
|
9836
9817
|
this.adapters.delete(key);
|
|
9837
9818
|
this.deps.removeAgentTracking(key);
|
|
9819
|
+
sessionRegistry?.unregisterByInstanceKey(key);
|
|
9838
9820
|
instanceManager.removeInstance(key);
|
|
9839
9821
|
LOG.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
|
|
9840
9822
|
this.deps.onStatusChange();
|
|
@@ -9895,12 +9877,14 @@ ${installInfo}`
|
|
|
9895
9877
|
}
|
|
9896
9878
|
this.adapters.delete(key);
|
|
9897
9879
|
this.deps.removeAgentTracking(key);
|
|
9880
|
+
this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
|
|
9898
9881
|
this.deps.getInstanceManager()?.removeInstance(key);
|
|
9899
9882
|
LOG.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
|
|
9900
9883
|
this.deps.onStatusChange();
|
|
9901
9884
|
} else {
|
|
9902
9885
|
const im = this.deps.getInstanceManager();
|
|
9903
9886
|
if (im) {
|
|
9887
|
+
this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
|
|
9904
9888
|
im.removeInstance(key);
|
|
9905
9889
|
this.deps.removeAgentTracking(key);
|
|
9906
9890
|
LOG.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
|
|
@@ -9915,7 +9899,7 @@ ${installInfo}`
|
|
|
9915
9899
|
// ─── Adapter search ─────────────────────────────
|
|
9916
9900
|
/**
|
|
9917
9901
|
* Search for CLI adapter. Priority order:
|
|
9918
|
-
* 0.
|
|
9902
|
+
* 0. sessionId (UUID direct match)
|
|
9919
9903
|
* 1. agentType + dir (iteration match)
|
|
9920
9904
|
* 2. agentType fuzzy match (⚠ returns first match when multiple sessions exist)
|
|
9921
9905
|
*/
|
|
@@ -9983,7 +9967,7 @@ ${installInfo}`
|
|
|
9983
9967
|
const cliType = args?.cliType;
|
|
9984
9968
|
const dir = args?.dir || "";
|
|
9985
9969
|
if (!cliType) throw new Error("cliType required");
|
|
9986
|
-
const found = this.findAdapter(cliType, { instanceKey: args?.
|
|
9970
|
+
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9987
9971
|
if (found) {
|
|
9988
9972
|
await this.stopSession(found.key);
|
|
9989
9973
|
} else {
|
|
@@ -10015,7 +9999,7 @@ ${installInfo}`
|
|
|
10015
9999
|
}
|
|
10016
10000
|
const dir = rdir.path;
|
|
10017
10001
|
if (!cliType) throw new Error("cliType required");
|
|
10018
|
-
const found = this.findAdapter(cliType, { instanceKey: args?.
|
|
10002
|
+
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
10019
10003
|
if (found) await this.stopSession(found.key);
|
|
10020
10004
|
await this.startSession(cliType, dir);
|
|
10021
10005
|
this.persistRecentDir(cliType, dir);
|
|
@@ -10027,7 +10011,7 @@ ${installInfo}`
|
|
|
10027
10011
|
if (!agentType || !action) throw new Error("agentType and action required");
|
|
10028
10012
|
const found = this.findAdapter(agentType, {
|
|
10029
10013
|
dir: args?.dir,
|
|
10030
|
-
instanceKey: args?.
|
|
10014
|
+
instanceKey: args?.targetSessionId
|
|
10031
10015
|
});
|
|
10032
10016
|
if (!found) throw new Error(`CLI agent not running: ${agentType}`);
|
|
10033
10017
|
const { adapter, key } = found;
|
|
@@ -10173,14 +10157,8 @@ var ProviderStreamAdapter = class {
|
|
|
10173
10157
|
// src/agent-stream/manager.ts
|
|
10174
10158
|
init_logger();
|
|
10175
10159
|
var DaemonAgentStreamManager = class {
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
enabled = true;
|
|
10179
|
-
logFn;
|
|
10180
|
-
lastDiscoveryTimeByScope = /* @__PURE__ */ new Map();
|
|
10181
|
-
discoveryIntervalMsByScope = /* @__PURE__ */ new Map();
|
|
10182
|
-
activeAgentTypeByScope = /* @__PURE__ */ new Map();
|
|
10183
|
-
constructor(logFn, providerLoader) {
|
|
10160
|
+
constructor(logFn, providerLoader, sessionRegistry) {
|
|
10161
|
+
this.sessionRegistry = sessionRegistry;
|
|
10184
10162
|
this.logFn = logFn || LOG.forComponent("AgentStream").asLogFn();
|
|
10185
10163
|
if (providerLoader) {
|
|
10186
10164
|
const allExtProviders = providerLoader.getByCategory("extension");
|
|
@@ -10188,257 +10166,278 @@ var DaemonAgentStreamManager = class {
|
|
|
10188
10166
|
const resolved = providerLoader.resolve(p.type);
|
|
10189
10167
|
if (!resolved) continue;
|
|
10190
10168
|
const adapter = new ProviderStreamAdapter(resolved);
|
|
10191
|
-
this.
|
|
10169
|
+
this.adaptersByType.set(p.type, adapter);
|
|
10192
10170
|
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name}) scripts=${Object.keys(resolved.scripts || {}).join(",") || "none"}`);
|
|
10193
10171
|
}
|
|
10194
10172
|
}
|
|
10195
10173
|
}
|
|
10174
|
+
adaptersByType = /* @__PURE__ */ new Map();
|
|
10175
|
+
managedBySessionId = /* @__PURE__ */ new Map();
|
|
10176
|
+
enabled = true;
|
|
10177
|
+
logFn;
|
|
10178
|
+
lastDiscoveryTimeByParent = /* @__PURE__ */ new Map();
|
|
10179
|
+
discoveryIntervalMsByParent = /* @__PURE__ */ new Map();
|
|
10180
|
+
activeSessionIdByParent = /* @__PURE__ */ new Map();
|
|
10196
10181
|
setEnabled(enabled) {
|
|
10197
10182
|
this.enabled = enabled;
|
|
10198
10183
|
}
|
|
10199
10184
|
get isEnabled() {
|
|
10200
10185
|
return this.enabled;
|
|
10201
10186
|
}
|
|
10202
|
-
|
|
10203
|
-
return this.
|
|
10187
|
+
getActiveSessionId(parentSessionId) {
|
|
10188
|
+
return this.activeSessionIdByParent.get(parentSessionId) || null;
|
|
10204
10189
|
}
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
if (!managed) {
|
|
10208
|
-
managed = /* @__PURE__ */ new Map();
|
|
10209
|
-
this.managedByScope.set(scopeKey, managed);
|
|
10210
|
-
}
|
|
10211
|
-
return managed;
|
|
10190
|
+
getSessionTarget(sessionId) {
|
|
10191
|
+
return this.sessionRegistry?.get(sessionId);
|
|
10212
10192
|
}
|
|
10213
|
-
|
|
10214
|
-
this.
|
|
10215
|
-
this.
|
|
10216
|
-
this.
|
|
10217
|
-
|
|
10193
|
+
resetParentSession(parentSessionId) {
|
|
10194
|
+
const activeSessionId = this.activeSessionIdByParent.get(parentSessionId);
|
|
10195
|
+
if (activeSessionId) this.managedBySessionId.delete(activeSessionId);
|
|
10196
|
+
for (const child of this.sessionRegistry?.listChildren(parentSessionId) || []) {
|
|
10197
|
+
this.managedBySessionId.delete(child.sessionId);
|
|
10198
|
+
}
|
|
10199
|
+
this.activeSessionIdByParent.delete(parentSessionId);
|
|
10200
|
+
this.lastDiscoveryTimeByParent.delete(parentSessionId);
|
|
10201
|
+
this.discoveryIntervalMsByParent.delete(parentSessionId);
|
|
10218
10202
|
}
|
|
10219
10203
|
/** Panel focus based on provider.js focusPanel or extensionId (currently no-op) */
|
|
10220
|
-
async
|
|
10221
|
-
}
|
|
10222
|
-
async
|
|
10223
|
-
const
|
|
10224
|
-
|
|
10225
|
-
if (
|
|
10226
|
-
|
|
10227
|
-
const prev = managed.get(previousAgentType);
|
|
10204
|
+
async ensureSessionPanelOpen(_sessionId) {
|
|
10205
|
+
}
|
|
10206
|
+
async setActiveSession(cdp, parentSessionId, sessionId) {
|
|
10207
|
+
const previousSessionId = this.getActiveSessionId(parentSessionId);
|
|
10208
|
+
if (previousSessionId === sessionId) return;
|
|
10209
|
+
if (previousSessionId) {
|
|
10210
|
+
const prev = this.managedBySessionId.get(previousSessionId);
|
|
10228
10211
|
if (prev) {
|
|
10229
10212
|
try {
|
|
10230
|
-
await cdp.detachAgent(prev.
|
|
10213
|
+
await cdp.detachAgent(prev.cdpSessionId);
|
|
10231
10214
|
} catch {
|
|
10232
10215
|
}
|
|
10233
|
-
|
|
10234
|
-
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName} (${
|
|
10235
|
-
}
|
|
10236
|
-
}
|
|
10237
|
-
this.
|
|
10238
|
-
this.
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
this.
|
|
10216
|
+
this.managedBySessionId.delete(previousSessionId);
|
|
10217
|
+
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName} (${parentSessionId})`);
|
|
10218
|
+
}
|
|
10219
|
+
}
|
|
10220
|
+
this.activeSessionIdByParent.set(parentSessionId, sessionId);
|
|
10221
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
10222
|
+
this.logFn(`[AgentStream] Active session (${parentSessionId}): ${sessionId || "none"}`);
|
|
10223
|
+
}
|
|
10224
|
+
resolveSessionIdForTarget(parentSessionId, agentType) {
|
|
10225
|
+
const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.providerCategory === "extension" && entry.providerType === agentType);
|
|
10226
|
+
return child?.sessionId || null;
|
|
10227
|
+
}
|
|
10228
|
+
async connectManagedSession(cdp, parentSessionId, runtimeSessionId) {
|
|
10229
|
+
const target = this.getSessionTarget(runtimeSessionId);
|
|
10230
|
+
if (!target || target.providerCategory !== "extension") return null;
|
|
10231
|
+
const adapter = this.adaptersByType.get(target.providerType);
|
|
10232
|
+
if (!adapter) return null;
|
|
10233
|
+
const targets = await cdp.discoverAgentWebviews();
|
|
10234
|
+
const activeTarget = targets.find((entry) => entry.agentType === target.providerType);
|
|
10235
|
+
if (!activeTarget) return null;
|
|
10236
|
+
const cdpSessionId = await cdp.attachToAgent(activeTarget);
|
|
10237
|
+
if (!cdpSessionId) return null;
|
|
10238
|
+
const managed = {
|
|
10239
|
+
adapter,
|
|
10240
|
+
runtimeSessionId,
|
|
10241
|
+
parentSessionId,
|
|
10242
|
+
cdpSessionId,
|
|
10243
|
+
target: activeTarget,
|
|
10244
|
+
lastState: null,
|
|
10245
|
+
lastError: null,
|
|
10246
|
+
lastHiddenCheckTime: 0
|
|
10247
|
+
};
|
|
10248
|
+
this.managedBySessionId.set(runtimeSessionId, managed);
|
|
10249
|
+
this.logFn(`[AgentStream] Connected: ${adapter.agentName} (${parentSessionId})`);
|
|
10250
|
+
return managed;
|
|
10243
10251
|
}
|
|
10244
10252
|
/** Agent webview discovery + session connection */
|
|
10245
|
-
async
|
|
10246
|
-
const
|
|
10247
|
-
if (!this.enabled || !
|
|
10253
|
+
async syncActiveSession(cdp, parentSessionId) {
|
|
10254
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
10255
|
+
if (!this.enabled || !activeSessionId) return;
|
|
10248
10256
|
const now = Date.now();
|
|
10249
|
-
const managed = this.
|
|
10250
|
-
const lastDiscoveryTime = this.
|
|
10251
|
-
const discoveryIntervalMs = this.
|
|
10252
|
-
if (managed
|
|
10257
|
+
const managed = this.managedBySessionId.get(activeSessionId);
|
|
10258
|
+
const lastDiscoveryTime = this.lastDiscoveryTimeByParent.get(parentSessionId) || 0;
|
|
10259
|
+
const discoveryIntervalMs = this.discoveryIntervalMsByParent.get(parentSessionId) || 1e4;
|
|
10260
|
+
if (managed && now - lastDiscoveryTime < discoveryIntervalMs) {
|
|
10253
10261
|
return;
|
|
10254
10262
|
}
|
|
10255
|
-
this.
|
|
10263
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, now);
|
|
10256
10264
|
try {
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
if (activeTarget && !managed.has(activeAgentType)) {
|
|
10260
|
-
const adapter = this.allAdapters.find((a) => a.agentType === activeAgentType);
|
|
10261
|
-
if (adapter) {
|
|
10262
|
-
const sessionId = await cdp.attachToAgent(activeTarget);
|
|
10263
|
-
if (sessionId) {
|
|
10264
|
-
managed.set(activeAgentType, {
|
|
10265
|
-
adapter,
|
|
10266
|
-
sessionId,
|
|
10267
|
-
target: activeTarget,
|
|
10268
|
-
lastState: null,
|
|
10269
|
-
lastError: null,
|
|
10270
|
-
lastHiddenCheckTime: 0
|
|
10271
|
-
});
|
|
10272
|
-
this.logFn(`[AgentStream] Connected: ${adapter.agentName} (${scopeKey})`);
|
|
10273
|
-
}
|
|
10274
|
-
}
|
|
10265
|
+
if (!managed) {
|
|
10266
|
+
await this.connectManagedSession(cdp, parentSessionId, activeSessionId);
|
|
10275
10267
|
}
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10268
|
+
this.discoveryIntervalMsByParent.set(parentSessionId, this.managedBySessionId.has(activeSessionId) ? 3e4 : 1e4);
|
|
10269
|
+
} catch (e) {
|
|
10270
|
+
this.logFn(`[AgentStream] sync error (${parentSessionId}): ${e.message}`);
|
|
10271
|
+
}
|
|
10272
|
+
}
|
|
10273
|
+
/** Collect active extension session state */
|
|
10274
|
+
async collectActiveSession(cdp, parentSessionId) {
|
|
10275
|
+
if (!this.enabled) return null;
|
|
10276
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
10277
|
+
if (!activeSessionId) return null;
|
|
10278
|
+
let agent = this.managedBySessionId.get(activeSessionId);
|
|
10279
|
+
if (!agent) {
|
|
10280
|
+
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
10281
|
+
}
|
|
10282
|
+
if (!agent) return null;
|
|
10283
|
+
const type = agent.adapter.agentType;
|
|
10284
|
+
const isHidden = agent.lastState?.status === "panel_hidden";
|
|
10285
|
+
const hiddenCacheFresh = isHidden && Date.now() - agent.lastHiddenCheckTime < 3e4;
|
|
10286
|
+
if (hiddenCacheFresh) return agent.lastState;
|
|
10287
|
+
try {
|
|
10288
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10289
|
+
const state = await agent.adapter.readChat(evaluate);
|
|
10290
|
+
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.error || state._error || "unknown") : ""}`);
|
|
10291
|
+
agent.lastState = state;
|
|
10292
|
+
agent.lastError = null;
|
|
10293
|
+
if (state.status === "panel_hidden") {
|
|
10294
|
+
agent.lastHiddenCheckTime = Date.now();
|
|
10281
10295
|
}
|
|
10282
|
-
|
|
10296
|
+
return state;
|
|
10283
10297
|
} catch (e) {
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
async collectAgentStreams(cdp, scopeKey) {
|
|
10289
|
-
if (!this.enabled) return [];
|
|
10290
|
-
const results = [];
|
|
10291
|
-
const activeAgentType = this.getActiveAgentType(scopeKey);
|
|
10292
|
-
const managed = this.managedByScope.get(scopeKey);
|
|
10293
|
-
if (activeAgentType && managed?.has(activeAgentType)) {
|
|
10294
|
-
const agent = managed.get(activeAgentType);
|
|
10295
|
-
const type = activeAgentType;
|
|
10296
|
-
const isHidden = agent.lastState?.status === "panel_hidden";
|
|
10297
|
-
const hiddenCacheFresh = isHidden && Date.now() - agent.lastHiddenCheckTime < 3e4;
|
|
10298
|
-
if (hiddenCacheFresh) {
|
|
10299
|
-
results.push(agent.lastState);
|
|
10300
|
-
} else {
|
|
10298
|
+
const errorMsg = e?.message || String(e);
|
|
10299
|
+
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
10300
|
+
agent.lastError = errorMsg;
|
|
10301
|
+
if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
|
|
10301
10302
|
try {
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
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.error || state._error || "unknown") : ""}`);
|
|
10305
|
-
agent.lastState = state;
|
|
10306
|
-
agent.lastError = null;
|
|
10307
|
-
if (state.status === "panel_hidden") {
|
|
10308
|
-
agent.lastHiddenCheckTime = Date.now();
|
|
10309
|
-
}
|
|
10310
|
-
results.push(state);
|
|
10311
|
-
} catch (e) {
|
|
10312
|
-
const errorMsg = e?.message || String(e);
|
|
10313
|
-
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
10314
|
-
agent.lastError = errorMsg;
|
|
10315
|
-
results.push({
|
|
10316
|
-
agentType: type,
|
|
10317
|
-
agentName: agent.adapter.agentName,
|
|
10318
|
-
extensionId: agent.adapter.extensionId,
|
|
10319
|
-
status: "disconnected",
|
|
10320
|
-
messages: agent.lastState?.messages || [],
|
|
10321
|
-
inputContent: ""
|
|
10322
|
-
});
|
|
10323
|
-
if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
|
|
10324
|
-
try {
|
|
10325
|
-
await cdp.detachAgent(agent.sessionId);
|
|
10326
|
-
} catch {
|
|
10327
|
-
}
|
|
10328
|
-
managed.delete(type);
|
|
10329
|
-
this.lastDiscoveryTimeByScope.set(scopeKey, 0);
|
|
10330
|
-
}
|
|
10303
|
+
await cdp.detachAgent(agent.cdpSessionId);
|
|
10304
|
+
} catch {
|
|
10331
10305
|
}
|
|
10306
|
+
this.managedBySessionId.delete(activeSessionId);
|
|
10307
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
10332
10308
|
}
|
|
10309
|
+
return {
|
|
10310
|
+
agentType: type,
|
|
10311
|
+
agentName: agent.adapter.agentName,
|
|
10312
|
+
extensionId: agent.adapter.extensionId,
|
|
10313
|
+
status: "disconnected",
|
|
10314
|
+
messages: agent.lastState?.messages || [],
|
|
10315
|
+
inputContent: ""
|
|
10316
|
+
};
|
|
10333
10317
|
}
|
|
10334
|
-
return results;
|
|
10335
10318
|
}
|
|
10336
|
-
async
|
|
10337
|
-
await this.
|
|
10338
|
-
const
|
|
10319
|
+
async sendToSession(cdp, sessionId, text) {
|
|
10320
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
10321
|
+
const target = this.getSessionTarget(sessionId);
|
|
10322
|
+
if (!target?.parentSessionId) return false;
|
|
10323
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10324
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10325
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10339
10326
|
if (!agent) return false;
|
|
10340
10327
|
try {
|
|
10341
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10328
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10342
10329
|
await agent.adapter.sendMessage(evaluate, text);
|
|
10343
10330
|
return true;
|
|
10344
10331
|
} catch (e) {
|
|
10345
|
-
this.logFn(`[AgentStream]
|
|
10332
|
+
this.logFn(`[AgentStream] sendToSession(${sessionId}) error: ${e.message}`);
|
|
10346
10333
|
return false;
|
|
10347
10334
|
}
|
|
10348
10335
|
}
|
|
10349
|
-
async
|
|
10350
|
-
await this.
|
|
10351
|
-
const
|
|
10336
|
+
async resolveSessionAction(cdp, sessionId, action) {
|
|
10337
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
10338
|
+
const target = this.getSessionTarget(sessionId);
|
|
10339
|
+
if (!target?.parentSessionId) return false;
|
|
10340
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10341
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10342
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10352
10343
|
if (!agent) return false;
|
|
10353
10344
|
try {
|
|
10354
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10345
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10355
10346
|
return await agent.adapter.resolveAction(evaluate, action);
|
|
10356
10347
|
} catch (e) {
|
|
10357
|
-
this.logFn(`[AgentStream] resolveAction(${
|
|
10348
|
+
this.logFn(`[AgentStream] resolveAction(${sessionId}) error: ${e.message}`);
|
|
10358
10349
|
return false;
|
|
10359
10350
|
}
|
|
10360
10351
|
}
|
|
10361
|
-
async
|
|
10362
|
-
await this.
|
|
10363
|
-
const
|
|
10352
|
+
async newSession(cdp, sessionId) {
|
|
10353
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
10354
|
+
const target = this.getSessionTarget(sessionId);
|
|
10355
|
+
if (!target?.parentSessionId) return false;
|
|
10356
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10357
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10358
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10364
10359
|
if (!agent) return false;
|
|
10365
10360
|
try {
|
|
10366
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10361
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10367
10362
|
await agent.adapter.newSession(evaluate);
|
|
10368
10363
|
return true;
|
|
10369
10364
|
} catch (e) {
|
|
10370
|
-
this.logFn(`[AgentStream] newSession(${
|
|
10365
|
+
this.logFn(`[AgentStream] newSession(${sessionId}) error: ${e.message}`);
|
|
10371
10366
|
return false;
|
|
10372
10367
|
}
|
|
10373
10368
|
}
|
|
10374
|
-
async
|
|
10375
|
-
|
|
10376
|
-
if (!
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
|
|
10380
|
-
agent = this.getManagedAgent(agentType, scopeKey);
|
|
10381
|
-
}
|
|
10369
|
+
async listSessionChats(cdp, sessionId) {
|
|
10370
|
+
const target = this.getSessionTarget(sessionId);
|
|
10371
|
+
if (!target?.parentSessionId) return [];
|
|
10372
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10373
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10374
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10382
10375
|
if (!agent || typeof agent.adapter.listChats !== "function") return [];
|
|
10383
10376
|
try {
|
|
10384
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10377
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10385
10378
|
return await agent.adapter.listChats(evaluate);
|
|
10386
10379
|
} catch (e) {
|
|
10387
|
-
this.logFn(`[AgentStream] listChats(${
|
|
10380
|
+
this.logFn(`[AgentStream] listChats(${sessionId}) error: ${e.message}`);
|
|
10388
10381
|
return [];
|
|
10389
10382
|
}
|
|
10390
10383
|
}
|
|
10391
|
-
async
|
|
10392
|
-
|
|
10393
|
-
if (!
|
|
10394
|
-
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
agent = this.getManagedAgent(agentType, scopeKey);
|
|
10398
|
-
}
|
|
10384
|
+
async switchConversation(cdp, sessionId, conversationId) {
|
|
10385
|
+
const target = this.getSessionTarget(sessionId);
|
|
10386
|
+
if (!target?.parentSessionId) return false;
|
|
10387
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10388
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10389
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10399
10390
|
if (!agent || typeof agent.adapter.switchSession !== "function") return false;
|
|
10400
10391
|
try {
|
|
10401
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10402
|
-
return await agent.adapter.switchSession(evaluate,
|
|
10392
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10393
|
+
return await agent.adapter.switchSession(evaluate, conversationId);
|
|
10403
10394
|
} catch (e) {
|
|
10404
|
-
this.logFn(`[AgentStream] switchSession(${
|
|
10395
|
+
this.logFn(`[AgentStream] switchSession(${sessionId}) error: ${e.message}`);
|
|
10405
10396
|
return false;
|
|
10406
10397
|
}
|
|
10407
10398
|
}
|
|
10408
|
-
async
|
|
10409
|
-
const
|
|
10399
|
+
async focusSession(cdp, sessionId) {
|
|
10400
|
+
const target = this.getSessionTarget(sessionId);
|
|
10401
|
+
if (!target?.parentSessionId) return false;
|
|
10402
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10403
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10404
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10410
10405
|
if (!agent || typeof agent.adapter.focusEditor !== "function") return false;
|
|
10411
10406
|
try {
|
|
10412
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10407
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10413
10408
|
await agent.adapter.focusEditor(evaluate);
|
|
10414
10409
|
return true;
|
|
10415
10410
|
} catch (e) {
|
|
10416
|
-
this.logFn(`[AgentStream] focusEditor(${
|
|
10411
|
+
this.logFn(`[AgentStream] focusEditor(${sessionId}) error: ${e.message}`);
|
|
10417
10412
|
return false;
|
|
10418
10413
|
}
|
|
10419
10414
|
}
|
|
10420
|
-
|
|
10421
|
-
if (
|
|
10422
|
-
|
|
10415
|
+
getConnectedSessions(parentSessionId) {
|
|
10416
|
+
if (parentSessionId) {
|
|
10417
|
+
return [...this.managedBySessionId.values()].filter((entry) => entry.parentSessionId === parentSessionId).map((entry) => entry.runtimeSessionId);
|
|
10418
|
+
}
|
|
10419
|
+
return [...this.managedBySessionId.keys()];
|
|
10423
10420
|
}
|
|
10424
|
-
|
|
10425
|
-
return this.
|
|
10421
|
+
getManagedSession(sessionId) {
|
|
10422
|
+
return this.managedBySessionId.get(sessionId);
|
|
10426
10423
|
}
|
|
10427
10424
|
async dispose(cdpManagers) {
|
|
10428
|
-
for (const
|
|
10429
|
-
const
|
|
10425
|
+
for (const managed of this.managedBySessionId.values()) {
|
|
10426
|
+
const managerKey = this.getSessionTarget(managed.runtimeSessionId)?.cdpManagerKey;
|
|
10427
|
+
const cdp = managerKey ? cdpManagers.get(managerKey) : null;
|
|
10430
10428
|
if (!cdp) continue;
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
|
|
10434
|
-
} catch {
|
|
10435
|
-
}
|
|
10429
|
+
try {
|
|
10430
|
+
await cdp.detachAgent(managed.cdpSessionId);
|
|
10431
|
+
} catch {
|
|
10436
10432
|
}
|
|
10437
10433
|
}
|
|
10438
|
-
this.
|
|
10439
|
-
this.
|
|
10440
|
-
this.
|
|
10441
|
-
this.
|
|
10434
|
+
this.managedBySessionId.clear();
|
|
10435
|
+
this.activeSessionIdByParent.clear();
|
|
10436
|
+
this.lastDiscoveryTimeByParent.clear();
|
|
10437
|
+
this.discoveryIntervalMsByParent.clear();
|
|
10438
|
+
}
|
|
10439
|
+
resolveSessionForAgent(parentSessionId, agentType) {
|
|
10440
|
+
return this.resolveSessionIdForTarget(parentSessionId, agentType);
|
|
10442
10441
|
}
|
|
10443
10442
|
};
|
|
10444
10443
|
|
|
@@ -10455,8 +10454,8 @@ var AgentStreamPoller = class {
|
|
|
10455
10454
|
return null;
|
|
10456
10455
|
}
|
|
10457
10456
|
/** Reset active IDE tracking (e.g., when IDE is stopped) */
|
|
10458
|
-
resetActiveIde(
|
|
10459
|
-
this.deps.agentStreamManager.
|
|
10457
|
+
resetActiveIde(parentSessionId) {
|
|
10458
|
+
this.deps.agentStreamManager.resetParentSession(parentSessionId);
|
|
10460
10459
|
}
|
|
10461
10460
|
/** Start polling (idempotent — ignored if already started) */
|
|
10462
10461
|
start(intervalMs = 5e3) {
|
|
@@ -10478,12 +10477,14 @@ var AgentStreamPoller = class {
|
|
|
10478
10477
|
agentStreamManager,
|
|
10479
10478
|
providerLoader,
|
|
10480
10479
|
instanceManager,
|
|
10481
|
-
cdpManagers
|
|
10480
|
+
cdpManagers,
|
|
10481
|
+
sessionRegistry
|
|
10482
10482
|
} = this.deps;
|
|
10483
10483
|
if (!agentStreamManager || cdpManagers.size === 0) return;
|
|
10484
10484
|
for (const [ideType, cdp] of cdpManagers) {
|
|
10485
10485
|
registerExtensionProviders(providerLoader, cdp, ideType);
|
|
10486
10486
|
const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
|
|
10487
|
+
const parentSessionId = ideInstance?.getInstanceId?.();
|
|
10487
10488
|
if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
|
|
10488
10489
|
const currentExtTypes = new Set(ideInstance.getExtensionTypes());
|
|
10489
10490
|
const enabledExtTypes = new Set(
|
|
@@ -10491,6 +10492,10 @@ var AgentStreamPoller = class {
|
|
|
10491
10492
|
);
|
|
10492
10493
|
for (const extType of currentExtTypes) {
|
|
10493
10494
|
if (!enabledExtTypes.has(extType)) {
|
|
10495
|
+
const extInstance = ideInstance.getExtension?.(extType);
|
|
10496
|
+
if (extInstance?.getInstanceId) {
|
|
10497
|
+
sessionRegistry.unregister(extInstance.getInstanceId());
|
|
10498
|
+
}
|
|
10494
10499
|
ideInstance.removeExtension(extType);
|
|
10495
10500
|
LOG.info("AgentStream", `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
10496
10501
|
}
|
|
@@ -10501,46 +10506,61 @@ var AgentStreamPoller = class {
|
|
|
10501
10506
|
if (extProvider) {
|
|
10502
10507
|
const extSettings = providerLoader.getSettings(extType);
|
|
10503
10508
|
ideInstance.addExtension(extProvider, extSettings);
|
|
10509
|
+
const extInstance = ideInstance.getExtension?.(extType);
|
|
10510
|
+
if (parentSessionId && extInstance?.getInstanceId) {
|
|
10511
|
+
sessionRegistry.register({
|
|
10512
|
+
sessionId: extInstance.getInstanceId(),
|
|
10513
|
+
parentSessionId,
|
|
10514
|
+
providerType: extType,
|
|
10515
|
+
providerCategory: "extension",
|
|
10516
|
+
transport: "cdp-webview",
|
|
10517
|
+
cdpManagerKey: ideType,
|
|
10518
|
+
instanceKey: `ide:${ideType}`
|
|
10519
|
+
});
|
|
10520
|
+
}
|
|
10504
10521
|
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
10505
10522
|
}
|
|
10506
10523
|
}
|
|
10507
10524
|
}
|
|
10508
10525
|
}
|
|
10509
|
-
const
|
|
10510
|
-
if (
|
|
10511
|
-
const
|
|
10512
|
-
|
|
10513
|
-
)
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
await agentStreamManager.switchActiveAgent(cdp, ideType, null);
|
|
10526
|
+
const activeSessionId = parentSessionId ? agentStreamManager.getActiveSessionId(parentSessionId) : null;
|
|
10527
|
+
if (activeSessionId) {
|
|
10528
|
+
const activeTarget = sessionRegistry.get(activeSessionId);
|
|
10529
|
+
const enabledExtTypes = new Set(providerLoader.getEnabledExtensionProviders(ideType).map((p) => p.type));
|
|
10530
|
+
if (!activeTarget || !enabledExtTypes.has(activeTarget.providerType)) {
|
|
10531
|
+
LOG.info("AgentStream", `Active agent ${activeTarget?.providerType || activeSessionId} was disabled for ${ideType} \u2014 detaching`);
|
|
10532
|
+
await agentStreamManager.setActiveSession(cdp, parentSessionId, null);
|
|
10517
10533
|
this.deps.onStreamsUpdated?.(ideType, []);
|
|
10518
10534
|
}
|
|
10519
10535
|
}
|
|
10520
10536
|
if (!cdp.isConnected) {
|
|
10521
|
-
if (
|
|
10522
|
-
agentStreamManager.
|
|
10537
|
+
if (parentSessionId && activeSessionId) {
|
|
10538
|
+
agentStreamManager.resetParentSession(parentSessionId);
|
|
10523
10539
|
this.deps.onStreamsUpdated?.(ideType, []);
|
|
10524
10540
|
}
|
|
10525
10541
|
continue;
|
|
10526
10542
|
}
|
|
10527
|
-
let
|
|
10528
|
-
if (!
|
|
10543
|
+
let resolvedActiveSessionId = activeSessionId;
|
|
10544
|
+
if (!resolvedActiveSessionId && parentSessionId) {
|
|
10529
10545
|
try {
|
|
10530
10546
|
const discovered = await cdp.discoverAgentWebviews();
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
10534
|
-
|
|
10547
|
+
for (const target of discovered) {
|
|
10548
|
+
const sessionId = agentStreamManager.resolveSessionForAgent(parentSessionId, target.agentType);
|
|
10549
|
+
if (sessionId) {
|
|
10550
|
+
resolvedActiveSessionId = sessionId;
|
|
10551
|
+
await agentStreamManager.setActiveSession(cdp, parentSessionId, sessionId);
|
|
10552
|
+
LOG.info("AgentStream", `Auto-activated: ${target.agentType} (${ideType})`);
|
|
10553
|
+
break;
|
|
10554
|
+
}
|
|
10535
10555
|
}
|
|
10536
10556
|
} catch {
|
|
10537
10557
|
}
|
|
10538
10558
|
}
|
|
10539
|
-
if (!
|
|
10559
|
+
if (!resolvedActiveSessionId || !parentSessionId) continue;
|
|
10540
10560
|
try {
|
|
10541
|
-
await agentStreamManager.
|
|
10542
|
-
const
|
|
10543
|
-
this.deps.onStreamsUpdated?.(ideType,
|
|
10561
|
+
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
10562
|
+
const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
10563
|
+
this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
|
|
10544
10564
|
} catch {
|
|
10545
10565
|
}
|
|
10546
10566
|
}
|
|
@@ -10629,6 +10649,7 @@ var ProviderInstanceManager = class {
|
|
|
10629
10649
|
...event,
|
|
10630
10650
|
providerType: instance.type,
|
|
10631
10651
|
instanceId: state.instanceId,
|
|
10652
|
+
targetSessionId: state.instanceId,
|
|
10632
10653
|
providerCategory: state.category
|
|
10633
10654
|
});
|
|
10634
10655
|
}
|
|
@@ -14439,6 +14460,63 @@ function launchIDE(ide, workspacePath) {
|
|
|
14439
14460
|
}
|
|
14440
14461
|
}
|
|
14441
14462
|
|
|
14463
|
+
// src/sessions/registry.ts
|
|
14464
|
+
var SessionRegistry = class {
|
|
14465
|
+
bySessionId = /* @__PURE__ */ new Map();
|
|
14466
|
+
byManagerKey = /* @__PURE__ */ new Map();
|
|
14467
|
+
byInstanceKey = /* @__PURE__ */ new Map();
|
|
14468
|
+
byParentSessionId = /* @__PURE__ */ new Map();
|
|
14469
|
+
register(target) {
|
|
14470
|
+
this.unregister(target.sessionId);
|
|
14471
|
+
this.bySessionId.set(target.sessionId, target);
|
|
14472
|
+
if (target.cdpManagerKey) this.addIndex(this.byManagerKey, target.cdpManagerKey, target.sessionId);
|
|
14473
|
+
if (target.instanceKey) this.addIndex(this.byInstanceKey, target.instanceKey, target.sessionId);
|
|
14474
|
+
if (target.parentSessionId) this.addIndex(this.byParentSessionId, target.parentSessionId, target.sessionId);
|
|
14475
|
+
}
|
|
14476
|
+
get(sessionId) {
|
|
14477
|
+
if (!sessionId) return void 0;
|
|
14478
|
+
return this.bySessionId.get(sessionId);
|
|
14479
|
+
}
|
|
14480
|
+
unregister(sessionId) {
|
|
14481
|
+
if (!sessionId) return;
|
|
14482
|
+
const target = this.bySessionId.get(sessionId);
|
|
14483
|
+
if (!target) return;
|
|
14484
|
+
this.bySessionId.delete(sessionId);
|
|
14485
|
+
if (target.cdpManagerKey) this.removeIndex(this.byManagerKey, target.cdpManagerKey, sessionId);
|
|
14486
|
+
if (target.instanceKey) this.removeIndex(this.byInstanceKey, target.instanceKey, sessionId);
|
|
14487
|
+
if (target.parentSessionId) this.removeIndex(this.byParentSessionId, target.parentSessionId, sessionId);
|
|
14488
|
+
}
|
|
14489
|
+
unregisterByManagerKey(managerKey) {
|
|
14490
|
+
for (const sessionId of [...this.byManagerKey.get(managerKey) || []]) {
|
|
14491
|
+
this.unregister(sessionId);
|
|
14492
|
+
}
|
|
14493
|
+
}
|
|
14494
|
+
unregisterByInstanceKey(instanceKey) {
|
|
14495
|
+
for (const sessionId of [...this.byInstanceKey.get(instanceKey) || []]) {
|
|
14496
|
+
this.unregister(sessionId);
|
|
14497
|
+
}
|
|
14498
|
+
}
|
|
14499
|
+
listChildren(parentSessionId) {
|
|
14500
|
+
const ids = this.byParentSessionId.get(parentSessionId);
|
|
14501
|
+
if (!ids) return [];
|
|
14502
|
+
return [...ids].map((id) => this.bySessionId.get(id)).filter(Boolean);
|
|
14503
|
+
}
|
|
14504
|
+
addIndex(index, key, sessionId) {
|
|
14505
|
+
let set = index.get(key);
|
|
14506
|
+
if (!set) {
|
|
14507
|
+
set = /* @__PURE__ */ new Set();
|
|
14508
|
+
index.set(key, set);
|
|
14509
|
+
}
|
|
14510
|
+
set.add(sessionId);
|
|
14511
|
+
}
|
|
14512
|
+
removeIndex(index, key, sessionId) {
|
|
14513
|
+
const set = index.get(key);
|
|
14514
|
+
if (!set) return;
|
|
14515
|
+
set.delete(sessionId);
|
|
14516
|
+
if (set.size === 0) index.delete(key);
|
|
14517
|
+
}
|
|
14518
|
+
};
|
|
14519
|
+
|
|
14442
14520
|
// src/boot/daemon-lifecycle.ts
|
|
14443
14521
|
init_logger();
|
|
14444
14522
|
init_config();
|
|
@@ -14478,11 +14556,14 @@ async function initDaemonComponents(config) {
|
|
|
14478
14556
|
});
|
|
14479
14557
|
const instanceManager = new ProviderInstanceManager();
|
|
14480
14558
|
const cdpManagers = /* @__PURE__ */ new Map();
|
|
14481
|
-
const
|
|
14559
|
+
const sessionRegistry = new SessionRegistry();
|
|
14482
14560
|
const detectedIdesRef = { value: [] };
|
|
14561
|
+
let agentStreamManager = null;
|
|
14562
|
+
let poller = null;
|
|
14483
14563
|
const cliManager = new DaemonCliManager({
|
|
14484
14564
|
...config.cliManagerDeps,
|
|
14485
|
-
getInstanceManager: () => instanceManager
|
|
14565
|
+
getInstanceManager: () => instanceManager,
|
|
14566
|
+
getSessionRegistry: () => sessionRegistry
|
|
14486
14567
|
}, providerLoader);
|
|
14487
14568
|
LOG.info("Init", "Detecting IDEs...");
|
|
14488
14569
|
detectedIdesRef.value = await detectIDEs();
|
|
@@ -14492,7 +14573,7 @@ async function initDaemonComponents(config) {
|
|
|
14492
14573
|
providerLoader,
|
|
14493
14574
|
instanceManager,
|
|
14494
14575
|
cdpManagers,
|
|
14495
|
-
|
|
14576
|
+
sessionRegistry
|
|
14496
14577
|
};
|
|
14497
14578
|
const cdpInitializer = new DaemonCdpInitializer({
|
|
14498
14579
|
providerLoader,
|
|
@@ -14501,6 +14582,19 @@ async function initDaemonComponents(config) {
|
|
|
14501
14582
|
onConnected: async (ideType, manager, managerKey) => {
|
|
14502
14583
|
await setupIdeInstance(cdpSetupContext, { ideType, manager, managerKey });
|
|
14503
14584
|
await config.onCdpManagerSetup?.(ideType, manager, managerKey);
|
|
14585
|
+
},
|
|
14586
|
+
onDisconnected: async (_ideType, _manager, managerKey) => {
|
|
14587
|
+
sessionRegistry.unregisterByManagerKey(managerKey);
|
|
14588
|
+
const instanceKey = `ide:${managerKey}`;
|
|
14589
|
+
const ideInstance = instanceManager.getInstance(instanceKey);
|
|
14590
|
+
if (ideInstance) {
|
|
14591
|
+
instanceManager.removeInstance(instanceKey);
|
|
14592
|
+
LOG.info("CDP", `Instance removed after disconnect: ${instanceKey}`);
|
|
14593
|
+
}
|
|
14594
|
+
if (ideInstance?.getInstanceId) {
|
|
14595
|
+
agentStreamManager?.resetParentSession(ideInstance.getInstanceId());
|
|
14596
|
+
}
|
|
14597
|
+
config.onStatusChange?.();
|
|
14504
14598
|
}
|
|
14505
14599
|
});
|
|
14506
14600
|
await cdpInitializer.connectAll(detectedIdesRef.value);
|
|
@@ -14512,14 +14606,14 @@ async function initDaemonComponents(config) {
|
|
|
14512
14606
|
adapters: cliManager.adapters,
|
|
14513
14607
|
providerLoader,
|
|
14514
14608
|
instanceManager,
|
|
14515
|
-
|
|
14609
|
+
sessionRegistry
|
|
14516
14610
|
});
|
|
14517
|
-
|
|
14611
|
+
agentStreamManager = new DaemonAgentStreamManager(
|
|
14518
14612
|
LOG.forComponent("AgentStream").asLogFn(),
|
|
14519
|
-
providerLoader
|
|
14613
|
+
providerLoader,
|
|
14614
|
+
sessionRegistry
|
|
14520
14615
|
);
|
|
14521
14616
|
commandHandler.setAgentStreamManager(agentStreamManager);
|
|
14522
|
-
let poller;
|
|
14523
14617
|
const router = new DaemonCommandRouter({
|
|
14524
14618
|
commandHandler,
|
|
14525
14619
|
cliManager,
|
|
@@ -14527,7 +14621,7 @@ async function initDaemonComponents(config) {
|
|
|
14527
14621
|
providerLoader,
|
|
14528
14622
|
instanceManager,
|
|
14529
14623
|
detectedIdes: detectedIdesRef,
|
|
14530
|
-
|
|
14624
|
+
sessionRegistry,
|
|
14531
14625
|
onCdpManagerCreated: async (ideType, manager) => {
|
|
14532
14626
|
await setupIdeInstance(cdpSetupContext, { ideType, manager });
|
|
14533
14627
|
await config.onCdpManagerSetup?.(ideType, manager, ideType);
|
|
@@ -14542,6 +14636,7 @@ async function initDaemonComponents(config) {
|
|
|
14542
14636
|
providerLoader,
|
|
14543
14637
|
instanceManager,
|
|
14544
14638
|
cdpManagers,
|
|
14639
|
+
sessionRegistry,
|
|
14545
14640
|
onStreamsUpdated: config.onStreamsUpdated
|
|
14546
14641
|
});
|
|
14547
14642
|
poller.start();
|
|
@@ -14556,7 +14651,7 @@ async function initDaemonComponents(config) {
|
|
|
14556
14651
|
poller,
|
|
14557
14652
|
cdpInitializer,
|
|
14558
14653
|
cdpManagers,
|
|
14559
|
-
|
|
14654
|
+
sessionRegistry,
|
|
14560
14655
|
detectedIdes: detectedIdesRef
|
|
14561
14656
|
};
|
|
14562
14657
|
}
|
|
@@ -14630,10 +14725,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
14630
14725
|
ProviderLoader,
|
|
14631
14726
|
VersionArchive,
|
|
14632
14727
|
addCliHistory,
|
|
14633
|
-
|
|
14634
|
-
buildManagedAcps,
|
|
14635
|
-
buildManagedClis,
|
|
14636
|
-
buildManagedIdes,
|
|
14728
|
+
buildSessionEntries,
|
|
14637
14729
|
buildStatusSnapshot,
|
|
14638
14730
|
connectCdpManager,
|
|
14639
14731
|
detectAllVersions,
|