@adhdev/daemon-core 0.6.77 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2342 -0
- package/dist/index.d.ts +86 -932
- package/dist/index.js +879 -664
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14702 -0
- package/dist/index.mjs.map +1 -0
- package/dist/normalize-S2PmiRgB.d.mts +843 -0
- package/dist/normalize-S2PmiRgB.d.ts +843 -0
- package/dist/status/normalize.d.mts +1 -0
- package/dist/status/normalize.d.ts +1 -0
- package/dist/status/normalize.js +73 -0
- package/dist/status/normalize.js.map +1 -0
- package/dist/status/normalize.mjs +45 -0
- package/dist/status/normalize.mjs.map +1 -0
- package/package.json +8 -1
- package/src/agent-stream/manager.ts +213 -150
- package/src/agent-stream/poller.ts +57 -45
- package/src/boot/daemon-lifecycle.ts +30 -12
- package/src/cdp/initializer.ts +47 -0
- package/src/cdp/manager.ts +45 -4
- package/src/cdp/setup.ts +26 -11
- package/src/commands/chat-commands.ts +136 -88
- package/src/commands/cli-manager.ts +31 -6
- package/src/commands/handler.ts +71 -109
- package/src/commands/router.ts +4 -20
- package/src/commands/stream-commands.ts +34 -156
- package/src/daemon-core.ts +3 -9
- package/src/index.ts +8 -5
- package/src/logging/command-log.ts +1 -1
- package/src/providers/acp-provider-instance.ts +4 -0
- package/src/providers/provider-instance-manager.ts +1 -0
- package/src/sessions/registry.ts +76 -0
- package/src/shared-types.ts +45 -54
- package/src/status/builders.ts +157 -120
- package/src/status/normalize.ts +64 -0
- package/src/status/reporter.ts +16 -15
- package/src/status/snapshot.ts +3 -11
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,
|
|
@@ -1814,6 +1811,8 @@ __export(index_exports, {
|
|
|
1814
1811
|
isCdpConnected: () => isCdpConnected,
|
|
1815
1812
|
isExtensionInstalled: () => isExtensionInstalled,
|
|
1816
1813
|
isIdeRunning: () => isIdeRunning,
|
|
1814
|
+
isManagedStatusWaiting: () => isManagedStatusWaiting,
|
|
1815
|
+
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
1817
1816
|
isSetupComplete: () => isSetupComplete,
|
|
1818
1817
|
killIdeProcess: () => killIdeProcess,
|
|
1819
1818
|
launchIDE: () => launchIDE,
|
|
@@ -1821,6 +1820,8 @@ __export(index_exports, {
|
|
|
1821
1820
|
loadConfig: () => loadConfig,
|
|
1822
1821
|
logCommand: () => logCommand,
|
|
1823
1822
|
markSetupComplete: () => markSetupComplete,
|
|
1823
|
+
normalizeActiveChatData: () => normalizeActiveChatData,
|
|
1824
|
+
normalizeManagedStatus: () => normalizeManagedStatus,
|
|
1824
1825
|
probeCdpPort: () => probeCdpPort,
|
|
1825
1826
|
readChatHistory: () => readChatHistory,
|
|
1826
1827
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
@@ -2711,9 +2712,12 @@ var DaemonCdpManager = class {
|
|
|
2711
2712
|
};
|
|
2712
2713
|
try {
|
|
2713
2714
|
const { targetInfos } = await sendWs("Target.getTargets");
|
|
2714
|
-
const
|
|
2715
|
-
|
|
2716
|
-
|
|
2715
|
+
const pageWebviewUrls = await this.getCurrentPageWebviewUrls();
|
|
2716
|
+
const webviewIframes = (targetInfos || []).filter((t) => {
|
|
2717
|
+
if (t.type !== "iframe" || !(t.url || "").includes("vscode-webview")) return false;
|
|
2718
|
+
if (pageWebviewUrls.size === 0) return true;
|
|
2719
|
+
return pageWebviewUrls.has(t.url || "");
|
|
2720
|
+
});
|
|
2717
2721
|
if (webviewIframes.length === 0) {
|
|
2718
2722
|
this.log("[CDP] evaluateInWebviewFrame: no webview iframes found");
|
|
2719
2723
|
return null;
|
|
@@ -2800,6 +2804,7 @@ var DaemonCdpManager = class {
|
|
|
2800
2804
|
const result = await this.sendInternal("Target.getTargets");
|
|
2801
2805
|
allTargets = result?.targetInfos || [];
|
|
2802
2806
|
}
|
|
2807
|
+
const pageWebviewUrls = await this.getCurrentPageWebviewUrls();
|
|
2803
2808
|
const iframes = allTargets.filter((t) => t.type === "iframe");
|
|
2804
2809
|
const typeMap = /* @__PURE__ */ new Map();
|
|
2805
2810
|
for (const t of allTargets) {
|
|
@@ -2825,6 +2830,7 @@ var DaemonCdpManager = class {
|
|
|
2825
2830
|
const url = target.url || "";
|
|
2826
2831
|
const hasWebview = url.includes("vscode-webview");
|
|
2827
2832
|
if (!hasWebview) continue;
|
|
2833
|
+
if (pageWebviewUrls.size > 0 && !pageWebviewUrls.has(url)) continue;
|
|
2828
2834
|
for (const known of this.extensionProviders) {
|
|
2829
2835
|
if (known.extensionIdPattern.test(url)) {
|
|
2830
2836
|
agents.push({
|
|
@@ -2850,7 +2856,11 @@ var DaemonCdpManager = class {
|
|
|
2850
2856
|
async attachToAgent(target) {
|
|
2851
2857
|
if (!this.isConnected) return null;
|
|
2852
2858
|
for (const [sid, t] of this.agentSessions) {
|
|
2853
|
-
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
|
+
}
|
|
2854
2864
|
}
|
|
2855
2865
|
try {
|
|
2856
2866
|
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
@@ -2972,6 +2982,36 @@ var DaemonCdpManager = class {
|
|
|
2972
2982
|
getAgentSessions() {
|
|
2973
2983
|
return this.agentSessions;
|
|
2974
2984
|
}
|
|
2985
|
+
async getCurrentPageWebviewUrls() {
|
|
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
|
+
}
|
|
3001
|
+
try {
|
|
3002
|
+
const raw = await this.evaluate(
|
|
3003
|
+
`JSON.stringify(Array.from(document.querySelectorAll('iframe,webview'))
|
|
3004
|
+
.map((el) => el.src || el.getAttribute('src') || '')
|
|
3005
|
+
.filter((src) => typeof src === 'string' && src.includes('vscode-webview')))`,
|
|
3006
|
+
5e3
|
|
3007
|
+
);
|
|
3008
|
+
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
3009
|
+
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
3010
|
+
return new Set(parsed.filter((src) => typeof src === "string" && src.length > 0));
|
|
3011
|
+
} catch {
|
|
3012
|
+
return /* @__PURE__ */ new Set();
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
2975
3015
|
// ─── Screenshot ──────────────────────────────────────────
|
|
2976
3016
|
async captureScreenshot(opts) {
|
|
2977
3017
|
if (!this.isConnected) return null;
|
|
@@ -4109,7 +4149,7 @@ function registerExtensionProviders(providerLoader, manager, ideType) {
|
|
|
4109
4149
|
manager.setExtensionProviders(enabledExtProviders);
|
|
4110
4150
|
}
|
|
4111
4151
|
async function setupIdeInstance(ctx, opts) {
|
|
4112
|
-
const { providerLoader, instanceManager,
|
|
4152
|
+
const { providerLoader, instanceManager, sessionRegistry } = ctx;
|
|
4113
4153
|
const { ideType, manager, settings } = opts;
|
|
4114
4154
|
const managerKey = opts.managerKey || ideType;
|
|
4115
4155
|
registerExtensionProviders(providerLoader, manager, ideType);
|
|
@@ -4125,14 +4165,30 @@ async function setupIdeInstance(ctx, opts) {
|
|
|
4125
4165
|
serverConn: ctx.serverConn,
|
|
4126
4166
|
settings: resolvedSettings
|
|
4127
4167
|
});
|
|
4128
|
-
|
|
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
|
+
});
|
|
4129
4177
|
const extensionProviders = providerLoader.getEnabledByCategory("extension", ideType);
|
|
4130
4178
|
for (const extProvider of extensionProviders) {
|
|
4131
4179
|
const extSettings = providerLoader.getSettings(extProvider.type);
|
|
4132
4180
|
await ideInstance.addExtension(extProvider, extSettings);
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
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
|
+
});
|
|
4136
4192
|
}
|
|
4137
4193
|
return ideInstance;
|
|
4138
4194
|
}
|
|
@@ -4349,6 +4405,7 @@ var DaemonCdpInitializer = class {
|
|
|
4349
4405
|
async connectIdePort(port, ide) {
|
|
4350
4406
|
const { providerLoader, cdpManagers } = this.config;
|
|
4351
4407
|
const targets = await DaemonCdpManager.listAllTargets(port);
|
|
4408
|
+
await this.pruneStaleManagers(port, ide, targets);
|
|
4352
4409
|
if (targets.length === 0) {
|
|
4353
4410
|
if (cdpManagers.has(ide)) return;
|
|
4354
4411
|
if (!await probeCdpPort(port)) return;
|
|
@@ -4401,6 +4458,34 @@ var DaemonCdpInitializer = class {
|
|
|
4401
4458
|
}
|
|
4402
4459
|
}
|
|
4403
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
|
+
}
|
|
4404
4489
|
// ─── Periodic scanning ───
|
|
4405
4490
|
/**
|
|
4406
4491
|
* Start periodic scanning for newly opened IDEs.
|
|
@@ -4443,6 +4528,45 @@ var DaemonCdpInitializer = class {
|
|
|
4443
4528
|
}
|
|
4444
4529
|
};
|
|
4445
4530
|
|
|
4531
|
+
// src/status/normalize.ts
|
|
4532
|
+
var WORKING_STATUSES = /* @__PURE__ */ new Set([
|
|
4533
|
+
"generating",
|
|
4534
|
+
"streaming",
|
|
4535
|
+
"loading",
|
|
4536
|
+
"loading_reference",
|
|
4537
|
+
"thinking",
|
|
4538
|
+
"active"
|
|
4539
|
+
]);
|
|
4540
|
+
function hasApprovalButtons(activeModal) {
|
|
4541
|
+
return (activeModal?.buttons?.length ?? 0) > 0;
|
|
4542
|
+
}
|
|
4543
|
+
function normalizeManagedStatus(status, opts) {
|
|
4544
|
+
if (hasApprovalButtons(opts?.activeModal)) return "waiting_approval";
|
|
4545
|
+
const normalized = String(status || "idle").trim().toLowerCase();
|
|
4546
|
+
if (normalized === "waiting_approval") return "waiting_approval";
|
|
4547
|
+
if (WORKING_STATUSES.has(normalized)) return "generating";
|
|
4548
|
+
if (normalized === "error") return "error";
|
|
4549
|
+
if (normalized === "stopped") return "stopped";
|
|
4550
|
+
if (normalized === "starting") return "starting";
|
|
4551
|
+
if (normalized === "panel_hidden") return "panel_hidden";
|
|
4552
|
+
if (normalized === "not_monitored") return "not_monitored";
|
|
4553
|
+
if (normalized === "disconnected") return "disconnected";
|
|
4554
|
+
return "idle";
|
|
4555
|
+
}
|
|
4556
|
+
function isManagedStatusWorking(status) {
|
|
4557
|
+
return normalizeManagedStatus(status) === "generating";
|
|
4558
|
+
}
|
|
4559
|
+
function isManagedStatusWaiting(status, opts) {
|
|
4560
|
+
return normalizeManagedStatus(status, opts) === "waiting_approval";
|
|
4561
|
+
}
|
|
4562
|
+
function normalizeActiveChatData(activeChat) {
|
|
4563
|
+
if (!activeChat) return activeChat;
|
|
4564
|
+
return {
|
|
4565
|
+
...activeChat,
|
|
4566
|
+
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
|
|
4567
|
+
};
|
|
4568
|
+
}
|
|
4569
|
+
|
|
4446
4570
|
// src/status/builders.ts
|
|
4447
4571
|
function findCdpManager(cdpManagers, key) {
|
|
4448
4572
|
const exact = cdpManagers.get(key);
|
|
@@ -4465,95 +4589,152 @@ function isCdpConnected(cdpManagers, key) {
|
|
|
4465
4589
|
const m = findCdpManager(cdpManagers, key);
|
|
4466
4590
|
return m?.isConnected ?? false;
|
|
4467
4591
|
}
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
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
|
+
};
|
|
4518
4653
|
}
|
|
4519
|
-
function
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
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
|
+
};
|
|
4530
4675
|
}
|
|
4531
|
-
function
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
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
|
+
};
|
|
4695
|
+
}
|
|
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
|
+
};
|
|
4547
4719
|
}
|
|
4548
|
-
function
|
|
4720
|
+
function buildSessionEntries(allStates, cdpManagers) {
|
|
4721
|
+
const sessions = [];
|
|
4549
4722
|
const ideStates = allStates.filter((s) => s.category === "ide");
|
|
4550
4723
|
const cliStates = allStates.filter((s) => s.category === "cli");
|
|
4551
4724
|
const acpStates = allStates.filter((s) => s.category === "acp");
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
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;
|
|
4557
4738
|
}
|
|
4558
4739
|
|
|
4559
4740
|
// src/commands/handler.ts
|
|
@@ -4562,14 +4743,37 @@ init_logger();
|
|
|
4562
4743
|
|
|
4563
4744
|
// src/commands/chat-commands.ts
|
|
4564
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
|
+
}
|
|
4565
4754
|
function getTargetedCliAdapter(h, args, providerType) {
|
|
4566
|
-
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;
|
|
4567
4770
|
}
|
|
4568
4771
|
async function handleChatHistory(h, args) {
|
|
4569
|
-
const { agentType, offset, limit
|
|
4772
|
+
const { agentType, offset, limit } = args;
|
|
4773
|
+
const instanceId = args?.targetSessionId;
|
|
4570
4774
|
try {
|
|
4571
4775
|
const provider = h.getProvider(agentType);
|
|
4572
|
-
const agentStr = provider?.type || agentType || h
|
|
4776
|
+
const agentStr = provider?.type || agentType || getCurrentProviderType(h);
|
|
4573
4777
|
const result = readChatHistory(agentStr, offset || 0, limit || 30, instanceId);
|
|
4574
4778
|
return { success: true, ...result, agent: agentStr };
|
|
4575
4779
|
} catch (e) {
|
|
@@ -4613,7 +4817,7 @@ async function handleReadChat(h, args) {
|
|
|
4613
4817
|
provider.type || "unknown_extension",
|
|
4614
4818
|
parsed.messages || [],
|
|
4615
4819
|
parsed.title,
|
|
4616
|
-
args?.
|
|
4820
|
+
args?.targetSessionId
|
|
4617
4821
|
);
|
|
4618
4822
|
return { success: true, ...parsed };
|
|
4619
4823
|
}
|
|
@@ -4623,15 +4827,18 @@ async function handleReadChat(h, args) {
|
|
|
4623
4827
|
}
|
|
4624
4828
|
if (h.agentStream) {
|
|
4625
4829
|
const cdp2 = h.getCdp();
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
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
|
+
}
|
|
4629
4836
|
if (stream) {
|
|
4630
4837
|
h.historyWriter.appendNewMessages(
|
|
4631
4838
|
stream.agentType,
|
|
4632
4839
|
stream.messages || [],
|
|
4633
4840
|
void 0,
|
|
4634
|
-
args?.
|
|
4841
|
+
args?.targetSessionId
|
|
4635
4842
|
);
|
|
4636
4843
|
return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
|
|
4637
4844
|
}
|
|
@@ -4658,10 +4865,10 @@ async function handleReadChat(h, args) {
|
|
|
4658
4865
|
if (parsed && typeof parsed === "object") {
|
|
4659
4866
|
_log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
|
|
4660
4867
|
h.historyWriter.appendNewMessages(
|
|
4661
|
-
provider?.type || h
|
|
4868
|
+
provider?.type || getCurrentProviderType(h, "unknown_webview"),
|
|
4662
4869
|
parsed.messages || [],
|
|
4663
4870
|
parsed.title,
|
|
4664
|
-
args?.
|
|
4871
|
+
args?.targetSessionId
|
|
4665
4872
|
);
|
|
4666
4873
|
return { success: true, ...parsed };
|
|
4667
4874
|
}
|
|
@@ -4685,10 +4892,10 @@ async function handleReadChat(h, args) {
|
|
|
4685
4892
|
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
4686
4893
|
_log(`OK: ${parsed.messages?.length} msgs`);
|
|
4687
4894
|
h.historyWriter.appendNewMessages(
|
|
4688
|
-
provider?.type || h
|
|
4895
|
+
provider?.type || getCurrentProviderType(h, "unknown_ide"),
|
|
4689
4896
|
parsed.messages || [],
|
|
4690
4897
|
parsed.title,
|
|
4691
|
-
args?.
|
|
4898
|
+
args?.targetSessionId
|
|
4692
4899
|
);
|
|
4693
4900
|
return { success: true, ...parsed };
|
|
4694
4901
|
}
|
|
@@ -4703,16 +4910,21 @@ async function handleSendChat(h, args) {
|
|
|
4703
4910
|
if (!text) return { success: false, error: "text required" };
|
|
4704
4911
|
const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
|
|
4705
4912
|
const provider = h.getProvider(args?.agentType);
|
|
4913
|
+
const dedupeKey = buildRecentSendKey(h, args, provider, text);
|
|
4706
4914
|
const _logSendSuccess = (method, targetAgent) => {
|
|
4707
4915
|
h.historyWriter.appendNewMessages(
|
|
4708
|
-
targetAgent || provider?.type || h
|
|
4916
|
+
targetAgent || provider?.type || getCurrentProviderType(h, "unknown_agent"),
|
|
4709
4917
|
[{ role: "user", content: text, receivedAt: Date.now() }],
|
|
4710
4918
|
void 0,
|
|
4711
4919
|
// title
|
|
4712
|
-
args?.
|
|
4920
|
+
args?.targetSessionId
|
|
4713
4921
|
);
|
|
4714
4922
|
return { success: true, sent: true, method, targetAgent };
|
|
4715
4923
|
};
|
|
4924
|
+
if (isRecentDuplicateSend(dedupeKey)) {
|
|
4925
|
+
_log(`Suppressed duplicate send for ${dedupeKey}`);
|
|
4926
|
+
return { success: true, sent: false, deduplicated: true };
|
|
4927
|
+
}
|
|
4716
4928
|
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
4717
4929
|
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
4718
4930
|
if (adapter) {
|
|
@@ -4748,8 +4960,9 @@ async function handleSendChat(h, args) {
|
|
|
4748
4960
|
} catch (e) {
|
|
4749
4961
|
_log(`Extension script error: ${e.message}`);
|
|
4750
4962
|
}
|
|
4751
|
-
|
|
4752
|
-
|
|
4963
|
+
const extensionSessionId = h.currentSession?.sessionId;
|
|
4964
|
+
if (h.agentStream && h.getCdp() && extensionSessionId) {
|
|
4965
|
+
const ok = await h.agentStream.sendToSession(h.getCdp(), extensionSessionId, text);
|
|
4753
4966
|
if (ok) {
|
|
4754
4967
|
_log(`AgentStreamManager sent OK`);
|
|
4755
4968
|
return _logSendSuccess("agent-stream");
|
|
@@ -4759,45 +4972,11 @@ async function handleSendChat(h, args) {
|
|
|
4759
4972
|
}
|
|
4760
4973
|
const targetCdp = h.getCdp();
|
|
4761
4974
|
if (!targetCdp?.isConnected) {
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
_log(`Targeting IDE: ${h.currentIdeType}`);
|
|
4766
|
-
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
4767
|
-
try {
|
|
4768
|
-
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4769
|
-
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
4770
|
-
const matchText = provider.webviewMatchText;
|
|
4771
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4772
|
-
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
4773
|
-
let wvParsed = wvResult;
|
|
4774
|
-
if (typeof wvResult === "string") {
|
|
4775
|
-
try {
|
|
4776
|
-
wvParsed = JSON.parse(wvResult);
|
|
4777
|
-
} catch {
|
|
4778
|
-
}
|
|
4779
|
-
}
|
|
4780
|
-
if (wvParsed?.sent) {
|
|
4781
|
-
_log(`webviewSendMessage (priority) OK`);
|
|
4782
|
-
return _logSendSuccess("webview-script-priority");
|
|
4783
|
-
}
|
|
4784
|
-
_log(`webviewSendMessage (priority) did not confirm sent, falling through`);
|
|
4785
|
-
}
|
|
4786
|
-
} catch (e) {
|
|
4787
|
-
_log(`webviewSendMessage (priority) failed: ${e.message}, falling through`);
|
|
4788
|
-
}
|
|
4789
|
-
}
|
|
4790
|
-
if (provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
4791
|
-
try {
|
|
4792
|
-
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
4793
|
-
if (sent) {
|
|
4794
|
-
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
4795
|
-
return _logSendSuccess("typeAndSend-provider");
|
|
4796
|
-
}
|
|
4797
|
-
} catch (e) {
|
|
4798
|
-
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
4799
|
-
}
|
|
4975
|
+
const managerKey = getCurrentManagerKey(h);
|
|
4976
|
+
_log(`No CDP for ${managerKey}`);
|
|
4977
|
+
return { success: false, error: `CDP for ${managerKey || "unknown"} not connected` };
|
|
4800
4978
|
}
|
|
4979
|
+
_log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
|
|
4801
4980
|
const sendScript = h.getProviderScript("sendMessage", { MESSAGE: text });
|
|
4802
4981
|
if (sendScript) {
|
|
4803
4982
|
try {
|
|
@@ -4824,7 +5003,30 @@ async function handleSendChat(h, args) {
|
|
|
4824
5003
|
_log(`typeAndSend(script.selector) failed: ${e.message}`);
|
|
4825
5004
|
}
|
|
4826
5005
|
}
|
|
4827
|
-
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) {
|
|
4828
5030
|
try {
|
|
4829
5031
|
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4830
5032
|
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
@@ -4847,20 +5049,44 @@ async function handleSendChat(h, args) {
|
|
|
4847
5049
|
_log(`webviewSendMessage failed: ${e.message}`);
|
|
4848
5050
|
}
|
|
4849
5051
|
}
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
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 {
|
|
4857
5070
|
}
|
|
4858
|
-
}
|
|
4859
|
-
|
|
5071
|
+
}
|
|
5072
|
+
if (wvParsed?.sent) {
|
|
5073
|
+
_log(`webviewSendMessage OK`);
|
|
5074
|
+
return _logSendSuccess("webview-script");
|
|
4860
5075
|
}
|
|
4861
5076
|
}
|
|
4862
5077
|
} catch (e) {
|
|
4863
|
-
_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}`);
|
|
4864
5090
|
}
|
|
4865
5091
|
}
|
|
4866
5092
|
_log("All methods failed");
|
|
@@ -4868,9 +5094,9 @@ async function handleSendChat(h, args) {
|
|
|
4868
5094
|
}
|
|
4869
5095
|
async function handleListChats(h, args) {
|
|
4870
5096
|
const provider = h.getProvider(args?.agentType);
|
|
4871
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
5097
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
4872
5098
|
try {
|
|
4873
|
-
const chats = await h.agentStream.
|
|
5099
|
+
const chats = await h.agentStream.listSessionChats(h.getCdp(), h.currentSession.sessionId);
|
|
4874
5100
|
LOG.info("Command", `[list_chats] Extension: ${chats.length} chats`);
|
|
4875
5101
|
return { success: true, chats };
|
|
4876
5102
|
} catch (e) {
|
|
@@ -4929,8 +5155,8 @@ async function handleNewChat(h, args) {
|
|
|
4929
5155
|
}
|
|
4930
5156
|
return { success: false, error: "new_chat not supported by this CLI provider" };
|
|
4931
5157
|
}
|
|
4932
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
4933
|
-
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);
|
|
4934
5160
|
return { success: ok };
|
|
4935
5161
|
}
|
|
4936
5162
|
try {
|
|
@@ -4954,15 +5180,15 @@ async function handleNewChat(h, args) {
|
|
|
4954
5180
|
}
|
|
4955
5181
|
async function handleSwitchChat(h, args) {
|
|
4956
5182
|
const provider = h.getProvider(args?.agentType);
|
|
4957
|
-
const
|
|
5183
|
+
const managerKey = getCurrentManagerKey(h);
|
|
4958
5184
|
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
4959
5185
|
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
4960
|
-
LOG.info("Command", `[switch_chat] sessionId=${sessionId},
|
|
4961
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
4962
|
-
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);
|
|
4963
5189
|
return { success: ok, result: ok ? "switched" : "failed" };
|
|
4964
5190
|
}
|
|
4965
|
-
const cdp = h.getCdp(
|
|
5191
|
+
const cdp = h.getCdp(managerKey);
|
|
4966
5192
|
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
4967
5193
|
try {
|
|
4968
5194
|
const webviewScript = h.getProviderScript("webviewSwitchSession", { SESSION_ID: JSON.stringify(sessionId) });
|
|
@@ -5104,7 +5330,7 @@ async function handleSetMode(h, args) {
|
|
|
5104
5330
|
async function handleChangeModel(h, args) {
|
|
5105
5331
|
const provider = h.getProvider(args?.agentType);
|
|
5106
5332
|
const model = args?.model;
|
|
5107
|
-
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)}`);
|
|
5108
5334
|
if (provider?.category === "acp") {
|
|
5109
5335
|
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
5110
5336
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
@@ -5225,13 +5451,8 @@ async function handleResolveAction(h, args) {
|
|
|
5225
5451
|
LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
5226
5452
|
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
5227
5453
|
}
|
|
5228
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
5229
|
-
const ok = await h.agentStream.
|
|
5230
|
-
h.getCdp(),
|
|
5231
|
-
provider.type,
|
|
5232
|
-
action,
|
|
5233
|
-
h.currentIdeType
|
|
5234
|
-
);
|
|
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);
|
|
5235
5456
|
return { success: ok };
|
|
5236
5457
|
}
|
|
5237
5458
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
@@ -5591,151 +5812,37 @@ async function handleFileListBrowse(h, args) {
|
|
|
5591
5812
|
// src/commands/stream-commands.ts
|
|
5592
5813
|
init_config();
|
|
5593
5814
|
init_logger();
|
|
5594
|
-
async function
|
|
5595
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5596
|
-
const agentType = args?.agentType || args?.agent || null;
|
|
5597
|
-
await h.agentStream.switchActiveAgent(h.getCdp(), agentType);
|
|
5598
|
-
return { success: true, activeAgent: agentType };
|
|
5599
|
-
}
|
|
5600
|
-
async function handleAgentStreamRead(h, args) {
|
|
5815
|
+
async function handleFocusSession(h, args) {
|
|
5601
5816
|
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5602
|
-
const
|
|
5603
|
-
return { success:
|
|
5604
|
-
|
|
5605
|
-
async function handleAgentStreamSend(h, args) {
|
|
5606
|
-
const agentType = args?.agentType || args?.agent;
|
|
5607
|
-
const text = args?.text || args?.message;
|
|
5608
|
-
if (!text) return { success: false, error: "text required" };
|
|
5609
|
-
if (agentType && h.ctx.adapters) {
|
|
5610
|
-
for (const [key, adapter] of h.ctx.adapters.entries()) {
|
|
5611
|
-
if (adapter.cliType === agentType || key.includes(agentType)) {
|
|
5612
|
-
LOG.info("Command", `[agent_stream_send] Routing to CLI adapter: ${adapter.cliType}`);
|
|
5613
|
-
try {
|
|
5614
|
-
await adapter.sendMessage(text);
|
|
5615
|
-
return { success: true, sent: true, targetAgent: adapter.cliType };
|
|
5616
|
-
} catch (e) {
|
|
5617
|
-
LOG.info("Command", `[agent_stream_send] CLI adapter failed: ${e.message}`);
|
|
5618
|
-
return { success: false, error: `CLI send failed: ${e.message}` };
|
|
5619
|
-
}
|
|
5620
|
-
}
|
|
5621
|
-
}
|
|
5622
|
-
}
|
|
5623
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5624
|
-
const resolvedAgent = agentType || h.agentStream.activeAgentType;
|
|
5625
|
-
if (!resolvedAgent) return { success: false, error: "agentType required" };
|
|
5626
|
-
const ok = await h.agentStream.sendToAgent(h.getCdp(), resolvedAgent, text, h.currentIdeType);
|
|
5627
|
-
return { success: ok };
|
|
5628
|
-
}
|
|
5629
|
-
async function handleAgentStreamResolve(h, args) {
|
|
5630
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5631
|
-
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
5632
|
-
const action = args?.action || "approve";
|
|
5633
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5634
|
-
const ok = await h.agentStream.resolveAgentAction(h.getCdp(), agentType, action, h.currentIdeType);
|
|
5635
|
-
return { success: ok };
|
|
5636
|
-
}
|
|
5637
|
-
async function handleAgentStreamNew(h, args) {
|
|
5638
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5639
|
-
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
5640
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5641
|
-
const ok = await h.agentStream.newAgentSession(h.getCdp(), agentType, h.currentIdeType);
|
|
5642
|
-
return { success: ok };
|
|
5643
|
-
}
|
|
5644
|
-
async function handleAgentStreamListChats(h, args) {
|
|
5645
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5646
|
-
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
5647
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5648
|
-
const chats = await h.agentStream.listAgentChats(h.getCdp(), agentType);
|
|
5649
|
-
return { success: true, chats };
|
|
5650
|
-
}
|
|
5651
|
-
async function handleAgentStreamSwitchSession(h, args) {
|
|
5652
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5653
|
-
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
5654
|
-
const sessionId = args?.sessionId || args?.id;
|
|
5655
|
-
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
5656
|
-
const ok = await h.agentStream.switchAgentSession(h.getCdp(), agentType, sessionId);
|
|
5657
|
-
return { success: ok };
|
|
5658
|
-
}
|
|
5659
|
-
async function handleAgentStreamFocus(h, args) {
|
|
5660
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5661
|
-
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
5662
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5663
|
-
await h.agentStream.ensureAgentPanelOpen(agentType, h.currentIdeType);
|
|
5664
|
-
const ok = await h.agentStream.focusAgentEditor(h.getCdp(), 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);
|
|
5665
5820
|
return { success: ok };
|
|
5666
5821
|
}
|
|
5667
5822
|
function handlePtyInput(h, args) {
|
|
5668
|
-
const { cliType, data } = args || {};
|
|
5823
|
+
const { cliType, data, targetSessionId } = args || {};
|
|
5669
5824
|
if (!data) return { success: false, error: "data required" };
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
const first = h.ctx.adapters.values().next().value;
|
|
5674
|
-
if (first && typeof first.writeRaw === "function") {
|
|
5675
|
-
first.writeRaw(data);
|
|
5676
|
-
return { success: true };
|
|
5677
|
-
}
|
|
5678
|
-
}
|
|
5679
|
-
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
5680
|
-
if (directAdapter && typeof directAdapter.writeRaw === "function") {
|
|
5681
|
-
directAdapter.writeRaw(data);
|
|
5682
|
-
return { success: true };
|
|
5683
|
-
}
|
|
5684
|
-
for (const [, adapter] of h.ctx.adapters) {
|
|
5685
|
-
if (adapter.cliType === targetCli && typeof adapter.writeRaw === "function") {
|
|
5686
|
-
adapter.writeRaw(data);
|
|
5687
|
-
return { success: true };
|
|
5688
|
-
}
|
|
5689
|
-
}
|
|
5690
|
-
for (const [key, adapter] of h.ctx.adapters) {
|
|
5691
|
-
if ((key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.writeRaw === "function") {
|
|
5692
|
-
adapter.writeRaw(data);
|
|
5693
|
-
return { success: true };
|
|
5694
|
-
}
|
|
5695
|
-
}
|
|
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"}` };
|
|
5696
5828
|
}
|
|
5697
|
-
|
|
5829
|
+
adapter.writeRaw(data);
|
|
5830
|
+
return { success: true };
|
|
5698
5831
|
}
|
|
5699
5832
|
function handlePtyResize(h, args) {
|
|
5700
|
-
const { cliType, cols, rows, force } = args || {};
|
|
5833
|
+
const { cliType, cols, rows, force, targetSessionId } = args || {};
|
|
5701
5834
|
if (!cols || !rows) return { success: false, error: "cols and rows required" };
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
const first = h.ctx.adapters.values().next().value;
|
|
5706
|
-
if (first && typeof first.resize === "function") {
|
|
5707
|
-
if (force) {
|
|
5708
|
-
first.resize(cols - 1, rows);
|
|
5709
|
-
setTimeout(() => first.resize(cols, rows), 50);
|
|
5710
|
-
} else {
|
|
5711
|
-
first.resize(cols, rows);
|
|
5712
|
-
}
|
|
5713
|
-
return { success: true };
|
|
5714
|
-
}
|
|
5715
|
-
}
|
|
5716
|
-
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
5717
|
-
if (directAdapter && typeof directAdapter.resize === "function") {
|
|
5718
|
-
if (force) {
|
|
5719
|
-
directAdapter.resize(cols - 1, rows);
|
|
5720
|
-
setTimeout(() => directAdapter.resize(cols, rows), 50);
|
|
5721
|
-
} else {
|
|
5722
|
-
directAdapter.resize(cols, rows);
|
|
5723
|
-
}
|
|
5724
|
-
return { success: true };
|
|
5725
|
-
}
|
|
5726
|
-
for (const [key, adapter] of h.ctx.adapters) {
|
|
5727
|
-
if ((adapter.cliType === targetCli || key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.resize === "function") {
|
|
5728
|
-
if (force) {
|
|
5729
|
-
adapter.resize(cols - 1, rows);
|
|
5730
|
-
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
5731
|
-
} else {
|
|
5732
|
-
adapter.resize(cols, rows);
|
|
5733
|
-
}
|
|
5734
|
-
return { success: true };
|
|
5735
|
-
}
|
|
5736
|
-
}
|
|
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"}` };
|
|
5737
5838
|
}
|
|
5738
|
-
|
|
5839
|
+
if (force) {
|
|
5840
|
+
adapter.resize(cols - 1, rows);
|
|
5841
|
+
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
5842
|
+
} else {
|
|
5843
|
+
adapter.resize(cols, rows);
|
|
5844
|
+
}
|
|
5845
|
+
return { success: true };
|
|
5739
5846
|
}
|
|
5740
5847
|
function handleGetProviderSettings(h, args) {
|
|
5741
5848
|
const loader = h.ctx.providerLoader;
|
|
@@ -5771,7 +5878,7 @@ function handleSetProviderSetting(h, args) {
|
|
|
5771
5878
|
}
|
|
5772
5879
|
async function handleExtensionScript(h, args, scriptName) {
|
|
5773
5880
|
const { agentType, ideType } = args || {};
|
|
5774
|
-
LOG.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType}
|
|
5881
|
+
LOG.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType} session=${h.currentSession?.sessionId || ""}`);
|
|
5775
5882
|
if (!agentType) return { success: false, error: "agentType is required" };
|
|
5776
5883
|
const loader = h.ctx.providerLoader;
|
|
5777
5884
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -5792,21 +5899,22 @@ async function handleExtensionScript(h, args, scriptName) {
|
|
|
5792
5899
|
}
|
|
5793
5900
|
const scriptCode = scriptFn(normalizedArgs);
|
|
5794
5901
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
5795
|
-
const cdpKey = provider.category === "ide" ? h.
|
|
5902
|
+
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
|
|
5796
5903
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
5797
5904
|
const cdp = h.getCdp(cdpKey);
|
|
5798
5905
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
5799
5906
|
try {
|
|
5800
5907
|
let result;
|
|
5801
5908
|
if (provider.category === "extension") {
|
|
5802
|
-
const
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
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;
|
|
5810
5918
|
const IDE_LEVEL_SCRIPTS = ["listModes", "setMode", "listModels", "setModel"];
|
|
5811
5919
|
if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
|
|
5812
5920
|
if (targetSessionId) {
|
|
@@ -5877,7 +5985,7 @@ function handleGetIdeExtensions(h, args) {
|
|
|
5877
5985
|
enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
|
|
5878
5986
|
}));
|
|
5879
5987
|
}
|
|
5880
|
-
return { success: true,
|
|
5988
|
+
return { success: true, ideExtensions: result };
|
|
5881
5989
|
}
|
|
5882
5990
|
function handleSetIdeExtension(h, args) {
|
|
5883
5991
|
const { ideType, extensionType, enabled } = args || {};
|
|
@@ -5989,10 +6097,8 @@ var DaemonCommandHandler = class {
|
|
|
5989
6097
|
_agentStream = null;
|
|
5990
6098
|
domHandlers;
|
|
5991
6099
|
_historyWriter;
|
|
5992
|
-
/** Current
|
|
5993
|
-
|
|
5994
|
-
/** Current provider type — agentType priority, ideType use */
|
|
5995
|
-
_currentProviderType;
|
|
6100
|
+
/** Current request route context */
|
|
6101
|
+
_currentRoute = {};
|
|
5996
6102
|
constructor(ctx) {
|
|
5997
6103
|
this._ctx = ctx;
|
|
5998
6104
|
this.domHandlers = new CdpDomHandlers((ideType) => this.getCdp(ideType));
|
|
@@ -6008,20 +6114,25 @@ var DaemonCommandHandler = class {
|
|
|
6008
6114
|
get historyWriter() {
|
|
6009
6115
|
return this._historyWriter;
|
|
6010
6116
|
}
|
|
6117
|
+
get currentManagerKey() {
|
|
6118
|
+
return this._currentRoute.managerKey;
|
|
6119
|
+
}
|
|
6011
6120
|
get currentIdeType() {
|
|
6012
|
-
return this.
|
|
6121
|
+
return this._currentRoute.managerKey;
|
|
6013
6122
|
}
|
|
6014
6123
|
get currentProviderType() {
|
|
6015
|
-
return this.
|
|
6124
|
+
return this._currentRoute.providerType;
|
|
6125
|
+
}
|
|
6126
|
+
get currentSession() {
|
|
6127
|
+
return this._currentRoute.session;
|
|
6016
6128
|
}
|
|
6017
|
-
/** Get CDP manager for a specific
|
|
6018
|
-
* Supports exact match, multi-window prefix match, and instanceIdMap UUID lookup.
|
|
6019
|
-
* Returns null if no match — never falls back to another IDE. */
|
|
6129
|
+
/** Get CDP manager for a specific session or manager key. */
|
|
6020
6130
|
getCdp(ideType) {
|
|
6021
|
-
const
|
|
6022
|
-
if (!
|
|
6023
|
-
const
|
|
6024
|
-
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);
|
|
6025
6136
|
if (m?.isConnected) return m;
|
|
6026
6137
|
return null;
|
|
6027
6138
|
}
|
|
@@ -6029,7 +6140,7 @@ var DaemonCommandHandler = class {
|
|
|
6029
6140
|
* Get provider module — _currentProviderType (agentType priority) use.
|
|
6030
6141
|
*/
|
|
6031
6142
|
getProvider(overrideType) {
|
|
6032
|
-
const key = overrideType || this.
|
|
6143
|
+
const key = overrideType || this._currentRoute.providerType || this._currentRoute.session?.providerType || this._currentRoute.managerKey;
|
|
6033
6144
|
if (!key || !this._ctx.providerLoader) return void 0;
|
|
6034
6145
|
const result = this._ctx.providerLoader.resolve(key);
|
|
6035
6146
|
if (result) return result;
|
|
@@ -6062,14 +6173,22 @@ var DaemonCommandHandler = class {
|
|
|
6062
6173
|
const cdp = this.getCdp();
|
|
6063
6174
|
if (!cdp?.isConnected) return null;
|
|
6064
6175
|
if (provider?.category === "extension") {
|
|
6065
|
-
let sessionId = this.
|
|
6066
|
-
if (!sessionId && this.
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
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
|
+
}
|
|
6070
6186
|
}
|
|
6071
6187
|
if (!sessionId) return null;
|
|
6072
|
-
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);
|
|
6073
6192
|
return { result: result2, category: "extension" };
|
|
6074
6193
|
}
|
|
6075
6194
|
const result = await cdp.evaluate(script, timeout);
|
|
@@ -6077,33 +6196,37 @@ var DaemonCommandHandler = class {
|
|
|
6077
6196
|
}
|
|
6078
6197
|
/** CLI adapter search */
|
|
6079
6198
|
getCliAdapter(type) {
|
|
6080
|
-
const target = type || this.
|
|
6199
|
+
const target = type || this._currentRoute.session?.sessionId || this._currentRoute.providerType || this._currentRoute.managerKey;
|
|
6081
6200
|
if (!target || !this._ctx.adapters) return null;
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
const direct = this._ctx.adapters.get(normalizedTarget);
|
|
6086
|
-
if (direct) return direct;
|
|
6087
|
-
for (const [key, adapter] of this._ctx.adapters.entries()) {
|
|
6088
|
-
if (adapter.cliType === target || adapter.cliType === normalizedTarget || key === normalizedTarget || key.startsWith(target) || key.startsWith(normalizedTarget)) {
|
|
6089
|
-
return adapter;
|
|
6090
|
-
}
|
|
6201
|
+
const session = this._ctx.sessionRegistry?.get(target);
|
|
6202
|
+
if (session?.adapterKey) {
|
|
6203
|
+
return this._ctx.adapters.get(session.adapterKey) || null;
|
|
6091
6204
|
}
|
|
6092
|
-
return null;
|
|
6205
|
+
return this._ctx.adapters.get(target) || null;
|
|
6093
6206
|
}
|
|
6094
6207
|
// ─── Private helpers ──────────────────────────────
|
|
6095
|
-
|
|
6096
|
-
if (
|
|
6097
|
-
const
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
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 */
|
|
6101
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
|
+
}
|
|
6102
6227
|
if (args?.ideType) {
|
|
6103
|
-
const
|
|
6104
|
-
if (
|
|
6105
|
-
return mappedKey;
|
|
6106
|
-
}
|
|
6228
|
+
const target = this._ctx.sessionRegistry?.get(args.ideType);
|
|
6229
|
+
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
6107
6230
|
if (this._ctx.cdpManagers.has(args.ideType)) {
|
|
6108
6231
|
return args.ideType;
|
|
6109
6232
|
}
|
|
@@ -6114,33 +6237,6 @@ var DaemonCommandHandler = class {
|
|
|
6114
6237
|
}
|
|
6115
6238
|
}
|
|
6116
6239
|
}
|
|
6117
|
-
if (args?._targetInstance) {
|
|
6118
|
-
let raw = args._targetInstance;
|
|
6119
|
-
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
6120
|
-
const cliMatch = raw.match(/:cli:(.+)$/);
|
|
6121
|
-
const acpMatch = raw.match(/:acp:(.+)$/);
|
|
6122
|
-
if (ideMatch) raw = ideMatch[1];
|
|
6123
|
-
else if (cliMatch) raw = cliMatch[1];
|
|
6124
|
-
else if (acpMatch) raw = acpMatch[1];
|
|
6125
|
-
if (this._ctx.instanceIdMap?.has(raw)) {
|
|
6126
|
-
return this._ctx.instanceIdMap.get(raw);
|
|
6127
|
-
}
|
|
6128
|
-
if (this._ctx.cdpManagers.has(raw)) {
|
|
6129
|
-
return raw;
|
|
6130
|
-
}
|
|
6131
|
-
const found = findCdpManager(this._ctx.cdpManagers, raw);
|
|
6132
|
-
if (found) {
|
|
6133
|
-
for (const [k, m] of this._ctx.cdpManagers.entries()) {
|
|
6134
|
-
if (m === found) return k;
|
|
6135
|
-
}
|
|
6136
|
-
}
|
|
6137
|
-
const lastUnderscore = raw.lastIndexOf("_");
|
|
6138
|
-
if (lastUnderscore > 0) {
|
|
6139
|
-
const stripped = raw.substring(0, lastUnderscore);
|
|
6140
|
-
if (this._ctx.cdpManagers.has(stripped)) return stripped;
|
|
6141
|
-
}
|
|
6142
|
-
return raw;
|
|
6143
|
-
}
|
|
6144
6240
|
return void 0;
|
|
6145
6241
|
}
|
|
6146
6242
|
setAgentStreamManager(manager) {
|
|
@@ -6148,12 +6244,11 @@ var DaemonCommandHandler = class {
|
|
|
6148
6244
|
}
|
|
6149
6245
|
// ─── Command Dispatcher ──────────────────────────
|
|
6150
6246
|
async handle(cmd, args) {
|
|
6151
|
-
this.
|
|
6152
|
-
this.
|
|
6153
|
-
if (!this._currentIdeType && !this._currentProviderType) {
|
|
6247
|
+
this._currentRoute = this.resolveRoute(args);
|
|
6248
|
+
if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
|
|
6154
6249
|
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
6155
6250
|
if (cdpCommands.includes(cmd)) {
|
|
6156
|
-
return { success: false, error: "No
|
|
6251
|
+
return { success: false, error: "No targetSessionId specified \u2014 cannot route command" };
|
|
6157
6252
|
}
|
|
6158
6253
|
}
|
|
6159
6254
|
try {
|
|
@@ -6244,22 +6339,8 @@ var DaemonCommandHandler = class {
|
|
|
6244
6339
|
case "refresh_scripts":
|
|
6245
6340
|
return this.handleRefreshScripts(args);
|
|
6246
6341
|
// ─── Stream commands (stream-commands.ts) ───────────
|
|
6247
|
-
case "
|
|
6248
|
-
return
|
|
6249
|
-
case "agent_stream_read":
|
|
6250
|
-
return handleAgentStreamRead(this, args);
|
|
6251
|
-
case "agent_stream_send":
|
|
6252
|
-
return handleAgentStreamSend(this, args);
|
|
6253
|
-
case "agent_stream_resolve":
|
|
6254
|
-
return handleAgentStreamResolve(this, args);
|
|
6255
|
-
case "agent_stream_new":
|
|
6256
|
-
return handleAgentStreamNew(this, args);
|
|
6257
|
-
case "agent_stream_list_chats":
|
|
6258
|
-
return handleAgentStreamListChats(this, args);
|
|
6259
|
-
case "agent_stream_switch_session":
|
|
6260
|
-
return handleAgentStreamSwitchSession(this, args);
|
|
6261
|
-
case "agent_stream_focus":
|
|
6262
|
-
return handleAgentStreamFocus(this, args);
|
|
6342
|
+
case "focus_session":
|
|
6343
|
+
return handleFocusSession(this, args);
|
|
6263
6344
|
// ─── PTY Raw I/O (stream-commands.ts) ─────────
|
|
6264
6345
|
case "pty_input":
|
|
6265
6346
|
return handlePtyInput(this, args);
|
|
@@ -7907,8 +7988,7 @@ var CHAT_COMMANDS = [
|
|
|
7907
7988
|
"new_chat",
|
|
7908
7989
|
"switch_chat",
|
|
7909
7990
|
"set_mode",
|
|
7910
|
-
"change_model"
|
|
7911
|
-
"agent_stream_send"
|
|
7991
|
+
"change_model"
|
|
7912
7992
|
];
|
|
7913
7993
|
var DaemonCommandRouter = class {
|
|
7914
7994
|
deps;
|
|
@@ -8146,6 +8226,7 @@ var DaemonCommandRouter = class {
|
|
|
8146
8226
|
} catch {
|
|
8147
8227
|
}
|
|
8148
8228
|
this.deps.cdpManagers.delete(key);
|
|
8229
|
+
this.deps.sessionRegistry.unregisterByManagerKey(key);
|
|
8149
8230
|
LOG.info("StopIDE", `CDP disconnected: ${key}`);
|
|
8150
8231
|
}
|
|
8151
8232
|
}
|
|
@@ -8158,14 +8239,6 @@ var DaemonCommandRouter = class {
|
|
|
8158
8239
|
for (const instanceKey of keysToRemove) {
|
|
8159
8240
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
8160
8241
|
if (ideInstance) {
|
|
8161
|
-
if (ideInstance.getInstanceId) {
|
|
8162
|
-
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
8163
|
-
}
|
|
8164
|
-
if (ideInstance.getExtensionInstances) {
|
|
8165
|
-
for (const ext of ideInstance.getExtensionInstances()) {
|
|
8166
|
-
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
8167
|
-
}
|
|
8168
|
-
}
|
|
8169
8242
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
8170
8243
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
8171
8244
|
}
|
|
@@ -8174,14 +8247,6 @@ var DaemonCommandRouter = class {
|
|
|
8174
8247
|
const instanceKey = `ide:${ideType}`;
|
|
8175
8248
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
8176
8249
|
if (ideInstance) {
|
|
8177
|
-
if (ideInstance.getInstanceId) {
|
|
8178
|
-
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
8179
|
-
}
|
|
8180
|
-
if (ideInstance.getExtensionInstances) {
|
|
8181
|
-
for (const ext of ideInstance.getExtensionInstances()) {
|
|
8182
|
-
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
8183
|
-
}
|
|
8184
|
-
}
|
|
8185
8250
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
8186
8251
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
8187
8252
|
}
|
|
@@ -8234,15 +8299,9 @@ function buildStatusSnapshot(options) {
|
|
|
8234
8299
|
const cfg = loadConfig();
|
|
8235
8300
|
const wsState = getWorkspaceState(cfg);
|
|
8236
8301
|
const memSnap = getHostMemorySnapshot();
|
|
8237
|
-
const
|
|
8302
|
+
const sessions = buildSessionEntries(
|
|
8238
8303
|
options.allStates,
|
|
8239
|
-
options.cdpManagers
|
|
8240
|
-
{
|
|
8241
|
-
detectedIdes: options.detectedIdes.map((ide) => ({
|
|
8242
|
-
id: ide.id,
|
|
8243
|
-
installed: ide.installed !== false
|
|
8244
|
-
}))
|
|
8245
|
-
}
|
|
8304
|
+
options.cdpManagers
|
|
8246
8305
|
);
|
|
8247
8306
|
return {
|
|
8248
8307
|
instanceId: options.instanceId,
|
|
@@ -8264,9 +8323,7 @@ function buildStatusSnapshot(options) {
|
|
|
8264
8323
|
timestamp: options.timestamp ?? Date.now(),
|
|
8265
8324
|
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8266
8325
|
...options.p2p ? { p2p: options.p2p } : {},
|
|
8267
|
-
|
|
8268
|
-
managedClis,
|
|
8269
|
-
managedAcps,
|
|
8326
|
+
sessions,
|
|
8270
8327
|
workspaces: wsState.workspaces,
|
|
8271
8328
|
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8272
8329
|
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
@@ -8378,7 +8435,7 @@ var DaemonStatusReporter = class {
|
|
|
8378
8435
|
LOG.info("StatusReport", `\u2192${target} ${baseSummary}`);
|
|
8379
8436
|
}
|
|
8380
8437
|
}
|
|
8381
|
-
const
|
|
8438
|
+
const sessions = buildSessionEntries(
|
|
8382
8439
|
allStates,
|
|
8383
8440
|
this.deps.cdpManagers
|
|
8384
8441
|
);
|
|
@@ -8409,23 +8466,20 @@ var DaemonStatusReporter = class {
|
|
|
8409
8466
|
if (opts?.p2pOnly) return;
|
|
8410
8467
|
const wsPayload = {
|
|
8411
8468
|
daemonMode: true,
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
id: a.id,
|
|
8427
|
-
acpType: a.acpType,
|
|
8428
|
-
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
|
|
8429
8483
|
})),
|
|
8430
8484
|
p2p: payload.p2p,
|
|
8431
8485
|
timestamp: now
|
|
@@ -8856,6 +8910,9 @@ var AcpProviderInstance = class {
|
|
|
8856
8910
|
);
|
|
8857
8911
|
}
|
|
8858
8912
|
}
|
|
8913
|
+
getInstanceId() {
|
|
8914
|
+
return this.instanceId;
|
|
8915
|
+
}
|
|
8859
8916
|
// ─── ACP Config Options & Modes ─────────────────────
|
|
8860
8917
|
parseConfigOptions(raw) {
|
|
8861
8918
|
if (!Array.isArray(raw)) return;
|
|
@@ -9635,6 +9692,7 @@ var DaemonCliManager = class {
|
|
|
9635
9692
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
9636
9693
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
9637
9694
|
const key = crypto4.randomUUID();
|
|
9695
|
+
const sessionRegistry = this.deps.getSessionRegistry?.() || null;
|
|
9638
9696
|
if (provider && provider.category === "acp") {
|
|
9639
9697
|
const instanceManager2 = this.deps.getInstanceManager();
|
|
9640
9698
|
if (!instanceManager2) throw new Error("InstanceManager not available");
|
|
@@ -9658,6 +9716,16 @@ ${installInfo}`
|
|
|
9658
9716
|
await instanceManager2.addInstance(key, acpInstance, {
|
|
9659
9717
|
settings: this.providerLoader.getSettings(normalizedType)
|
|
9660
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
|
+
});
|
|
9661
9729
|
this.adapters.set(key, {
|
|
9662
9730
|
cliType: normalizedType,
|
|
9663
9731
|
workingDir: resolvedDir,
|
|
@@ -9715,9 +9783,18 @@ ${installInfo}`
|
|
|
9715
9783
|
serverConn: this.deps.getServerConn(),
|
|
9716
9784
|
settings: {},
|
|
9717
9785
|
onPtyData: (data) => {
|
|
9718
|
-
this.deps.getP2p()?.broadcastPtyOutput(
|
|
9786
|
+
this.deps.getP2p()?.broadcastPtyOutput(cliInstance.instanceId, data);
|
|
9719
9787
|
}
|
|
9720
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
|
+
});
|
|
9721
9798
|
} catch (spawnErr) {
|
|
9722
9799
|
LOG.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
9723
9800
|
instanceManager.removeInstance(key);
|
|
@@ -9739,6 +9816,7 @@ ${installInfo}`
|
|
|
9739
9816
|
if (this.adapters.has(key)) {
|
|
9740
9817
|
this.adapters.delete(key);
|
|
9741
9818
|
this.deps.removeAgentTracking(key);
|
|
9819
|
+
sessionRegistry?.unregisterByInstanceKey(key);
|
|
9742
9820
|
instanceManager.removeInstance(key);
|
|
9743
9821
|
LOG.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
|
|
9744
9822
|
this.deps.onStatusChange();
|
|
@@ -9799,12 +9877,14 @@ ${installInfo}`
|
|
|
9799
9877
|
}
|
|
9800
9878
|
this.adapters.delete(key);
|
|
9801
9879
|
this.deps.removeAgentTracking(key);
|
|
9880
|
+
this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
|
|
9802
9881
|
this.deps.getInstanceManager()?.removeInstance(key);
|
|
9803
9882
|
LOG.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
|
|
9804
9883
|
this.deps.onStatusChange();
|
|
9805
9884
|
} else {
|
|
9806
9885
|
const im = this.deps.getInstanceManager();
|
|
9807
9886
|
if (im) {
|
|
9887
|
+
this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
|
|
9808
9888
|
im.removeInstance(key);
|
|
9809
9889
|
this.deps.removeAgentTracking(key);
|
|
9810
9890
|
LOG.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
|
|
@@ -9819,7 +9899,7 @@ ${installInfo}`
|
|
|
9819
9899
|
// ─── Adapter search ─────────────────────────────
|
|
9820
9900
|
/**
|
|
9821
9901
|
* Search for CLI adapter. Priority order:
|
|
9822
|
-
* 0.
|
|
9902
|
+
* 0. sessionId (UUID direct match)
|
|
9823
9903
|
* 1. agentType + dir (iteration match)
|
|
9824
9904
|
* 2. agentType fuzzy match (⚠ returns first match when multiple sessions exist)
|
|
9825
9905
|
*/
|
|
@@ -9887,7 +9967,7 @@ ${installInfo}`
|
|
|
9887
9967
|
const cliType = args?.cliType;
|
|
9888
9968
|
const dir = args?.dir || "";
|
|
9889
9969
|
if (!cliType) throw new Error("cliType required");
|
|
9890
|
-
const found = this.findAdapter(cliType, { instanceKey: args?.
|
|
9970
|
+
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9891
9971
|
if (found) {
|
|
9892
9972
|
await this.stopSession(found.key);
|
|
9893
9973
|
} else {
|
|
@@ -9919,7 +9999,7 @@ ${installInfo}`
|
|
|
9919
9999
|
}
|
|
9920
10000
|
const dir = rdir.path;
|
|
9921
10001
|
if (!cliType) throw new Error("cliType required");
|
|
9922
|
-
const found = this.findAdapter(cliType, { instanceKey: args?.
|
|
10002
|
+
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9923
10003
|
if (found) await this.stopSession(found.key);
|
|
9924
10004
|
await this.startSession(cliType, dir);
|
|
9925
10005
|
this.persistRecentDir(cliType, dir);
|
|
@@ -9931,7 +10011,7 @@ ${installInfo}`
|
|
|
9931
10011
|
if (!agentType || !action) throw new Error("agentType and action required");
|
|
9932
10012
|
const found = this.findAdapter(agentType, {
|
|
9933
10013
|
dir: args?.dir,
|
|
9934
|
-
instanceKey: args?.
|
|
10014
|
+
instanceKey: args?.targetSessionId
|
|
9935
10015
|
});
|
|
9936
10016
|
if (!found) throw new Error(`CLI agent not running: ${agentType}`);
|
|
9937
10017
|
const { adapter, key } = found;
|
|
@@ -10077,14 +10157,8 @@ var ProviderStreamAdapter = class {
|
|
|
10077
10157
|
// src/agent-stream/manager.ts
|
|
10078
10158
|
init_logger();
|
|
10079
10159
|
var DaemonAgentStreamManager = class {
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
enabled = true;
|
|
10083
|
-
logFn;
|
|
10084
|
-
lastDiscoveryTime = 0;
|
|
10085
|
-
discoveryIntervalMs = 1e4;
|
|
10086
|
-
_activeAgentType = null;
|
|
10087
|
-
constructor(logFn, providerLoader) {
|
|
10160
|
+
constructor(logFn, providerLoader, sessionRegistry) {
|
|
10161
|
+
this.sessionRegistry = sessionRegistry;
|
|
10088
10162
|
this.logFn = logFn || LOG.forComponent("AgentStream").asLogFn();
|
|
10089
10163
|
if (providerLoader) {
|
|
10090
10164
|
const allExtProviders = providerLoader.getByCategory("extension");
|
|
@@ -10092,224 +10166,278 @@ var DaemonAgentStreamManager = class {
|
|
|
10092
10166
|
const resolved = providerLoader.resolve(p.type);
|
|
10093
10167
|
if (!resolved) continue;
|
|
10094
10168
|
const adapter = new ProviderStreamAdapter(resolved);
|
|
10095
|
-
this.
|
|
10169
|
+
this.adaptersByType.set(p.type, adapter);
|
|
10096
10170
|
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name}) scripts=${Object.keys(resolved.scripts || {}).join(",") || "none"}`);
|
|
10097
10171
|
}
|
|
10098
10172
|
}
|
|
10099
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();
|
|
10100
10181
|
setEnabled(enabled) {
|
|
10101
10182
|
this.enabled = enabled;
|
|
10102
10183
|
}
|
|
10103
10184
|
get isEnabled() {
|
|
10104
10185
|
return this.enabled;
|
|
10105
10186
|
}
|
|
10106
|
-
|
|
10107
|
-
return this.
|
|
10187
|
+
getActiveSessionId(parentSessionId) {
|
|
10188
|
+
return this.activeSessionIdByParent.get(parentSessionId) || null;
|
|
10189
|
+
}
|
|
10190
|
+
getSessionTarget(sessionId) {
|
|
10191
|
+
return this.sessionRegistry?.get(sessionId);
|
|
10192
|
+
}
|
|
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);
|
|
10108
10202
|
}
|
|
10109
10203
|
/** Panel focus based on provider.js focusPanel or extensionId (currently no-op) */
|
|
10110
|
-
async
|
|
10204
|
+
async ensureSessionPanelOpen(_sessionId) {
|
|
10111
10205
|
}
|
|
10112
|
-
async
|
|
10113
|
-
|
|
10114
|
-
if (
|
|
10115
|
-
|
|
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);
|
|
10116
10211
|
if (prev) {
|
|
10117
10212
|
try {
|
|
10118
|
-
await cdp.detachAgent(prev.
|
|
10213
|
+
await cdp.detachAgent(prev.cdpSessionId);
|
|
10119
10214
|
} catch {
|
|
10120
10215
|
}
|
|
10121
|
-
this.
|
|
10122
|
-
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName}`);
|
|
10123
|
-
}
|
|
10124
|
-
}
|
|
10125
|
-
this.
|
|
10126
|
-
this.
|
|
10127
|
-
this.logFn(`[AgentStream] Active
|
|
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;
|
|
10128
10251
|
}
|
|
10129
10252
|
/** Agent webview discovery + session connection */
|
|
10130
|
-
async
|
|
10131
|
-
|
|
10253
|
+
async syncActiveSession(cdp, parentSessionId) {
|
|
10254
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
10255
|
+
if (!this.enabled || !activeSessionId) return;
|
|
10132
10256
|
const now = Date.now();
|
|
10133
|
-
|
|
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) {
|
|
10134
10261
|
return;
|
|
10135
10262
|
}
|
|
10136
|
-
this.
|
|
10263
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, now);
|
|
10137
10264
|
try {
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
if (activeTarget && !this.managed.has(this._activeAgentType)) {
|
|
10141
|
-
const adapter = this.allAdapters.find((a) => a.agentType === this._activeAgentType);
|
|
10142
|
-
if (adapter) {
|
|
10143
|
-
const sessionId = await cdp.attachToAgent(activeTarget);
|
|
10144
|
-
if (sessionId) {
|
|
10145
|
-
this.managed.set(this._activeAgentType, {
|
|
10146
|
-
adapter,
|
|
10147
|
-
sessionId,
|
|
10148
|
-
target: activeTarget,
|
|
10149
|
-
lastState: null,
|
|
10150
|
-
lastError: null,
|
|
10151
|
-
lastHiddenCheckTime: 0
|
|
10152
|
-
});
|
|
10153
|
-
this.logFn(`[AgentStream] Connected: ${adapter.agentName}`);
|
|
10154
|
-
}
|
|
10155
|
-
}
|
|
10265
|
+
if (!managed) {
|
|
10266
|
+
await this.connectManagedSession(cdp, parentSessionId, activeSessionId);
|
|
10156
10267
|
}
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
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();
|
|
10162
10295
|
}
|
|
10163
|
-
|
|
10296
|
+
return state;
|
|
10164
10297
|
} catch (e) {
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
async collectAgentStreams(cdp) {
|
|
10170
|
-
if (!this.enabled) return [];
|
|
10171
|
-
const results = [];
|
|
10172
|
-
if (this._activeAgentType && this.managed.has(this._activeAgentType)) {
|
|
10173
|
-
const agent = this.managed.get(this._activeAgentType);
|
|
10174
|
-
const type = this._activeAgentType;
|
|
10175
|
-
const isHidden = agent.lastState?.status === "panel_hidden";
|
|
10176
|
-
const hiddenCacheFresh = isHidden && Date.now() - agent.lastHiddenCheckTime < 3e4;
|
|
10177
|
-
if (hiddenCacheFresh) {
|
|
10178
|
-
results.push(agent.lastState);
|
|
10179
|
-
} 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")) {
|
|
10180
10302
|
try {
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
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") : ""}`);
|
|
10184
|
-
agent.lastState = state;
|
|
10185
|
-
agent.lastError = null;
|
|
10186
|
-
if (state.status === "panel_hidden") {
|
|
10187
|
-
agent.lastHiddenCheckTime = Date.now();
|
|
10188
|
-
}
|
|
10189
|
-
results.push(state);
|
|
10190
|
-
} catch (e) {
|
|
10191
|
-
const errorMsg = e?.message || String(e);
|
|
10192
|
-
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
10193
|
-
agent.lastError = errorMsg;
|
|
10194
|
-
results.push({
|
|
10195
|
-
agentType: type,
|
|
10196
|
-
agentName: agent.adapter.agentName,
|
|
10197
|
-
extensionId: agent.adapter.extensionId,
|
|
10198
|
-
status: "disconnected",
|
|
10199
|
-
messages: agent.lastState?.messages || [],
|
|
10200
|
-
inputContent: ""
|
|
10201
|
-
});
|
|
10202
|
-
if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
|
|
10203
|
-
try {
|
|
10204
|
-
await cdp.detachAgent(agent.sessionId);
|
|
10205
|
-
} catch {
|
|
10206
|
-
}
|
|
10207
|
-
this.managed.delete(type);
|
|
10208
|
-
this.lastDiscoveryTime = 0;
|
|
10209
|
-
}
|
|
10303
|
+
await cdp.detachAgent(agent.cdpSessionId);
|
|
10304
|
+
} catch {
|
|
10210
10305
|
}
|
|
10306
|
+
this.managedBySessionId.delete(activeSessionId);
|
|
10307
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
10211
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
|
+
};
|
|
10212
10317
|
}
|
|
10213
|
-
return results;
|
|
10214
10318
|
}
|
|
10215
|
-
async
|
|
10216
|
-
await this.
|
|
10217
|
-
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);
|
|
10218
10326
|
if (!agent) return false;
|
|
10219
10327
|
try {
|
|
10220
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10328
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10221
10329
|
await agent.adapter.sendMessage(evaluate, text);
|
|
10222
10330
|
return true;
|
|
10223
10331
|
} catch (e) {
|
|
10224
|
-
this.logFn(`[AgentStream]
|
|
10332
|
+
this.logFn(`[AgentStream] sendToSession(${sessionId}) error: ${e.message}`);
|
|
10225
10333
|
return false;
|
|
10226
10334
|
}
|
|
10227
10335
|
}
|
|
10228
|
-
async
|
|
10229
|
-
await this.
|
|
10230
|
-
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);
|
|
10231
10343
|
if (!agent) return false;
|
|
10232
10344
|
try {
|
|
10233
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10345
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10234
10346
|
return await agent.adapter.resolveAction(evaluate, action);
|
|
10235
10347
|
} catch (e) {
|
|
10236
|
-
this.logFn(`[AgentStream] resolveAction(${
|
|
10348
|
+
this.logFn(`[AgentStream] resolveAction(${sessionId}) error: ${e.message}`);
|
|
10237
10349
|
return false;
|
|
10238
10350
|
}
|
|
10239
10351
|
}
|
|
10240
|
-
async
|
|
10241
|
-
await this.
|
|
10242
|
-
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);
|
|
10243
10359
|
if (!agent) return false;
|
|
10244
10360
|
try {
|
|
10245
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10361
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10246
10362
|
await agent.adapter.newSession(evaluate);
|
|
10247
10363
|
return true;
|
|
10248
10364
|
} catch (e) {
|
|
10249
|
-
this.logFn(`[AgentStream] newSession(${
|
|
10365
|
+
this.logFn(`[AgentStream] newSession(${sessionId}) error: ${e.message}`);
|
|
10250
10366
|
return false;
|
|
10251
10367
|
}
|
|
10252
10368
|
}
|
|
10253
|
-
async
|
|
10254
|
-
|
|
10255
|
-
if (!
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
agent = this.managed.get(agentType);
|
|
10260
|
-
}
|
|
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);
|
|
10261
10375
|
if (!agent || typeof agent.adapter.listChats !== "function") return [];
|
|
10262
10376
|
try {
|
|
10263
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10377
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10264
10378
|
return await agent.adapter.listChats(evaluate);
|
|
10265
10379
|
} catch (e) {
|
|
10266
|
-
this.logFn(`[AgentStream] listChats(${
|
|
10380
|
+
this.logFn(`[AgentStream] listChats(${sessionId}) error: ${e.message}`);
|
|
10267
10381
|
return [];
|
|
10268
10382
|
}
|
|
10269
10383
|
}
|
|
10270
|
-
async
|
|
10271
|
-
|
|
10272
|
-
if (!
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
agent = this.managed.get(agentType);
|
|
10277
|
-
}
|
|
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);
|
|
10278
10390
|
if (!agent || typeof agent.adapter.switchSession !== "function") return false;
|
|
10279
10391
|
try {
|
|
10280
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10281
|
-
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);
|
|
10282
10394
|
} catch (e) {
|
|
10283
|
-
this.logFn(`[AgentStream] switchSession(${
|
|
10395
|
+
this.logFn(`[AgentStream] switchSession(${sessionId}) error: ${e.message}`);
|
|
10284
10396
|
return false;
|
|
10285
10397
|
}
|
|
10286
10398
|
}
|
|
10287
|
-
async
|
|
10288
|
-
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);
|
|
10289
10405
|
if (!agent || typeof agent.adapter.focusEditor !== "function") return false;
|
|
10290
10406
|
try {
|
|
10291
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10407
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10292
10408
|
await agent.adapter.focusEditor(evaluate);
|
|
10293
10409
|
return true;
|
|
10294
10410
|
} catch (e) {
|
|
10295
|
-
this.logFn(`[AgentStream] focusEditor(${
|
|
10411
|
+
this.logFn(`[AgentStream] focusEditor(${sessionId}) error: ${e.message}`);
|
|
10296
10412
|
return false;
|
|
10297
10413
|
}
|
|
10298
10414
|
}
|
|
10299
|
-
|
|
10300
|
-
|
|
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()];
|
|
10301
10420
|
}
|
|
10302
|
-
|
|
10303
|
-
return this.
|
|
10421
|
+
getManagedSession(sessionId) {
|
|
10422
|
+
return this.managedBySessionId.get(sessionId);
|
|
10304
10423
|
}
|
|
10305
|
-
async dispose(
|
|
10306
|
-
for (const
|
|
10424
|
+
async dispose(cdpManagers) {
|
|
10425
|
+
for (const managed of this.managedBySessionId.values()) {
|
|
10426
|
+
const managerKey = this.getSessionTarget(managed.runtimeSessionId)?.cdpManagerKey;
|
|
10427
|
+
const cdp = managerKey ? cdpManagers.get(managerKey) : null;
|
|
10428
|
+
if (!cdp) continue;
|
|
10307
10429
|
try {
|
|
10308
|
-
await cdp.detachAgent(
|
|
10430
|
+
await cdp.detachAgent(managed.cdpSessionId);
|
|
10309
10431
|
} catch {
|
|
10310
10432
|
}
|
|
10311
10433
|
}
|
|
10312
|
-
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);
|
|
10313
10441
|
}
|
|
10314
10442
|
};
|
|
10315
10443
|
|
|
@@ -10317,20 +10445,17 @@ var DaemonAgentStreamManager = class {
|
|
|
10317
10445
|
init_logger();
|
|
10318
10446
|
var AgentStreamPoller = class {
|
|
10319
10447
|
deps;
|
|
10320
|
-
_activeIdeType = null;
|
|
10321
10448
|
timer = null;
|
|
10322
10449
|
constructor(deps) {
|
|
10323
10450
|
this.deps = deps;
|
|
10324
10451
|
}
|
|
10325
10452
|
/** Currently active IDE type for agent streaming */
|
|
10326
10453
|
get activeIde() {
|
|
10327
|
-
return
|
|
10454
|
+
return null;
|
|
10328
10455
|
}
|
|
10329
10456
|
/** Reset active IDE tracking (e.g., when IDE is stopped) */
|
|
10330
|
-
resetActiveIde(
|
|
10331
|
-
|
|
10332
|
-
this._activeIdeType = null;
|
|
10333
|
-
}
|
|
10457
|
+
resetActiveIde(parentSessionId) {
|
|
10458
|
+
this.deps.agentStreamManager.resetParentSession(parentSessionId);
|
|
10334
10459
|
}
|
|
10335
10460
|
/** Start polling (idempotent — ignored if already started) */
|
|
10336
10461
|
start(intervalMs = 5e3) {
|
|
@@ -10352,12 +10477,14 @@ var AgentStreamPoller = class {
|
|
|
10352
10477
|
agentStreamManager,
|
|
10353
10478
|
providerLoader,
|
|
10354
10479
|
instanceManager,
|
|
10355
|
-
cdpManagers
|
|
10480
|
+
cdpManagers,
|
|
10481
|
+
sessionRegistry
|
|
10356
10482
|
} = this.deps;
|
|
10357
10483
|
if (!agentStreamManager || cdpManagers.size === 0) return;
|
|
10358
10484
|
for (const [ideType, cdp] of cdpManagers) {
|
|
10359
10485
|
registerExtensionProviders(providerLoader, cdp, ideType);
|
|
10360
10486
|
const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
|
|
10487
|
+
const parentSessionId = ideInstance?.getInstanceId?.();
|
|
10361
10488
|
if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
|
|
10362
10489
|
const currentExtTypes = new Set(ideInstance.getExtensionTypes());
|
|
10363
10490
|
const enabledExtTypes = new Set(
|
|
@@ -10365,6 +10492,10 @@ var AgentStreamPoller = class {
|
|
|
10365
10492
|
);
|
|
10366
10493
|
for (const extType of currentExtTypes) {
|
|
10367
10494
|
if (!enabledExtTypes.has(extType)) {
|
|
10495
|
+
const extInstance = ideInstance.getExtension?.(extType);
|
|
10496
|
+
if (extInstance?.getInstanceId) {
|
|
10497
|
+
sessionRegistry.unregister(extInstance.getInstanceId());
|
|
10498
|
+
}
|
|
10368
10499
|
ideInstance.removeExtension(extType);
|
|
10369
10500
|
LOG.info("AgentStream", `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
10370
10501
|
}
|
|
@@ -10375,54 +10506,63 @@ var AgentStreamPoller = class {
|
|
|
10375
10506
|
if (extProvider) {
|
|
10376
10507
|
const extSettings = providerLoader.getSettings(extType);
|
|
10377
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
|
+
}
|
|
10378
10521
|
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
10379
10522
|
}
|
|
10380
10523
|
}
|
|
10381
10524
|
}
|
|
10382
10525
|
}
|
|
10383
|
-
|
|
10384
|
-
|
|
10385
|
-
const
|
|
10386
|
-
|
|
10387
|
-
)
|
|
10388
|
-
|
|
10389
|
-
|
|
10390
|
-
await agentStreamManager.switchActiveAgent(cdp, null);
|
|
10391
|
-
this._activeIdeType = 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);
|
|
10392
10533
|
this.deps.onStreamsUpdated?.(ideType, []);
|
|
10393
10534
|
}
|
|
10394
10535
|
}
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
|
|
10399
|
-
try {
|
|
10400
|
-
await agentStreamManager.syncAgentSessions(cdp);
|
|
10401
|
-
const streams = await agentStreamManager.collectAgentStreams(cdp);
|
|
10402
|
-
this.deps.onStreamsUpdated?.(this._activeIdeType, streams);
|
|
10403
|
-
} catch {
|
|
10536
|
+
if (!cdp.isConnected) {
|
|
10537
|
+
if (parentSessionId && activeSessionId) {
|
|
10538
|
+
agentStreamManager.resetParentSession(parentSessionId);
|
|
10539
|
+
this.deps.onStreamsUpdated?.(ideType, []);
|
|
10404
10540
|
}
|
|
10405
|
-
|
|
10541
|
+
continue;
|
|
10406
10542
|
}
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
if (!agentStreamManager.activeAgentType) {
|
|
10410
|
-
for (const [ideType, cdp] of cdpManagers) {
|
|
10411
|
-
if (!cdp.isConnected) continue;
|
|
10543
|
+
let resolvedActiveSessionId = activeSessionId;
|
|
10544
|
+
if (!resolvedActiveSessionId && parentSessionId) {
|
|
10412
10545
|
try {
|
|
10413
10546
|
const discovered = await cdp.discoverAgentWebviews();
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
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
|
+
}
|
|
10422
10555
|
}
|
|
10423
10556
|
} catch {
|
|
10424
10557
|
}
|
|
10425
10558
|
}
|
|
10559
|
+
if (!resolvedActiveSessionId || !parentSessionId) continue;
|
|
10560
|
+
try {
|
|
10561
|
+
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
10562
|
+
const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
10563
|
+
this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
|
|
10564
|
+
} catch {
|
|
10565
|
+
}
|
|
10426
10566
|
}
|
|
10427
10567
|
}
|
|
10428
10568
|
};
|
|
@@ -10509,6 +10649,7 @@ var ProviderInstanceManager = class {
|
|
|
10509
10649
|
...event,
|
|
10510
10650
|
providerType: instance.type,
|
|
10511
10651
|
instanceId: state.instanceId,
|
|
10652
|
+
targetSessionId: state.instanceId,
|
|
10512
10653
|
providerCategory: state.category
|
|
10513
10654
|
});
|
|
10514
10655
|
}
|
|
@@ -14319,6 +14460,63 @@ function launchIDE(ide, workspacePath) {
|
|
|
14319
14460
|
}
|
|
14320
14461
|
}
|
|
14321
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
|
+
|
|
14322
14520
|
// src/boot/daemon-lifecycle.ts
|
|
14323
14521
|
init_logger();
|
|
14324
14522
|
init_config();
|
|
@@ -14358,11 +14556,14 @@ async function initDaemonComponents(config) {
|
|
|
14358
14556
|
});
|
|
14359
14557
|
const instanceManager = new ProviderInstanceManager();
|
|
14360
14558
|
const cdpManagers = /* @__PURE__ */ new Map();
|
|
14361
|
-
const
|
|
14559
|
+
const sessionRegistry = new SessionRegistry();
|
|
14362
14560
|
const detectedIdesRef = { value: [] };
|
|
14561
|
+
let agentStreamManager = null;
|
|
14562
|
+
let poller = null;
|
|
14363
14563
|
const cliManager = new DaemonCliManager({
|
|
14364
14564
|
...config.cliManagerDeps,
|
|
14365
|
-
getInstanceManager: () => instanceManager
|
|
14565
|
+
getInstanceManager: () => instanceManager,
|
|
14566
|
+
getSessionRegistry: () => sessionRegistry
|
|
14366
14567
|
}, providerLoader);
|
|
14367
14568
|
LOG.info("Init", "Detecting IDEs...");
|
|
14368
14569
|
detectedIdesRef.value = await detectIDEs();
|
|
@@ -14372,7 +14573,7 @@ async function initDaemonComponents(config) {
|
|
|
14372
14573
|
providerLoader,
|
|
14373
14574
|
instanceManager,
|
|
14374
14575
|
cdpManagers,
|
|
14375
|
-
|
|
14576
|
+
sessionRegistry
|
|
14376
14577
|
};
|
|
14377
14578
|
const cdpInitializer = new DaemonCdpInitializer({
|
|
14378
14579
|
providerLoader,
|
|
@@ -14381,6 +14582,19 @@ async function initDaemonComponents(config) {
|
|
|
14381
14582
|
onConnected: async (ideType, manager, managerKey) => {
|
|
14382
14583
|
await setupIdeInstance(cdpSetupContext, { ideType, manager, managerKey });
|
|
14383
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?.();
|
|
14384
14598
|
}
|
|
14385
14599
|
});
|
|
14386
14600
|
await cdpInitializer.connectAll(detectedIdesRef.value);
|
|
@@ -14392,14 +14606,14 @@ async function initDaemonComponents(config) {
|
|
|
14392
14606
|
adapters: cliManager.adapters,
|
|
14393
14607
|
providerLoader,
|
|
14394
14608
|
instanceManager,
|
|
14395
|
-
|
|
14609
|
+
sessionRegistry
|
|
14396
14610
|
});
|
|
14397
|
-
|
|
14611
|
+
agentStreamManager = new DaemonAgentStreamManager(
|
|
14398
14612
|
LOG.forComponent("AgentStream").asLogFn(),
|
|
14399
|
-
providerLoader
|
|
14613
|
+
providerLoader,
|
|
14614
|
+
sessionRegistry
|
|
14400
14615
|
);
|
|
14401
14616
|
commandHandler.setAgentStreamManager(agentStreamManager);
|
|
14402
|
-
let poller;
|
|
14403
14617
|
const router = new DaemonCommandRouter({
|
|
14404
14618
|
commandHandler,
|
|
14405
14619
|
cliManager,
|
|
@@ -14407,7 +14621,7 @@ async function initDaemonComponents(config) {
|
|
|
14407
14621
|
providerLoader,
|
|
14408
14622
|
instanceManager,
|
|
14409
14623
|
detectedIdes: detectedIdesRef,
|
|
14410
|
-
|
|
14624
|
+
sessionRegistry,
|
|
14411
14625
|
onCdpManagerCreated: async (ideType, manager) => {
|
|
14412
14626
|
await setupIdeInstance(cdpSetupContext, { ideType, manager });
|
|
14413
14627
|
await config.onCdpManagerSetup?.(ideType, manager, ideType);
|
|
@@ -14422,6 +14636,7 @@ async function initDaemonComponents(config) {
|
|
|
14422
14636
|
providerLoader,
|
|
14423
14637
|
instanceManager,
|
|
14424
14638
|
cdpManagers,
|
|
14639
|
+
sessionRegistry,
|
|
14425
14640
|
onStreamsUpdated: config.onStreamsUpdated
|
|
14426
14641
|
});
|
|
14427
14642
|
poller.start();
|
|
@@ -14436,7 +14651,7 @@ async function initDaemonComponents(config) {
|
|
|
14436
14651
|
poller,
|
|
14437
14652
|
cdpInitializer,
|
|
14438
14653
|
cdpManagers,
|
|
14439
|
-
|
|
14654
|
+
sessionRegistry,
|
|
14440
14655
|
detectedIdes: detectedIdesRef
|
|
14441
14656
|
};
|
|
14442
14657
|
}
|
|
@@ -14464,9 +14679,8 @@ async function shutdownDaemonComponents(components) {
|
|
|
14464
14679
|
poller.stop();
|
|
14465
14680
|
cdpInitializer.stop();
|
|
14466
14681
|
try {
|
|
14467
|
-
|
|
14468
|
-
|
|
14469
|
-
await agentStreamManager.dispose(anyCdp);
|
|
14682
|
+
if (agentStreamManager) {
|
|
14683
|
+
await agentStreamManager.dispose(cdpManagers);
|
|
14470
14684
|
}
|
|
14471
14685
|
} catch (e) {
|
|
14472
14686
|
LOG.warn("Shutdown", `AgentStream dispose: ${e?.message}`);
|
|
@@ -14511,10 +14725,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
14511
14725
|
ProviderLoader,
|
|
14512
14726
|
VersionArchive,
|
|
14513
14727
|
addCliHistory,
|
|
14514
|
-
|
|
14515
|
-
buildManagedAcps,
|
|
14516
|
-
buildManagedClis,
|
|
14517
|
-
buildManagedIdes,
|
|
14728
|
+
buildSessionEntries,
|
|
14518
14729
|
buildStatusSnapshot,
|
|
14519
14730
|
connectCdpManager,
|
|
14520
14731
|
detectAllVersions,
|
|
@@ -14537,6 +14748,8 @@ async function shutdownDaemonComponents(components) {
|
|
|
14537
14748
|
isCdpConnected,
|
|
14538
14749
|
isExtensionInstalled,
|
|
14539
14750
|
isIdeRunning,
|
|
14751
|
+
isManagedStatusWaiting,
|
|
14752
|
+
isManagedStatusWorking,
|
|
14540
14753
|
isSetupComplete,
|
|
14541
14754
|
killIdeProcess,
|
|
14542
14755
|
launchIDE,
|
|
@@ -14544,6 +14757,8 @@ async function shutdownDaemonComponents(components) {
|
|
|
14544
14757
|
loadConfig,
|
|
14545
14758
|
logCommand,
|
|
14546
14759
|
markSetupComplete,
|
|
14760
|
+
normalizeActiveChatData,
|
|
14761
|
+
normalizeManagedStatus,
|
|
14547
14762
|
probeCdpPort,
|
|
14548
14763
|
readChatHistory,
|
|
14549
14764
|
registerExtensionProviders,
|