@adhdev/daemon-core 0.6.79 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +84 -87
- package/dist/index.d.ts +84 -87
- package/dist/index.js +798 -706
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +797 -702
- package/dist/index.mjs.map +1 -1
- package/dist/{normalize-igHDb198.d.mts → normalize-S2PmiRgB.d.mts} +32 -53
- package/dist/{normalize-igHDb198.d.ts → normalize-S2PmiRgB.d.ts} +32 -53
- package/dist/status/normalize.d.mts +1 -1
- package/dist/status/normalize.d.ts +1 -1
- package/package.json +1 -1
- package/src/agent-stream/manager.ts +203 -180
- package/src/agent-stream/poller.ts +45 -22
- package/src/boot/daemon-lifecycle.ts +28 -9
- package/src/cdp/initializer.ts +47 -0
- package/src/cdp/manager.ts +19 -1
- package/src/cdp/setup.ts +26 -11
- package/src/commands/chat-commands.ts +136 -88
- package/src/commands/cli-manager.ts +31 -6
- package/src/commands/handler.ts +69 -138
- package/src/commands/router.ts +4 -20
- package/src/commands/stream-commands.ts +34 -162
- package/src/daemon-core.ts +3 -9
- package/src/index.ts +6 -5
- package/src/logging/command-log.ts +1 -1
- package/src/providers/acp-provider-instance.ts +4 -0
- package/src/providers/provider-instance-manager.ts +1 -0
- package/src/sessions/registry.ts +76 -0
- package/src/shared-types.ts +45 -54
- package/src/status/builders.ts +156 -120
- package/src/status/reporter.ts +16 -15
- package/src/status/snapshot.ts +3 -11
package/dist/index.mjs
CHANGED
|
@@ -2781,7 +2781,11 @@ var DaemonCdpManager = class {
|
|
|
2781
2781
|
async attachToAgent(target) {
|
|
2782
2782
|
if (!this.isConnected) return null;
|
|
2783
2783
|
for (const [sid, t] of this.agentSessions) {
|
|
2784
|
-
if (t.
|
|
2784
|
+
if (t.targetId === target.targetId) return sid;
|
|
2785
|
+
if (t.agentType === target.agentType && t.targetId !== target.targetId) {
|
|
2786
|
+
await this.detachAgent(sid).catch(() => {
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2785
2789
|
}
|
|
2786
2790
|
try {
|
|
2787
2791
|
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
@@ -2905,6 +2909,20 @@ var DaemonCdpManager = class {
|
|
|
2905
2909
|
}
|
|
2906
2910
|
async getCurrentPageWebviewUrls() {
|
|
2907
2911
|
if (!this.isConnected) return /* @__PURE__ */ new Set();
|
|
2912
|
+
try {
|
|
2913
|
+
const urls = /* @__PURE__ */ new Set();
|
|
2914
|
+
const { frameTree } = await this.sendInternal("Page.getFrameTree", {}, 5e3);
|
|
2915
|
+
const visit = (node) => {
|
|
2916
|
+
const url = node?.frame?.url;
|
|
2917
|
+
if (typeof url === "string" && url.includes("vscode-webview")) {
|
|
2918
|
+
urls.add(url);
|
|
2919
|
+
}
|
|
2920
|
+
for (const child of node?.childFrames || []) visit(child);
|
|
2921
|
+
};
|
|
2922
|
+
if (frameTree) visit(frameTree);
|
|
2923
|
+
if (urls.size > 0) return urls;
|
|
2924
|
+
} catch {
|
|
2925
|
+
}
|
|
2908
2926
|
try {
|
|
2909
2927
|
const raw = await this.evaluate(
|
|
2910
2928
|
`JSON.stringify(Array.from(document.querySelectorAll('iframe,webview'))
|
|
@@ -4056,7 +4074,7 @@ function registerExtensionProviders(providerLoader, manager, ideType) {
|
|
|
4056
4074
|
manager.setExtensionProviders(enabledExtProviders);
|
|
4057
4075
|
}
|
|
4058
4076
|
async function setupIdeInstance(ctx, opts) {
|
|
4059
|
-
const { providerLoader, instanceManager,
|
|
4077
|
+
const { providerLoader, instanceManager, sessionRegistry } = ctx;
|
|
4060
4078
|
const { ideType, manager, settings } = opts;
|
|
4061
4079
|
const managerKey = opts.managerKey || ideType;
|
|
4062
4080
|
registerExtensionProviders(providerLoader, manager, ideType);
|
|
@@ -4072,14 +4090,30 @@ async function setupIdeInstance(ctx, opts) {
|
|
|
4072
4090
|
serverConn: ctx.serverConn,
|
|
4073
4091
|
settings: resolvedSettings
|
|
4074
4092
|
});
|
|
4075
|
-
|
|
4093
|
+
sessionRegistry.register({
|
|
4094
|
+
sessionId: ideInstance.getInstanceId(),
|
|
4095
|
+
parentSessionId: null,
|
|
4096
|
+
providerType: ideType,
|
|
4097
|
+
providerCategory: "ide",
|
|
4098
|
+
transport: "cdp-page",
|
|
4099
|
+
cdpManagerKey: managerKey,
|
|
4100
|
+
instanceKey: `ide:${managerKey}`
|
|
4101
|
+
});
|
|
4076
4102
|
const extensionProviders = providerLoader.getEnabledByCategory("extension", ideType);
|
|
4077
4103
|
for (const extProvider of extensionProviders) {
|
|
4078
4104
|
const extSettings = providerLoader.getSettings(extProvider.type);
|
|
4079
4105
|
await ideInstance.addExtension(extProvider, extSettings);
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4106
|
+
}
|
|
4107
|
+
for (const ext of ideInstance.getExtensionInstances()) {
|
|
4108
|
+
sessionRegistry.register({
|
|
4109
|
+
sessionId: ext.getInstanceId(),
|
|
4110
|
+
parentSessionId: ideInstance.getInstanceId(),
|
|
4111
|
+
providerType: ext.type,
|
|
4112
|
+
providerCategory: "extension",
|
|
4113
|
+
transport: "cdp-webview",
|
|
4114
|
+
cdpManagerKey: managerKey,
|
|
4115
|
+
instanceKey: `ide:${managerKey}`
|
|
4116
|
+
});
|
|
4083
4117
|
}
|
|
4084
4118
|
return ideInstance;
|
|
4085
4119
|
}
|
|
@@ -4296,6 +4330,7 @@ var DaemonCdpInitializer = class {
|
|
|
4296
4330
|
async connectIdePort(port, ide) {
|
|
4297
4331
|
const { providerLoader, cdpManagers } = this.config;
|
|
4298
4332
|
const targets = await DaemonCdpManager.listAllTargets(port);
|
|
4333
|
+
await this.pruneStaleManagers(port, ide, targets);
|
|
4299
4334
|
if (targets.length === 0) {
|
|
4300
4335
|
if (cdpManagers.has(ide)) return;
|
|
4301
4336
|
if (!await probeCdpPort(port)) return;
|
|
@@ -4348,6 +4383,34 @@ var DaemonCdpInitializer = class {
|
|
|
4348
4383
|
}
|
|
4349
4384
|
}
|
|
4350
4385
|
}
|
|
4386
|
+
async pruneStaleManagers(port, ide, targets) {
|
|
4387
|
+
const trackedTargetIds = new Set(targets.map((target) => target.id));
|
|
4388
|
+
const removals = [];
|
|
4389
|
+
for (const [key, manager] of this.config.cdpManagers.entries()) {
|
|
4390
|
+
if (!(key === ide || key.startsWith(`${ide}_`))) continue;
|
|
4391
|
+
if (manager.getPort() !== port) continue;
|
|
4392
|
+
if (targets.length === 0) {
|
|
4393
|
+
removals.push({ key, manager, reason: "ide_closed" });
|
|
4394
|
+
continue;
|
|
4395
|
+
}
|
|
4396
|
+
if (manager.targetId && !trackedTargetIds.has(manager.targetId)) {
|
|
4397
|
+
removals.push({ key, manager, reason: "target_closed" });
|
|
4398
|
+
continue;
|
|
4399
|
+
}
|
|
4400
|
+
if (key === ide && !manager.targetId && targets.length > 1) {
|
|
4401
|
+
removals.push({ key, manager, reason: "target_rekeyed" });
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
for (const { key, manager, reason } of removals) {
|
|
4405
|
+
try {
|
|
4406
|
+
manager.disconnect();
|
|
4407
|
+
} catch {
|
|
4408
|
+
}
|
|
4409
|
+
this.config.cdpManagers.delete(key);
|
|
4410
|
+
LOG.info("CDP", `Removed stale manager: ${key} (${reason})`);
|
|
4411
|
+
await this.config.onDisconnected?.(ide, manager, key, reason);
|
|
4412
|
+
}
|
|
4413
|
+
}
|
|
4351
4414
|
// ─── Periodic scanning ───
|
|
4352
4415
|
/**
|
|
4353
4416
|
* Start periodic scanning for newly opened IDEs.
|
|
@@ -4451,95 +4514,152 @@ function isCdpConnected(cdpManagers, key) {
|
|
|
4451
4514
|
const m = findCdpManager(cdpManagers, key);
|
|
4452
4515
|
return m?.isConnected ?? false;
|
|
4453
4516
|
}
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
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
|
-
|
|
4517
|
+
var IDE_SESSION_CAPABILITIES = [
|
|
4518
|
+
"read_chat",
|
|
4519
|
+
"send_message",
|
|
4520
|
+
"new_session",
|
|
4521
|
+
"list_sessions",
|
|
4522
|
+
"switch_session",
|
|
4523
|
+
"resolve_action",
|
|
4524
|
+
"change_model",
|
|
4525
|
+
"set_mode",
|
|
4526
|
+
"set_thought_level"
|
|
4527
|
+
];
|
|
4528
|
+
var EXTENSION_SESSION_CAPABILITIES = [
|
|
4529
|
+
"read_chat",
|
|
4530
|
+
"send_message",
|
|
4531
|
+
"new_session",
|
|
4532
|
+
"list_sessions",
|
|
4533
|
+
"switch_session",
|
|
4534
|
+
"resolve_action",
|
|
4535
|
+
"change_model",
|
|
4536
|
+
"set_mode"
|
|
4537
|
+
];
|
|
4538
|
+
var PTY_SESSION_CAPABILITIES = [
|
|
4539
|
+
"read_chat",
|
|
4540
|
+
"send_message",
|
|
4541
|
+
"resolve_action",
|
|
4542
|
+
"terminal_io",
|
|
4543
|
+
"resize_terminal"
|
|
4544
|
+
];
|
|
4545
|
+
var ACP_SESSION_CAPABILITIES = [
|
|
4546
|
+
"read_chat",
|
|
4547
|
+
"send_message",
|
|
4548
|
+
"new_session",
|
|
4549
|
+
"resolve_action",
|
|
4550
|
+
"change_model",
|
|
4551
|
+
"set_mode",
|
|
4552
|
+
"set_thought_level"
|
|
4553
|
+
];
|
|
4554
|
+
function buildIdeWorkspaceSession(state, cdpManagers) {
|
|
4555
|
+
const activeChat = normalizeActiveChatData(state.activeChat);
|
|
4556
|
+
const title = activeChat?.title || state.name;
|
|
4557
|
+
return {
|
|
4558
|
+
id: state.instanceId || state.type,
|
|
4559
|
+
parentId: null,
|
|
4560
|
+
providerType: state.type,
|
|
4561
|
+
providerName: state.name,
|
|
4562
|
+
kind: "workspace",
|
|
4563
|
+
transport: "cdp-page",
|
|
4564
|
+
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
4565
|
+
activeModal: activeChat?.activeModal || null
|
|
4566
|
+
}),
|
|
4567
|
+
title,
|
|
4568
|
+
workspace: state.workspace || null,
|
|
4569
|
+
activeChat,
|
|
4570
|
+
capabilities: IDE_SESSION_CAPABILITIES,
|
|
4571
|
+
cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
|
|
4572
|
+
currentModel: state.currentModel,
|
|
4573
|
+
currentPlan: state.currentPlan,
|
|
4574
|
+
currentAutoApprove: state.currentAutoApprove,
|
|
4575
|
+
errorMessage: state.errorMessage,
|
|
4576
|
+
errorReason: state.errorReason
|
|
4577
|
+
};
|
|
4504
4578
|
}
|
|
4505
|
-
function
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4579
|
+
function buildExtensionAgentSession(parent, ext) {
|
|
4580
|
+
const activeChat = normalizeActiveChatData(ext.activeChat);
|
|
4581
|
+
return {
|
|
4582
|
+
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
4583
|
+
parentId: parent.instanceId || parent.type,
|
|
4584
|
+
providerType: ext.type,
|
|
4585
|
+
providerName: ext.name,
|
|
4586
|
+
kind: "agent",
|
|
4587
|
+
transport: "cdp-webview",
|
|
4588
|
+
status: normalizeManagedStatus(activeChat?.status || ext.status, {
|
|
4589
|
+
activeModal: activeChat?.activeModal || null
|
|
4590
|
+
}),
|
|
4591
|
+
title: activeChat?.title || ext.name,
|
|
4592
|
+
workspace: parent.workspace || null,
|
|
4593
|
+
activeChat,
|
|
4594
|
+
capabilities: EXTENSION_SESSION_CAPABILITIES,
|
|
4595
|
+
currentModel: ext.currentModel,
|
|
4596
|
+
currentPlan: ext.currentPlan,
|
|
4597
|
+
errorMessage: ext.errorMessage,
|
|
4598
|
+
errorReason: ext.errorReason
|
|
4599
|
+
};
|
|
4516
4600
|
}
|
|
4517
|
-
function
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4601
|
+
function buildCliSession(state) {
|
|
4602
|
+
const activeChat = normalizeActiveChatData(state.activeChat);
|
|
4603
|
+
return {
|
|
4604
|
+
id: state.instanceId,
|
|
4605
|
+
parentId: null,
|
|
4606
|
+
providerType: state.type,
|
|
4607
|
+
providerName: state.name,
|
|
4608
|
+
kind: "agent",
|
|
4609
|
+
transport: "pty",
|
|
4610
|
+
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
4611
|
+
activeModal: activeChat?.activeModal || null
|
|
4612
|
+
}),
|
|
4613
|
+
title: activeChat?.title || state.name,
|
|
4614
|
+
workspace: state.workspace || null,
|
|
4615
|
+
activeChat,
|
|
4616
|
+
capabilities: PTY_SESSION_CAPABILITIES,
|
|
4617
|
+
errorMessage: state.errorMessage,
|
|
4618
|
+
errorReason: state.errorReason
|
|
4619
|
+
};
|
|
4533
4620
|
}
|
|
4534
|
-
function
|
|
4621
|
+
function buildAcpSession(state) {
|
|
4622
|
+
const activeChat = normalizeActiveChatData(state.activeChat);
|
|
4623
|
+
return {
|
|
4624
|
+
id: state.instanceId,
|
|
4625
|
+
parentId: null,
|
|
4626
|
+
providerType: state.type,
|
|
4627
|
+
providerName: state.name,
|
|
4628
|
+
kind: "agent",
|
|
4629
|
+
transport: "acp",
|
|
4630
|
+
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
4631
|
+
activeModal: activeChat?.activeModal || null
|
|
4632
|
+
}),
|
|
4633
|
+
title: activeChat?.title || state.name,
|
|
4634
|
+
workspace: state.workspace || null,
|
|
4635
|
+
activeChat,
|
|
4636
|
+
capabilities: ACP_SESSION_CAPABILITIES,
|
|
4637
|
+
currentModel: state.currentModel,
|
|
4638
|
+
currentPlan: state.currentPlan,
|
|
4639
|
+
acpConfigOptions: state.acpConfigOptions,
|
|
4640
|
+
acpModes: state.acpModes,
|
|
4641
|
+
errorMessage: state.errorMessage,
|
|
4642
|
+
errorReason: state.errorReason
|
|
4643
|
+
};
|
|
4644
|
+
}
|
|
4645
|
+
function buildSessionEntries(allStates, cdpManagers) {
|
|
4646
|
+
const sessions = [];
|
|
4535
4647
|
const ideStates = allStates.filter((s) => s.category === "ide");
|
|
4536
4648
|
const cliStates = allStates.filter((s) => s.category === "cli");
|
|
4537
4649
|
const acpStates = allStates.filter((s) => s.category === "acp");
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4650
|
+
for (const state of ideStates) {
|
|
4651
|
+
sessions.push(buildIdeWorkspaceSession(state, cdpManagers));
|
|
4652
|
+
for (const ext of state.extensions) {
|
|
4653
|
+
sessions.push(buildExtensionAgentSession(state, ext));
|
|
4654
|
+
}
|
|
4655
|
+
}
|
|
4656
|
+
for (const state of cliStates) {
|
|
4657
|
+
sessions.push(buildCliSession(state));
|
|
4658
|
+
}
|
|
4659
|
+
for (const state of acpStates) {
|
|
4660
|
+
sessions.push(buildAcpSession(state));
|
|
4661
|
+
}
|
|
4662
|
+
return sessions;
|
|
4543
4663
|
}
|
|
4544
4664
|
|
|
4545
4665
|
// src/commands/handler.ts
|
|
@@ -4548,14 +4668,37 @@ init_logger();
|
|
|
4548
4668
|
|
|
4549
4669
|
// src/commands/chat-commands.ts
|
|
4550
4670
|
init_logger();
|
|
4671
|
+
var RECENT_SEND_WINDOW_MS = 1200;
|
|
4672
|
+
var recentSendByTarget = /* @__PURE__ */ new Map();
|
|
4673
|
+
function getCurrentProviderType(h, fallback = "") {
|
|
4674
|
+
return h.currentSession?.providerType || h.currentProviderType || fallback;
|
|
4675
|
+
}
|
|
4676
|
+
function getCurrentManagerKey(h) {
|
|
4677
|
+
return h.currentSession?.cdpManagerKey || h.currentManagerKey || "";
|
|
4678
|
+
}
|
|
4551
4679
|
function getTargetedCliAdapter(h, args, providerType) {
|
|
4552
|
-
return h.getCliAdapter(args?.
|
|
4680
|
+
return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
|
|
4681
|
+
}
|
|
4682
|
+
function buildRecentSendKey(h, args, provider, text) {
|
|
4683
|
+
const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
|
|
4684
|
+
return `${provider?.category || "unknown"}:${target}:${text.trim()}`;
|
|
4685
|
+
}
|
|
4686
|
+
function isRecentDuplicateSend(key) {
|
|
4687
|
+
const now = Date.now();
|
|
4688
|
+
for (const [candidate, ts2] of recentSendByTarget.entries()) {
|
|
4689
|
+
if (now - ts2 > RECENT_SEND_WINDOW_MS) recentSendByTarget.delete(candidate);
|
|
4690
|
+
}
|
|
4691
|
+
const previous = recentSendByTarget.get(key);
|
|
4692
|
+
if (previous && now - previous <= RECENT_SEND_WINDOW_MS) return true;
|
|
4693
|
+
recentSendByTarget.set(key, now);
|
|
4694
|
+
return false;
|
|
4553
4695
|
}
|
|
4554
4696
|
async function handleChatHistory(h, args) {
|
|
4555
|
-
const { agentType, offset, limit
|
|
4697
|
+
const { agentType, offset, limit } = args;
|
|
4698
|
+
const instanceId = args?.targetSessionId;
|
|
4556
4699
|
try {
|
|
4557
4700
|
const provider = h.getProvider(agentType);
|
|
4558
|
-
const agentStr = provider?.type || agentType || h
|
|
4701
|
+
const agentStr = provider?.type || agentType || getCurrentProviderType(h);
|
|
4559
4702
|
const result = readChatHistory(agentStr, offset || 0, limit || 30, instanceId);
|
|
4560
4703
|
return { success: true, ...result, agent: agentStr };
|
|
4561
4704
|
} catch (e) {
|
|
@@ -4599,7 +4742,7 @@ async function handleReadChat(h, args) {
|
|
|
4599
4742
|
provider.type || "unknown_extension",
|
|
4600
4743
|
parsed.messages || [],
|
|
4601
4744
|
parsed.title,
|
|
4602
|
-
args?.
|
|
4745
|
+
args?.targetSessionId
|
|
4603
4746
|
);
|
|
4604
4747
|
return { success: true, ...parsed };
|
|
4605
4748
|
}
|
|
@@ -4609,15 +4752,18 @@ async function handleReadChat(h, args) {
|
|
|
4609
4752
|
}
|
|
4610
4753
|
if (h.agentStream) {
|
|
4611
4754
|
const cdp2 = h.getCdp();
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
const stream =
|
|
4755
|
+
const parentSessionId = h.currentSession?.parentSessionId;
|
|
4756
|
+
if (cdp2 && parentSessionId) {
|
|
4757
|
+
const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
|
|
4758
|
+
if (stream?.agentType !== provider.type) {
|
|
4759
|
+
return { success: true, messages: [], status: "idle" };
|
|
4760
|
+
}
|
|
4615
4761
|
if (stream) {
|
|
4616
4762
|
h.historyWriter.appendNewMessages(
|
|
4617
4763
|
stream.agentType,
|
|
4618
4764
|
stream.messages || [],
|
|
4619
4765
|
void 0,
|
|
4620
|
-
args?.
|
|
4766
|
+
args?.targetSessionId
|
|
4621
4767
|
);
|
|
4622
4768
|
return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
|
|
4623
4769
|
}
|
|
@@ -4644,10 +4790,10 @@ async function handleReadChat(h, args) {
|
|
|
4644
4790
|
if (parsed && typeof parsed === "object") {
|
|
4645
4791
|
_log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
|
|
4646
4792
|
h.historyWriter.appendNewMessages(
|
|
4647
|
-
provider?.type || h
|
|
4793
|
+
provider?.type || getCurrentProviderType(h, "unknown_webview"),
|
|
4648
4794
|
parsed.messages || [],
|
|
4649
4795
|
parsed.title,
|
|
4650
|
-
args?.
|
|
4796
|
+
args?.targetSessionId
|
|
4651
4797
|
);
|
|
4652
4798
|
return { success: true, ...parsed };
|
|
4653
4799
|
}
|
|
@@ -4671,10 +4817,10 @@ async function handleReadChat(h, args) {
|
|
|
4671
4817
|
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
4672
4818
|
_log(`OK: ${parsed.messages?.length} msgs`);
|
|
4673
4819
|
h.historyWriter.appendNewMessages(
|
|
4674
|
-
provider?.type || h
|
|
4820
|
+
provider?.type || getCurrentProviderType(h, "unknown_ide"),
|
|
4675
4821
|
parsed.messages || [],
|
|
4676
4822
|
parsed.title,
|
|
4677
|
-
args?.
|
|
4823
|
+
args?.targetSessionId
|
|
4678
4824
|
);
|
|
4679
4825
|
return { success: true, ...parsed };
|
|
4680
4826
|
}
|
|
@@ -4689,16 +4835,21 @@ async function handleSendChat(h, args) {
|
|
|
4689
4835
|
if (!text) return { success: false, error: "text required" };
|
|
4690
4836
|
const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
|
|
4691
4837
|
const provider = h.getProvider(args?.agentType);
|
|
4838
|
+
const dedupeKey = buildRecentSendKey(h, args, provider, text);
|
|
4692
4839
|
const _logSendSuccess = (method, targetAgent) => {
|
|
4693
4840
|
h.historyWriter.appendNewMessages(
|
|
4694
|
-
targetAgent || provider?.type || h
|
|
4841
|
+
targetAgent || provider?.type || getCurrentProviderType(h, "unknown_agent"),
|
|
4695
4842
|
[{ role: "user", content: text, receivedAt: Date.now() }],
|
|
4696
4843
|
void 0,
|
|
4697
4844
|
// title
|
|
4698
|
-
args?.
|
|
4845
|
+
args?.targetSessionId
|
|
4699
4846
|
);
|
|
4700
4847
|
return { success: true, sent: true, method, targetAgent };
|
|
4701
4848
|
};
|
|
4849
|
+
if (isRecentDuplicateSend(dedupeKey)) {
|
|
4850
|
+
_log(`Suppressed duplicate send for ${dedupeKey}`);
|
|
4851
|
+
return { success: true, sent: false, deduplicated: true };
|
|
4852
|
+
}
|
|
4702
4853
|
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
4703
4854
|
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
4704
4855
|
if (adapter) {
|
|
@@ -4734,8 +4885,9 @@ async function handleSendChat(h, args) {
|
|
|
4734
4885
|
} catch (e) {
|
|
4735
4886
|
_log(`Extension script error: ${e.message}`);
|
|
4736
4887
|
}
|
|
4737
|
-
|
|
4738
|
-
|
|
4888
|
+
const extensionSessionId = h.currentSession?.sessionId;
|
|
4889
|
+
if (h.agentStream && h.getCdp() && extensionSessionId) {
|
|
4890
|
+
const ok = await h.agentStream.sendToSession(h.getCdp(), extensionSessionId, text);
|
|
4739
4891
|
if (ok) {
|
|
4740
4892
|
_log(`AgentStreamManager sent OK`);
|
|
4741
4893
|
return _logSendSuccess("agent-stream");
|
|
@@ -4745,45 +4897,11 @@ async function handleSendChat(h, args) {
|
|
|
4745
4897
|
}
|
|
4746
4898
|
const targetCdp = h.getCdp();
|
|
4747
4899
|
if (!targetCdp?.isConnected) {
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
_log(`Targeting IDE: ${h.currentIdeType}`);
|
|
4752
|
-
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
4753
|
-
try {
|
|
4754
|
-
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4755
|
-
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
4756
|
-
const matchText = provider.webviewMatchText;
|
|
4757
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4758
|
-
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
4759
|
-
let wvParsed = wvResult;
|
|
4760
|
-
if (typeof wvResult === "string") {
|
|
4761
|
-
try {
|
|
4762
|
-
wvParsed = JSON.parse(wvResult);
|
|
4763
|
-
} catch {
|
|
4764
|
-
}
|
|
4765
|
-
}
|
|
4766
|
-
if (wvParsed?.sent) {
|
|
4767
|
-
_log(`webviewSendMessage (priority) OK`);
|
|
4768
|
-
return _logSendSuccess("webview-script-priority");
|
|
4769
|
-
}
|
|
4770
|
-
_log(`webviewSendMessage (priority) did not confirm sent, falling through`);
|
|
4771
|
-
}
|
|
4772
|
-
} catch (e) {
|
|
4773
|
-
_log(`webviewSendMessage (priority) failed: ${e.message}, falling through`);
|
|
4774
|
-
}
|
|
4775
|
-
}
|
|
4776
|
-
if (provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
4777
|
-
try {
|
|
4778
|
-
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
4779
|
-
if (sent) {
|
|
4780
|
-
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
4781
|
-
return _logSendSuccess("typeAndSend-provider");
|
|
4782
|
-
}
|
|
4783
|
-
} catch (e) {
|
|
4784
|
-
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
4785
|
-
}
|
|
4900
|
+
const managerKey = getCurrentManagerKey(h);
|
|
4901
|
+
_log(`No CDP for ${managerKey}`);
|
|
4902
|
+
return { success: false, error: `CDP for ${managerKey || "unknown"} not connected` };
|
|
4786
4903
|
}
|
|
4904
|
+
_log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
|
|
4787
4905
|
const sendScript = h.getProviderScript("sendMessage", { MESSAGE: text });
|
|
4788
4906
|
if (sendScript) {
|
|
4789
4907
|
try {
|
|
@@ -4810,7 +4928,30 @@ async function handleSendChat(h, args) {
|
|
|
4810
4928
|
_log(`typeAndSend(script.selector) failed: ${e.message}`);
|
|
4811
4929
|
}
|
|
4812
4930
|
}
|
|
4813
|
-
if (parsed?.needsTypeAndSend &&
|
|
4931
|
+
if (parsed?.needsTypeAndSend && parsed?.clickCoords) {
|
|
4932
|
+
try {
|
|
4933
|
+
const { x, y } = parsed.clickCoords;
|
|
4934
|
+
const sent = await targetCdp.typeAndSendAt(x, y, text);
|
|
4935
|
+
if (sent) {
|
|
4936
|
+
_log(`typeAndSendAt(${x},${y}) success`);
|
|
4937
|
+
return _logSendSuccess("typeAndSendAt-script");
|
|
4938
|
+
}
|
|
4939
|
+
} catch (e) {
|
|
4940
|
+
_log(`typeAndSendAt failed: ${e.message}`);
|
|
4941
|
+
}
|
|
4942
|
+
}
|
|
4943
|
+
if (parsed?.needsTypeAndSend && provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
4944
|
+
try {
|
|
4945
|
+
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
4946
|
+
if (sent) {
|
|
4947
|
+
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
4948
|
+
return _logSendSuccess("typeAndSend-provider");
|
|
4949
|
+
}
|
|
4950
|
+
} catch (e) {
|
|
4951
|
+
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
if (parsed?.needsTypeAndSend && provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
4814
4955
|
try {
|
|
4815
4956
|
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4816
4957
|
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
@@ -4833,20 +4974,44 @@ async function handleSendChat(h, args) {
|
|
|
4833
4974
|
_log(`webviewSendMessage failed: ${e.message}`);
|
|
4834
4975
|
}
|
|
4835
4976
|
}
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4977
|
+
return { success: false, error: parsed?.error || "Provider sendMessage did not confirm send" };
|
|
4978
|
+
} catch (e) {
|
|
4979
|
+
_log(`sendMessage script failed: ${e.message}`);
|
|
4980
|
+
return { success: false, error: `Provider sendMessage failed: ${e.message}` };
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
4984
|
+
try {
|
|
4985
|
+
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
4986
|
+
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
4987
|
+
const matchText = provider.webviewMatchText;
|
|
4988
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4989
|
+
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
4990
|
+
let wvParsed = wvResult;
|
|
4991
|
+
if (typeof wvResult === "string") {
|
|
4992
|
+
try {
|
|
4993
|
+
wvParsed = JSON.parse(wvResult);
|
|
4994
|
+
} catch {
|
|
4843
4995
|
}
|
|
4844
|
-
}
|
|
4845
|
-
|
|
4996
|
+
}
|
|
4997
|
+
if (wvParsed?.sent) {
|
|
4998
|
+
_log(`webviewSendMessage OK`);
|
|
4999
|
+
return _logSendSuccess("webview-script");
|
|
4846
5000
|
}
|
|
4847
5001
|
}
|
|
4848
5002
|
} catch (e) {
|
|
4849
|
-
_log(`
|
|
5003
|
+
_log(`webviewSendMessage failed: ${e.message}`);
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
if (provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
5007
|
+
try {
|
|
5008
|
+
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
5009
|
+
if (sent) {
|
|
5010
|
+
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
5011
|
+
return _logSendSuccess("typeAndSend-provider");
|
|
5012
|
+
}
|
|
5013
|
+
} catch (e) {
|
|
5014
|
+
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
4850
5015
|
}
|
|
4851
5016
|
}
|
|
4852
5017
|
_log("All methods failed");
|
|
@@ -4854,9 +5019,9 @@ async function handleSendChat(h, args) {
|
|
|
4854
5019
|
}
|
|
4855
5020
|
async function handleListChats(h, args) {
|
|
4856
5021
|
const provider = h.getProvider(args?.agentType);
|
|
4857
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
5022
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
4858
5023
|
try {
|
|
4859
|
-
const chats = await h.agentStream.
|
|
5024
|
+
const chats = await h.agentStream.listSessionChats(h.getCdp(), h.currentSession.sessionId);
|
|
4860
5025
|
LOG.info("Command", `[list_chats] Extension: ${chats.length} chats`);
|
|
4861
5026
|
return { success: true, chats };
|
|
4862
5027
|
} catch (e) {
|
|
@@ -4915,8 +5080,8 @@ async function handleNewChat(h, args) {
|
|
|
4915
5080
|
}
|
|
4916
5081
|
return { success: false, error: "new_chat not supported by this CLI provider" };
|
|
4917
5082
|
}
|
|
4918
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
4919
|
-
const ok = await h.agentStream.
|
|
5083
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
5084
|
+
const ok = await h.agentStream.newSession(h.getCdp(), h.currentSession.sessionId);
|
|
4920
5085
|
return { success: ok };
|
|
4921
5086
|
}
|
|
4922
5087
|
try {
|
|
@@ -4940,15 +5105,15 @@ async function handleNewChat(h, args) {
|
|
|
4940
5105
|
}
|
|
4941
5106
|
async function handleSwitchChat(h, args) {
|
|
4942
5107
|
const provider = h.getProvider(args?.agentType);
|
|
4943
|
-
const
|
|
5108
|
+
const managerKey = getCurrentManagerKey(h);
|
|
4944
5109
|
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
4945
5110
|
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
4946
|
-
LOG.info("Command", `[switch_chat] sessionId=${sessionId},
|
|
4947
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
4948
|
-
const ok = await h.agentStream.
|
|
5111
|
+
LOG.info("Command", `[switch_chat] sessionId=${sessionId}, manager=${managerKey}`);
|
|
5112
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
5113
|
+
const ok = await h.agentStream.switchConversation(h.getCdp(), h.currentSession.sessionId, sessionId);
|
|
4949
5114
|
return { success: ok, result: ok ? "switched" : "failed" };
|
|
4950
5115
|
}
|
|
4951
|
-
const cdp = h.getCdp(
|
|
5116
|
+
const cdp = h.getCdp(managerKey);
|
|
4952
5117
|
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
4953
5118
|
try {
|
|
4954
5119
|
const webviewScript = h.getProviderScript("webviewSwitchSession", { SESSION_ID: JSON.stringify(sessionId) });
|
|
@@ -5090,7 +5255,7 @@ async function handleSetMode(h, args) {
|
|
|
5090
5255
|
async function handleChangeModel(h, args) {
|
|
5091
5256
|
const provider = h.getProvider(args?.agentType);
|
|
5092
5257
|
const model = args?.model;
|
|
5093
|
-
LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category}
|
|
5258
|
+
LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
|
|
5094
5259
|
if (provider?.category === "acp") {
|
|
5095
5260
|
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
5096
5261
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
@@ -5211,14 +5376,8 @@ async function handleResolveAction(h, args) {
|
|
|
5211
5376
|
LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
5212
5377
|
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
5213
5378
|
}
|
|
5214
|
-
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.
|
|
5215
|
-
const ok = await h.agentStream.
|
|
5216
|
-
h.getCdp(),
|
|
5217
|
-
h.currentIdeType,
|
|
5218
|
-
provider.type,
|
|
5219
|
-
action,
|
|
5220
|
-
h.currentIdeType
|
|
5221
|
-
);
|
|
5379
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
5380
|
+
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
|
|
5222
5381
|
return { success: ok };
|
|
5223
5382
|
}
|
|
5224
5383
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
@@ -5578,157 +5737,37 @@ async function handleFileListBrowse(h, args) {
|
|
|
5578
5737
|
// src/commands/stream-commands.ts
|
|
5579
5738
|
init_config();
|
|
5580
5739
|
init_logger();
|
|
5581
|
-
async function
|
|
5582
|
-
if (!h.agentStream || !h.getCdp() || !h.currentIdeType) return { success: false, error: "AgentStream or CDP not available" };
|
|
5583
|
-
const agentType = args?.agentType || args?.agent || null;
|
|
5584
|
-
await h.agentStream.switchActiveAgent(h.getCdp(), h.currentIdeType, agentType);
|
|
5585
|
-
return { success: true, activeAgent: agentType };
|
|
5586
|
-
}
|
|
5587
|
-
async function handleAgentStreamRead(h, args) {
|
|
5588
|
-
if (!h.agentStream || !h.getCdp() || !h.currentIdeType) return { success: false, error: "AgentStream or CDP not available" };
|
|
5589
|
-
const streams = await h.agentStream.collectAgentStreams(h.getCdp(), h.currentIdeType);
|
|
5590
|
-
return { success: true, streams };
|
|
5591
|
-
}
|
|
5592
|
-
async function handleAgentStreamSend(h, args) {
|
|
5593
|
-
const agentType = args?.agentType || args?.agent;
|
|
5594
|
-
const text = args?.text || args?.message;
|
|
5595
|
-
if (!text) return { success: false, error: "text required" };
|
|
5596
|
-
if (agentType && h.ctx.adapters) {
|
|
5597
|
-
for (const [key, adapter] of h.ctx.adapters.entries()) {
|
|
5598
|
-
if (adapter.cliType === agentType || key.includes(agentType)) {
|
|
5599
|
-
LOG.info("Command", `[agent_stream_send] Routing to CLI adapter: ${adapter.cliType}`);
|
|
5600
|
-
try {
|
|
5601
|
-
await adapter.sendMessage(text);
|
|
5602
|
-
return { success: true, sent: true, targetAgent: adapter.cliType };
|
|
5603
|
-
} catch (e) {
|
|
5604
|
-
LOG.info("Command", `[agent_stream_send] CLI adapter failed: ${e.message}`);
|
|
5605
|
-
return { success: false, error: `CLI send failed: ${e.message}` };
|
|
5606
|
-
}
|
|
5607
|
-
}
|
|
5608
|
-
}
|
|
5609
|
-
}
|
|
5610
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5611
|
-
const resolvedAgent = agentType || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5612
|
-
if (!resolvedAgent) return { success: false, error: "agentType required" };
|
|
5613
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5614
|
-
const ok = await h.agentStream.sendToAgent(h.getCdp(), h.currentIdeType, resolvedAgent, text, h.currentIdeType);
|
|
5615
|
-
return { success: ok };
|
|
5616
|
-
}
|
|
5617
|
-
async function handleAgentStreamResolve(h, args) {
|
|
5618
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5619
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5620
|
-
const action = args?.action || "approve";
|
|
5621
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5622
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5623
|
-
const ok = await h.agentStream.resolveAgentAction(h.getCdp(), h.currentIdeType, agentType, action, h.currentIdeType);
|
|
5624
|
-
return { success: ok };
|
|
5625
|
-
}
|
|
5626
|
-
async function handleAgentStreamNew(h, args) {
|
|
5627
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5628
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5629
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5630
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5631
|
-
const ok = await h.agentStream.newAgentSession(h.getCdp(), h.currentIdeType, agentType, h.currentIdeType);
|
|
5632
|
-
return { success: ok };
|
|
5633
|
-
}
|
|
5634
|
-
async function handleAgentStreamListChats(h, args) {
|
|
5635
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5636
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5637
|
-
if (!agentType) return { success: false, error: "agentType required" };
|
|
5638
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5639
|
-
const chats = await h.agentStream.listAgentChats(h.getCdp(), h.currentIdeType, agentType);
|
|
5640
|
-
return { success: true, chats };
|
|
5641
|
-
}
|
|
5642
|
-
async function handleAgentStreamSwitchSession(h, args) {
|
|
5643
|
-
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5644
|
-
const agentType = args?.agentType || args?.agent || (h.currentIdeType ? h.agentStream.getActiveAgentType(h.currentIdeType) : null);
|
|
5645
|
-
const sessionId = args?.sessionId || args?.id;
|
|
5646
|
-
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
5647
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5648
|
-
const ok = await h.agentStream.switchAgentSession(h.getCdp(), h.currentIdeType, agentType, sessionId);
|
|
5649
|
-
return { success: ok };
|
|
5650
|
-
}
|
|
5651
|
-
async function handleAgentStreamFocus(h, args) {
|
|
5740
|
+
async function handleFocusSession(h, args) {
|
|
5652
5741
|
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
5653
|
-
const
|
|
5654
|
-
if (!
|
|
5655
|
-
await h.agentStream.
|
|
5656
|
-
if (!h.currentIdeType) return { success: false, error: "ideType required" };
|
|
5657
|
-
const ok = await h.agentStream.focusAgentEditor(h.getCdp(), h.currentIdeType, agentType);
|
|
5742
|
+
const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
|
|
5743
|
+
if (!sessionId) return { success: false, error: "targetSessionId required" };
|
|
5744
|
+
const ok = await h.agentStream.focusSession(h.getCdp(), sessionId);
|
|
5658
5745
|
return { success: ok };
|
|
5659
5746
|
}
|
|
5660
5747
|
function handlePtyInput(h, args) {
|
|
5661
|
-
const { cliType, data } = args || {};
|
|
5748
|
+
const { cliType, data, targetSessionId } = args || {};
|
|
5662
5749
|
if (!data) return { success: false, error: "data required" };
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
const first = h.ctx.adapters.values().next().value;
|
|
5667
|
-
if (first && typeof first.writeRaw === "function") {
|
|
5668
|
-
first.writeRaw(data);
|
|
5669
|
-
return { success: true };
|
|
5670
|
-
}
|
|
5671
|
-
}
|
|
5672
|
-
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
5673
|
-
if (directAdapter && typeof directAdapter.writeRaw === "function") {
|
|
5674
|
-
directAdapter.writeRaw(data);
|
|
5675
|
-
return { success: true };
|
|
5676
|
-
}
|
|
5677
|
-
for (const [, adapter] of h.ctx.adapters) {
|
|
5678
|
-
if (adapter.cliType === targetCli && typeof adapter.writeRaw === "function") {
|
|
5679
|
-
adapter.writeRaw(data);
|
|
5680
|
-
return { success: true };
|
|
5681
|
-
}
|
|
5682
|
-
}
|
|
5683
|
-
for (const [key, adapter] of h.ctx.adapters) {
|
|
5684
|
-
if ((key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.writeRaw === "function") {
|
|
5685
|
-
adapter.writeRaw(data);
|
|
5686
|
-
return { success: true };
|
|
5687
|
-
}
|
|
5688
|
-
}
|
|
5750
|
+
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
5751
|
+
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
5752
|
+
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
5689
5753
|
}
|
|
5690
|
-
|
|
5754
|
+
adapter.writeRaw(data);
|
|
5755
|
+
return { success: true };
|
|
5691
5756
|
}
|
|
5692
5757
|
function handlePtyResize(h, args) {
|
|
5693
|
-
const { cliType, cols, rows, force } = args || {};
|
|
5758
|
+
const { cliType, cols, rows, force, targetSessionId } = args || {};
|
|
5694
5759
|
if (!cols || !rows) return { success: false, error: "cols and rows required" };
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
first.resize(cols, rows);
|
|
5705
|
-
}
|
|
5706
|
-
return { success: true };
|
|
5707
|
-
}
|
|
5708
|
-
}
|
|
5709
|
-
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
5710
|
-
if (directAdapter && typeof directAdapter.resize === "function") {
|
|
5711
|
-
if (force) {
|
|
5712
|
-
directAdapter.resize(cols - 1, rows);
|
|
5713
|
-
setTimeout(() => directAdapter.resize(cols, rows), 50);
|
|
5714
|
-
} else {
|
|
5715
|
-
directAdapter.resize(cols, rows);
|
|
5716
|
-
}
|
|
5717
|
-
return { success: true };
|
|
5718
|
-
}
|
|
5719
|
-
for (const [key, adapter] of h.ctx.adapters) {
|
|
5720
|
-
if ((adapter.cliType === targetCli || key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.resize === "function") {
|
|
5721
|
-
if (force) {
|
|
5722
|
-
adapter.resize(cols - 1, rows);
|
|
5723
|
-
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
5724
|
-
} else {
|
|
5725
|
-
adapter.resize(cols, rows);
|
|
5726
|
-
}
|
|
5727
|
-
return { success: true };
|
|
5728
|
-
}
|
|
5729
|
-
}
|
|
5760
|
+
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
5761
|
+
if (!adapter || typeof adapter.resize !== "function") {
|
|
5762
|
+
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
5763
|
+
}
|
|
5764
|
+
if (force) {
|
|
5765
|
+
adapter.resize(cols - 1, rows);
|
|
5766
|
+
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
5767
|
+
} else {
|
|
5768
|
+
adapter.resize(cols, rows);
|
|
5730
5769
|
}
|
|
5731
|
-
return { success:
|
|
5770
|
+
return { success: true };
|
|
5732
5771
|
}
|
|
5733
5772
|
function handleGetProviderSettings(h, args) {
|
|
5734
5773
|
const loader = h.ctx.providerLoader;
|
|
@@ -5764,7 +5803,7 @@ function handleSetProviderSetting(h, args) {
|
|
|
5764
5803
|
}
|
|
5765
5804
|
async function handleExtensionScript(h, args, scriptName) {
|
|
5766
5805
|
const { agentType, ideType } = args || {};
|
|
5767
|
-
LOG.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType}
|
|
5806
|
+
LOG.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType} session=${h.currentSession?.sessionId || ""}`);
|
|
5768
5807
|
if (!agentType) return { success: false, error: "agentType is required" };
|
|
5769
5808
|
const loader = h.ctx.providerLoader;
|
|
5770
5809
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -5785,21 +5824,22 @@ async function handleExtensionScript(h, args, scriptName) {
|
|
|
5785
5824
|
}
|
|
5786
5825
|
const scriptCode = scriptFn(normalizedArgs);
|
|
5787
5826
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
5788
|
-
const cdpKey = provider.category === "ide" ? h.
|
|
5827
|
+
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
|
|
5789
5828
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
5790
5829
|
const cdp = h.getCdp(cdpKey);
|
|
5791
5830
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
5792
5831
|
try {
|
|
5793
5832
|
let result;
|
|
5794
5833
|
if (provider.category === "extension") {
|
|
5795
|
-
const
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5834
|
+
const runtimeSessionId = h.currentSession?.sessionId || args?.targetSessionId;
|
|
5835
|
+
if (!runtimeSessionId) return { success: false, error: `No target session found for ${agentType}` };
|
|
5836
|
+
const parentSessionId = h.currentSession?.parentSessionId;
|
|
5837
|
+
if (parentSessionId) {
|
|
5838
|
+
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
5839
|
+
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
5840
|
+
}
|
|
5841
|
+
const managed = runtimeSessionId ? h.agentStream?.getManagedSession(runtimeSessionId) : null;
|
|
5842
|
+
const targetSessionId = managed?.cdpSessionId || null;
|
|
5803
5843
|
const IDE_LEVEL_SCRIPTS = ["listModes", "setMode", "listModels", "setModel"];
|
|
5804
5844
|
if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
|
|
5805
5845
|
if (targetSessionId) {
|
|
@@ -5870,7 +5910,7 @@ function handleGetIdeExtensions(h, args) {
|
|
|
5870
5910
|
enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
|
|
5871
5911
|
}));
|
|
5872
5912
|
}
|
|
5873
|
-
return { success: true,
|
|
5913
|
+
return { success: true, ideExtensions: result };
|
|
5874
5914
|
}
|
|
5875
5915
|
function handleSetIdeExtension(h, args) {
|
|
5876
5916
|
const { ideType, extensionType, enabled } = args || {};
|
|
@@ -5982,10 +6022,8 @@ var DaemonCommandHandler = class {
|
|
|
5982
6022
|
_agentStream = null;
|
|
5983
6023
|
domHandlers;
|
|
5984
6024
|
_historyWriter;
|
|
5985
|
-
/** Current
|
|
5986
|
-
|
|
5987
|
-
/** Current provider type — agentType priority, ideType use */
|
|
5988
|
-
_currentProviderType;
|
|
6025
|
+
/** Current request route context */
|
|
6026
|
+
_currentRoute = {};
|
|
5989
6027
|
constructor(ctx) {
|
|
5990
6028
|
this._ctx = ctx;
|
|
5991
6029
|
this.domHandlers = new CdpDomHandlers((ideType) => this.getCdp(ideType));
|
|
@@ -6001,20 +6039,25 @@ var DaemonCommandHandler = class {
|
|
|
6001
6039
|
get historyWriter() {
|
|
6002
6040
|
return this._historyWriter;
|
|
6003
6041
|
}
|
|
6042
|
+
get currentManagerKey() {
|
|
6043
|
+
return this._currentRoute.managerKey;
|
|
6044
|
+
}
|
|
6004
6045
|
get currentIdeType() {
|
|
6005
|
-
return this.
|
|
6046
|
+
return this._currentRoute.managerKey;
|
|
6006
6047
|
}
|
|
6007
6048
|
get currentProviderType() {
|
|
6008
|
-
return this.
|
|
6049
|
+
return this._currentRoute.providerType;
|
|
6050
|
+
}
|
|
6051
|
+
get currentSession() {
|
|
6052
|
+
return this._currentRoute.session;
|
|
6009
6053
|
}
|
|
6010
|
-
/** Get CDP manager for a specific
|
|
6011
|
-
* Supports exact match, multi-window prefix match, and instanceIdMap UUID lookup.
|
|
6012
|
-
* Returns null if no match — never falls back to another IDE. */
|
|
6054
|
+
/** Get CDP manager for a specific session or manager key. */
|
|
6013
6055
|
getCdp(ideType) {
|
|
6014
|
-
const
|
|
6015
|
-
if (!
|
|
6016
|
-
const
|
|
6017
|
-
const
|
|
6056
|
+
const requested = ideType || this._currentRoute.session?.sessionId || this._currentRoute.managerKey;
|
|
6057
|
+
if (!requested) return null;
|
|
6058
|
+
const session = this._ctx.sessionRegistry?.get(requested);
|
|
6059
|
+
const managerKey = session?.cdpManagerKey || requested;
|
|
6060
|
+
const m = findCdpManager(this._ctx.cdpManagers, managerKey);
|
|
6018
6061
|
if (m?.isConnected) return m;
|
|
6019
6062
|
return null;
|
|
6020
6063
|
}
|
|
@@ -6022,7 +6065,7 @@ var DaemonCommandHandler = class {
|
|
|
6022
6065
|
* Get provider module — _currentProviderType (agentType priority) use.
|
|
6023
6066
|
*/
|
|
6024
6067
|
getProvider(overrideType) {
|
|
6025
|
-
const key = overrideType || this.
|
|
6068
|
+
const key = overrideType || this._currentRoute.providerType || this._currentRoute.session?.providerType || this._currentRoute.managerKey;
|
|
6026
6069
|
if (!key || !this._ctx.providerLoader) return void 0;
|
|
6027
6070
|
const result = this._ctx.providerLoader.resolve(key);
|
|
6028
6071
|
if (result) return result;
|
|
@@ -6055,14 +6098,22 @@ var DaemonCommandHandler = class {
|
|
|
6055
6098
|
const cdp = this.getCdp();
|
|
6056
6099
|
if (!cdp?.isConnected) return null;
|
|
6057
6100
|
if (provider?.category === "extension") {
|
|
6058
|
-
let sessionId = this.
|
|
6059
|
-
if (!sessionId && this.
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6101
|
+
let sessionId = this._currentRoute.session?.sessionId || null;
|
|
6102
|
+
if (!sessionId && this._currentRoute.session?.parentSessionId) {
|
|
6103
|
+
sessionId = this._agentStream?.resolveSessionForAgent(this._currentRoute.session.parentSessionId, provider.type) || null;
|
|
6104
|
+
}
|
|
6105
|
+
if (sessionId && this._agentStream) {
|
|
6106
|
+
const target = this._ctx.sessionRegistry?.get(sessionId);
|
|
6107
|
+
if (target?.parentSessionId) {
|
|
6108
|
+
await this._agentStream.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
6109
|
+
await this._agentStream.syncActiveSession(cdp, target.parentSessionId);
|
|
6110
|
+
}
|
|
6063
6111
|
}
|
|
6064
6112
|
if (!sessionId) return null;
|
|
6065
|
-
const
|
|
6113
|
+
const managed = this._agentStream?.getManagedSession(sessionId);
|
|
6114
|
+
const cdpSessionId = managed?.cdpSessionId;
|
|
6115
|
+
if (!cdpSessionId) return null;
|
|
6116
|
+
const result2 = await cdp.evaluateInSessionFrame(cdpSessionId, script, timeout);
|
|
6066
6117
|
return { result: result2, category: "extension" };
|
|
6067
6118
|
}
|
|
6068
6119
|
const result = await cdp.evaluate(script, timeout);
|
|
@@ -6070,57 +6121,37 @@ var DaemonCommandHandler = class {
|
|
|
6070
6121
|
}
|
|
6071
6122
|
/** CLI adapter search */
|
|
6072
6123
|
getCliAdapter(type) {
|
|
6073
|
-
const target = type || this.
|
|
6124
|
+
const target = type || this._currentRoute.session?.sessionId || this._currentRoute.providerType || this._currentRoute.managerKey;
|
|
6074
6125
|
if (!target || !this._ctx.adapters) return null;
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
const direct = this._ctx.adapters.get(normalizedTarget);
|
|
6079
|
-
if (direct) return direct;
|
|
6080
|
-
for (const [key, adapter] of this._ctx.adapters.entries()) {
|
|
6081
|
-
if (adapter.cliType === target || adapter.cliType === normalizedTarget || key === normalizedTarget || key.startsWith(target) || key.startsWith(normalizedTarget)) {
|
|
6082
|
-
return adapter;
|
|
6083
|
-
}
|
|
6126
|
+
const session = this._ctx.sessionRegistry?.get(target);
|
|
6127
|
+
if (session?.adapterKey) {
|
|
6128
|
+
return this._ctx.adapters.get(session.adapterKey) || null;
|
|
6084
6129
|
}
|
|
6085
|
-
return null;
|
|
6130
|
+
return this._ctx.adapters.get(target) || null;
|
|
6086
6131
|
}
|
|
6087
6132
|
// ─── Private helpers ──────────────────────────────
|
|
6088
|
-
|
|
6089
|
-
if (
|
|
6090
|
-
const
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
const
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
const managerKey = instanceKey.slice(4);
|
|
6102
|
-
this._ctx.instanceIdMap?.set(instanceId, managerKey);
|
|
6103
|
-
return managerKey;
|
|
6104
|
-
}
|
|
6105
|
-
if (typeof instance?.getExtensionInstances === "function") {
|
|
6106
|
-
for (const ext of instance.getExtensionInstances() || []) {
|
|
6107
|
-
if (typeof ext?.getInstanceId === "function" && ext.getInstanceId() === instanceId) {
|
|
6108
|
-
const managerKey = instanceKey.slice(4);
|
|
6109
|
-
this._ctx.instanceIdMap?.set(instanceId, managerKey);
|
|
6110
|
-
return managerKey;
|
|
6111
|
-
}
|
|
6112
|
-
}
|
|
6113
|
-
}
|
|
6114
|
-
}
|
|
6115
|
-
return void 0;
|
|
6116
|
-
}
|
|
6117
|
-
/** Extract ideType from _targetInstance or explicit ideType */
|
|
6133
|
+
inferProviderType(key) {
|
|
6134
|
+
if (!key) return void 0;
|
|
6135
|
+
const session = this._ctx.sessionRegistry?.get(key);
|
|
6136
|
+
if (session?.providerType) return session.providerType;
|
|
6137
|
+
return key.split("_")[0];
|
|
6138
|
+
}
|
|
6139
|
+
resolveRoute(args) {
|
|
6140
|
+
const session = this._ctx.sessionRegistry?.get(args?.targetSessionId);
|
|
6141
|
+
const managerKey = this.extractIdeType(args);
|
|
6142
|
+
const providerType = args?.agentType || args?.providerType || session?.providerType || this.inferProviderType(managerKey);
|
|
6143
|
+
return { session, managerKey, providerType };
|
|
6144
|
+
}
|
|
6145
|
+
/** Extract CDP scope key from target session or explicit ideType */
|
|
6118
6146
|
extractIdeType(args) {
|
|
6147
|
+
if (args?.targetSessionId) {
|
|
6148
|
+
const target = this._ctx.sessionRegistry?.get(args.targetSessionId);
|
|
6149
|
+
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
6150
|
+
if (this._ctx.cdpManagers.has(args.targetSessionId)) return args.targetSessionId;
|
|
6151
|
+
}
|
|
6119
6152
|
if (args?.ideType) {
|
|
6120
|
-
const
|
|
6121
|
-
if (
|
|
6122
|
-
return mappedKey;
|
|
6123
|
-
}
|
|
6153
|
+
const target = this._ctx.sessionRegistry?.get(args.ideType);
|
|
6154
|
+
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
6124
6155
|
if (this._ctx.cdpManagers.has(args.ideType)) {
|
|
6125
6156
|
return args.ideType;
|
|
6126
6157
|
}
|
|
@@ -6131,34 +6162,6 @@ var DaemonCommandHandler = class {
|
|
|
6131
6162
|
}
|
|
6132
6163
|
}
|
|
6133
6164
|
}
|
|
6134
|
-
if (args?._targetInstance) {
|
|
6135
|
-
let raw = args._targetInstance;
|
|
6136
|
-
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
6137
|
-
const cliMatch = raw.match(/:cli:(.+)$/);
|
|
6138
|
-
const acpMatch = raw.match(/:acp:(.+)$/);
|
|
6139
|
-
if (ideMatch) raw = ideMatch[1];
|
|
6140
|
-
else if (cliMatch) raw = cliMatch[1];
|
|
6141
|
-
else if (acpMatch) raw = acpMatch[1];
|
|
6142
|
-
const mappedKey = this.resolveManagerKeyFromInstanceId(raw);
|
|
6143
|
-
if (mappedKey) {
|
|
6144
|
-
return mappedKey;
|
|
6145
|
-
}
|
|
6146
|
-
if (this._ctx.cdpManagers.has(raw)) {
|
|
6147
|
-
return raw;
|
|
6148
|
-
}
|
|
6149
|
-
const found = findCdpManager(this._ctx.cdpManagers, raw);
|
|
6150
|
-
if (found) {
|
|
6151
|
-
for (const [k, m] of this._ctx.cdpManagers.entries()) {
|
|
6152
|
-
if (m === found) return k;
|
|
6153
|
-
}
|
|
6154
|
-
}
|
|
6155
|
-
const lastUnderscore = raw.lastIndexOf("_");
|
|
6156
|
-
if (lastUnderscore > 0) {
|
|
6157
|
-
const stripped = raw.substring(0, lastUnderscore);
|
|
6158
|
-
if (this._ctx.cdpManagers.has(stripped)) return stripped;
|
|
6159
|
-
}
|
|
6160
|
-
return raw;
|
|
6161
|
-
}
|
|
6162
6165
|
return void 0;
|
|
6163
6166
|
}
|
|
6164
6167
|
setAgentStreamManager(manager) {
|
|
@@ -6166,12 +6169,11 @@ var DaemonCommandHandler = class {
|
|
|
6166
6169
|
}
|
|
6167
6170
|
// ─── Command Dispatcher ──────────────────────────
|
|
6168
6171
|
async handle(cmd, args) {
|
|
6169
|
-
this.
|
|
6170
|
-
this.
|
|
6171
|
-
if (!this._currentIdeType && !this._currentProviderType) {
|
|
6172
|
+
this._currentRoute = this.resolveRoute(args);
|
|
6173
|
+
if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
|
|
6172
6174
|
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
6173
6175
|
if (cdpCommands.includes(cmd)) {
|
|
6174
|
-
return { success: false, error: "No
|
|
6176
|
+
return { success: false, error: "No targetSessionId specified \u2014 cannot route command" };
|
|
6175
6177
|
}
|
|
6176
6178
|
}
|
|
6177
6179
|
try {
|
|
@@ -6262,22 +6264,8 @@ var DaemonCommandHandler = class {
|
|
|
6262
6264
|
case "refresh_scripts":
|
|
6263
6265
|
return this.handleRefreshScripts(args);
|
|
6264
6266
|
// ─── Stream commands (stream-commands.ts) ───────────
|
|
6265
|
-
case "
|
|
6266
|
-
return
|
|
6267
|
-
case "agent_stream_read":
|
|
6268
|
-
return handleAgentStreamRead(this, args);
|
|
6269
|
-
case "agent_stream_send":
|
|
6270
|
-
return handleAgentStreamSend(this, args);
|
|
6271
|
-
case "agent_stream_resolve":
|
|
6272
|
-
return handleAgentStreamResolve(this, args);
|
|
6273
|
-
case "agent_stream_new":
|
|
6274
|
-
return handleAgentStreamNew(this, args);
|
|
6275
|
-
case "agent_stream_list_chats":
|
|
6276
|
-
return handleAgentStreamListChats(this, args);
|
|
6277
|
-
case "agent_stream_switch_session":
|
|
6278
|
-
return handleAgentStreamSwitchSession(this, args);
|
|
6279
|
-
case "agent_stream_focus":
|
|
6280
|
-
return handleAgentStreamFocus(this, args);
|
|
6267
|
+
case "focus_session":
|
|
6268
|
+
return handleFocusSession(this, args);
|
|
6281
6269
|
// ─── PTY Raw I/O (stream-commands.ts) ─────────
|
|
6282
6270
|
case "pty_input":
|
|
6283
6271
|
return handlePtyInput(this, args);
|
|
@@ -7925,8 +7913,7 @@ var CHAT_COMMANDS = [
|
|
|
7925
7913
|
"new_chat",
|
|
7926
7914
|
"switch_chat",
|
|
7927
7915
|
"set_mode",
|
|
7928
|
-
"change_model"
|
|
7929
|
-
"agent_stream_send"
|
|
7916
|
+
"change_model"
|
|
7930
7917
|
];
|
|
7931
7918
|
var DaemonCommandRouter = class {
|
|
7932
7919
|
deps;
|
|
@@ -8164,6 +8151,7 @@ var DaemonCommandRouter = class {
|
|
|
8164
8151
|
} catch {
|
|
8165
8152
|
}
|
|
8166
8153
|
this.deps.cdpManagers.delete(key);
|
|
8154
|
+
this.deps.sessionRegistry.unregisterByManagerKey(key);
|
|
8167
8155
|
LOG.info("StopIDE", `CDP disconnected: ${key}`);
|
|
8168
8156
|
}
|
|
8169
8157
|
}
|
|
@@ -8176,14 +8164,6 @@ var DaemonCommandRouter = class {
|
|
|
8176
8164
|
for (const instanceKey of keysToRemove) {
|
|
8177
8165
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
8178
8166
|
if (ideInstance) {
|
|
8179
|
-
if (ideInstance.getInstanceId) {
|
|
8180
|
-
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
8181
|
-
}
|
|
8182
|
-
if (ideInstance.getExtensionInstances) {
|
|
8183
|
-
for (const ext of ideInstance.getExtensionInstances()) {
|
|
8184
|
-
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
8185
|
-
}
|
|
8186
|
-
}
|
|
8187
8167
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
8188
8168
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
8189
8169
|
}
|
|
@@ -8192,14 +8172,6 @@ var DaemonCommandRouter = class {
|
|
|
8192
8172
|
const instanceKey = `ide:${ideType}`;
|
|
8193
8173
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
8194
8174
|
if (ideInstance) {
|
|
8195
|
-
if (ideInstance.getInstanceId) {
|
|
8196
|
-
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
8197
|
-
}
|
|
8198
|
-
if (ideInstance.getExtensionInstances) {
|
|
8199
|
-
for (const ext of ideInstance.getExtensionInstances()) {
|
|
8200
|
-
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
8201
|
-
}
|
|
8202
|
-
}
|
|
8203
8175
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
8204
8176
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
8205
8177
|
}
|
|
@@ -8252,15 +8224,9 @@ function buildStatusSnapshot(options) {
|
|
|
8252
8224
|
const cfg = loadConfig();
|
|
8253
8225
|
const wsState = getWorkspaceState(cfg);
|
|
8254
8226
|
const memSnap = getHostMemorySnapshot();
|
|
8255
|
-
const
|
|
8227
|
+
const sessions = buildSessionEntries(
|
|
8256
8228
|
options.allStates,
|
|
8257
|
-
options.cdpManagers
|
|
8258
|
-
{
|
|
8259
|
-
detectedIdes: options.detectedIdes.map((ide) => ({
|
|
8260
|
-
id: ide.id,
|
|
8261
|
-
installed: ide.installed !== false
|
|
8262
|
-
}))
|
|
8263
|
-
}
|
|
8229
|
+
options.cdpManagers
|
|
8264
8230
|
);
|
|
8265
8231
|
return {
|
|
8266
8232
|
instanceId: options.instanceId,
|
|
@@ -8282,9 +8248,7 @@ function buildStatusSnapshot(options) {
|
|
|
8282
8248
|
timestamp: options.timestamp ?? Date.now(),
|
|
8283
8249
|
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8284
8250
|
...options.p2p ? { p2p: options.p2p } : {},
|
|
8285
|
-
|
|
8286
|
-
managedClis,
|
|
8287
|
-
managedAcps,
|
|
8251
|
+
sessions,
|
|
8288
8252
|
workspaces: wsState.workspaces,
|
|
8289
8253
|
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8290
8254
|
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
@@ -8396,7 +8360,7 @@ var DaemonStatusReporter = class {
|
|
|
8396
8360
|
LOG.info("StatusReport", `\u2192${target} ${baseSummary}`);
|
|
8397
8361
|
}
|
|
8398
8362
|
}
|
|
8399
|
-
const
|
|
8363
|
+
const sessions = buildSessionEntries(
|
|
8400
8364
|
allStates,
|
|
8401
8365
|
this.deps.cdpManagers
|
|
8402
8366
|
);
|
|
@@ -8427,23 +8391,20 @@ var DaemonStatusReporter = class {
|
|
|
8427
8391
|
if (opts?.p2pOnly) return;
|
|
8428
8392
|
const wsPayload = {
|
|
8429
8393
|
daemonMode: true,
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
id: a.id,
|
|
8445
|
-
acpType: a.acpType,
|
|
8446
|
-
acpName: a.acpName
|
|
8394
|
+
sessions: sessions.map((session) => ({
|
|
8395
|
+
id: session.id,
|
|
8396
|
+
parentId: session.parentId,
|
|
8397
|
+
providerType: session.providerType,
|
|
8398
|
+
providerName: session.providerName,
|
|
8399
|
+
kind: session.kind,
|
|
8400
|
+
transport: session.transport,
|
|
8401
|
+
status: session.status,
|
|
8402
|
+
workspace: session.workspace,
|
|
8403
|
+
title: session.title,
|
|
8404
|
+
cdpConnected: session.cdpConnected,
|
|
8405
|
+
currentModel: session.currentModel,
|
|
8406
|
+
currentPlan: session.currentPlan,
|
|
8407
|
+
currentAutoApprove: session.currentAutoApprove
|
|
8447
8408
|
})),
|
|
8448
8409
|
p2p: payload.p2p,
|
|
8449
8410
|
timestamp: now
|
|
@@ -8879,6 +8840,9 @@ var AcpProviderInstance = class {
|
|
|
8879
8840
|
);
|
|
8880
8841
|
}
|
|
8881
8842
|
}
|
|
8843
|
+
getInstanceId() {
|
|
8844
|
+
return this.instanceId;
|
|
8845
|
+
}
|
|
8882
8846
|
// ─── ACP Config Options & Modes ─────────────────────
|
|
8883
8847
|
parseConfigOptions(raw) {
|
|
8884
8848
|
if (!Array.isArray(raw)) return;
|
|
@@ -9658,6 +9622,7 @@ var DaemonCliManager = class {
|
|
|
9658
9622
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
9659
9623
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
9660
9624
|
const key = crypto4.randomUUID();
|
|
9625
|
+
const sessionRegistry = this.deps.getSessionRegistry?.() || null;
|
|
9661
9626
|
if (provider && provider.category === "acp") {
|
|
9662
9627
|
const instanceManager2 = this.deps.getInstanceManager();
|
|
9663
9628
|
if (!instanceManager2) throw new Error("InstanceManager not available");
|
|
@@ -9681,6 +9646,16 @@ ${installInfo}`
|
|
|
9681
9646
|
await instanceManager2.addInstance(key, acpInstance, {
|
|
9682
9647
|
settings: this.providerLoader.getSettings(normalizedType)
|
|
9683
9648
|
});
|
|
9649
|
+
const sessionId = acpInstance.getInstanceId();
|
|
9650
|
+
sessionRegistry?.register({
|
|
9651
|
+
sessionId,
|
|
9652
|
+
parentSessionId: null,
|
|
9653
|
+
providerType: normalizedType,
|
|
9654
|
+
providerCategory: "acp",
|
|
9655
|
+
transport: "acp",
|
|
9656
|
+
adapterKey: key,
|
|
9657
|
+
instanceKey: key
|
|
9658
|
+
});
|
|
9684
9659
|
this.adapters.set(key, {
|
|
9685
9660
|
cliType: normalizedType,
|
|
9686
9661
|
workingDir: resolvedDir,
|
|
@@ -9738,9 +9713,18 @@ ${installInfo}`
|
|
|
9738
9713
|
serverConn: this.deps.getServerConn(),
|
|
9739
9714
|
settings: {},
|
|
9740
9715
|
onPtyData: (data) => {
|
|
9741
|
-
this.deps.getP2p()?.broadcastPtyOutput(
|
|
9716
|
+
this.deps.getP2p()?.broadcastPtyOutput(cliInstance.instanceId, data);
|
|
9742
9717
|
}
|
|
9743
9718
|
});
|
|
9719
|
+
sessionRegistry?.register({
|
|
9720
|
+
sessionId: cliInstance.instanceId,
|
|
9721
|
+
parentSessionId: null,
|
|
9722
|
+
providerType: normalizedType,
|
|
9723
|
+
providerCategory: "cli",
|
|
9724
|
+
transport: "pty",
|
|
9725
|
+
adapterKey: key,
|
|
9726
|
+
instanceKey: key
|
|
9727
|
+
});
|
|
9744
9728
|
} catch (spawnErr) {
|
|
9745
9729
|
LOG.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
9746
9730
|
instanceManager.removeInstance(key);
|
|
@@ -9762,6 +9746,7 @@ ${installInfo}`
|
|
|
9762
9746
|
if (this.adapters.has(key)) {
|
|
9763
9747
|
this.adapters.delete(key);
|
|
9764
9748
|
this.deps.removeAgentTracking(key);
|
|
9749
|
+
sessionRegistry?.unregisterByInstanceKey(key);
|
|
9765
9750
|
instanceManager.removeInstance(key);
|
|
9766
9751
|
LOG.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
|
|
9767
9752
|
this.deps.onStatusChange();
|
|
@@ -9822,12 +9807,14 @@ ${installInfo}`
|
|
|
9822
9807
|
}
|
|
9823
9808
|
this.adapters.delete(key);
|
|
9824
9809
|
this.deps.removeAgentTracking(key);
|
|
9810
|
+
this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
|
|
9825
9811
|
this.deps.getInstanceManager()?.removeInstance(key);
|
|
9826
9812
|
LOG.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
|
|
9827
9813
|
this.deps.onStatusChange();
|
|
9828
9814
|
} else {
|
|
9829
9815
|
const im = this.deps.getInstanceManager();
|
|
9830
9816
|
if (im) {
|
|
9817
|
+
this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
|
|
9831
9818
|
im.removeInstance(key);
|
|
9832
9819
|
this.deps.removeAgentTracking(key);
|
|
9833
9820
|
LOG.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
|
|
@@ -9842,7 +9829,7 @@ ${installInfo}`
|
|
|
9842
9829
|
// ─── Adapter search ─────────────────────────────
|
|
9843
9830
|
/**
|
|
9844
9831
|
* Search for CLI adapter. Priority order:
|
|
9845
|
-
* 0.
|
|
9832
|
+
* 0. sessionId (UUID direct match)
|
|
9846
9833
|
* 1. agentType + dir (iteration match)
|
|
9847
9834
|
* 2. agentType fuzzy match (⚠ returns first match when multiple sessions exist)
|
|
9848
9835
|
*/
|
|
@@ -9910,7 +9897,7 @@ ${installInfo}`
|
|
|
9910
9897
|
const cliType = args?.cliType;
|
|
9911
9898
|
const dir = args?.dir || "";
|
|
9912
9899
|
if (!cliType) throw new Error("cliType required");
|
|
9913
|
-
const found = this.findAdapter(cliType, { instanceKey: args?.
|
|
9900
|
+
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9914
9901
|
if (found) {
|
|
9915
9902
|
await this.stopSession(found.key);
|
|
9916
9903
|
} else {
|
|
@@ -9942,7 +9929,7 @@ ${installInfo}`
|
|
|
9942
9929
|
}
|
|
9943
9930
|
const dir = rdir.path;
|
|
9944
9931
|
if (!cliType) throw new Error("cliType required");
|
|
9945
|
-
const found = this.findAdapter(cliType, { instanceKey: args?.
|
|
9932
|
+
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9946
9933
|
if (found) await this.stopSession(found.key);
|
|
9947
9934
|
await this.startSession(cliType, dir);
|
|
9948
9935
|
this.persistRecentDir(cliType, dir);
|
|
@@ -9954,7 +9941,7 @@ ${installInfo}`
|
|
|
9954
9941
|
if (!agentType || !action) throw new Error("agentType and action required");
|
|
9955
9942
|
const found = this.findAdapter(agentType, {
|
|
9956
9943
|
dir: args?.dir,
|
|
9957
|
-
instanceKey: args?.
|
|
9944
|
+
instanceKey: args?.targetSessionId
|
|
9958
9945
|
});
|
|
9959
9946
|
if (!found) throw new Error(`CLI agent not running: ${agentType}`);
|
|
9960
9947
|
const { adapter, key } = found;
|
|
@@ -10100,14 +10087,8 @@ var ProviderStreamAdapter = class {
|
|
|
10100
10087
|
// src/agent-stream/manager.ts
|
|
10101
10088
|
init_logger();
|
|
10102
10089
|
var DaemonAgentStreamManager = class {
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
enabled = true;
|
|
10106
|
-
logFn;
|
|
10107
|
-
lastDiscoveryTimeByScope = /* @__PURE__ */ new Map();
|
|
10108
|
-
discoveryIntervalMsByScope = /* @__PURE__ */ new Map();
|
|
10109
|
-
activeAgentTypeByScope = /* @__PURE__ */ new Map();
|
|
10110
|
-
constructor(logFn, providerLoader) {
|
|
10090
|
+
constructor(logFn, providerLoader, sessionRegistry) {
|
|
10091
|
+
this.sessionRegistry = sessionRegistry;
|
|
10111
10092
|
this.logFn = logFn || LOG.forComponent("AgentStream").asLogFn();
|
|
10112
10093
|
if (providerLoader) {
|
|
10113
10094
|
const allExtProviders = providerLoader.getByCategory("extension");
|
|
@@ -10115,257 +10096,278 @@ var DaemonAgentStreamManager = class {
|
|
|
10115
10096
|
const resolved = providerLoader.resolve(p.type);
|
|
10116
10097
|
if (!resolved) continue;
|
|
10117
10098
|
const adapter = new ProviderStreamAdapter(resolved);
|
|
10118
|
-
this.
|
|
10099
|
+
this.adaptersByType.set(p.type, adapter);
|
|
10119
10100
|
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name}) scripts=${Object.keys(resolved.scripts || {}).join(",") || "none"}`);
|
|
10120
10101
|
}
|
|
10121
10102
|
}
|
|
10122
10103
|
}
|
|
10104
|
+
adaptersByType = /* @__PURE__ */ new Map();
|
|
10105
|
+
managedBySessionId = /* @__PURE__ */ new Map();
|
|
10106
|
+
enabled = true;
|
|
10107
|
+
logFn;
|
|
10108
|
+
lastDiscoveryTimeByParent = /* @__PURE__ */ new Map();
|
|
10109
|
+
discoveryIntervalMsByParent = /* @__PURE__ */ new Map();
|
|
10110
|
+
activeSessionIdByParent = /* @__PURE__ */ new Map();
|
|
10123
10111
|
setEnabled(enabled) {
|
|
10124
10112
|
this.enabled = enabled;
|
|
10125
10113
|
}
|
|
10126
10114
|
get isEnabled() {
|
|
10127
10115
|
return this.enabled;
|
|
10128
10116
|
}
|
|
10129
|
-
|
|
10130
|
-
return this.
|
|
10117
|
+
getActiveSessionId(parentSessionId) {
|
|
10118
|
+
return this.activeSessionIdByParent.get(parentSessionId) || null;
|
|
10131
10119
|
}
|
|
10132
|
-
|
|
10133
|
-
|
|
10134
|
-
if (!managed) {
|
|
10135
|
-
managed = /* @__PURE__ */ new Map();
|
|
10136
|
-
this.managedByScope.set(scopeKey, managed);
|
|
10137
|
-
}
|
|
10138
|
-
return managed;
|
|
10120
|
+
getSessionTarget(sessionId) {
|
|
10121
|
+
return this.sessionRegistry?.get(sessionId);
|
|
10139
10122
|
}
|
|
10140
|
-
|
|
10141
|
-
this.
|
|
10142
|
-
this.
|
|
10143
|
-
this.
|
|
10144
|
-
|
|
10123
|
+
resetParentSession(parentSessionId) {
|
|
10124
|
+
const activeSessionId = this.activeSessionIdByParent.get(parentSessionId);
|
|
10125
|
+
if (activeSessionId) this.managedBySessionId.delete(activeSessionId);
|
|
10126
|
+
for (const child of this.sessionRegistry?.listChildren(parentSessionId) || []) {
|
|
10127
|
+
this.managedBySessionId.delete(child.sessionId);
|
|
10128
|
+
}
|
|
10129
|
+
this.activeSessionIdByParent.delete(parentSessionId);
|
|
10130
|
+
this.lastDiscoveryTimeByParent.delete(parentSessionId);
|
|
10131
|
+
this.discoveryIntervalMsByParent.delete(parentSessionId);
|
|
10145
10132
|
}
|
|
10146
10133
|
/** Panel focus based on provider.js focusPanel or extensionId (currently no-op) */
|
|
10147
|
-
async
|
|
10148
|
-
}
|
|
10149
|
-
async
|
|
10150
|
-
const
|
|
10151
|
-
|
|
10152
|
-
if (
|
|
10153
|
-
|
|
10154
|
-
const prev = managed.get(previousAgentType);
|
|
10134
|
+
async ensureSessionPanelOpen(_sessionId) {
|
|
10135
|
+
}
|
|
10136
|
+
async setActiveSession(cdp, parentSessionId, sessionId) {
|
|
10137
|
+
const previousSessionId = this.getActiveSessionId(parentSessionId);
|
|
10138
|
+
if (previousSessionId === sessionId) return;
|
|
10139
|
+
if (previousSessionId) {
|
|
10140
|
+
const prev = this.managedBySessionId.get(previousSessionId);
|
|
10155
10141
|
if (prev) {
|
|
10156
10142
|
try {
|
|
10157
|
-
await cdp.detachAgent(prev.
|
|
10143
|
+
await cdp.detachAgent(prev.cdpSessionId);
|
|
10158
10144
|
} catch {
|
|
10159
10145
|
}
|
|
10160
|
-
|
|
10161
|
-
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName} (${
|
|
10162
|
-
}
|
|
10163
|
-
}
|
|
10164
|
-
this.
|
|
10165
|
-
this.
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
this.
|
|
10146
|
+
this.managedBySessionId.delete(previousSessionId);
|
|
10147
|
+
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName} (${parentSessionId})`);
|
|
10148
|
+
}
|
|
10149
|
+
}
|
|
10150
|
+
this.activeSessionIdByParent.set(parentSessionId, sessionId);
|
|
10151
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
10152
|
+
this.logFn(`[AgentStream] Active session (${parentSessionId}): ${sessionId || "none"}`);
|
|
10153
|
+
}
|
|
10154
|
+
resolveSessionIdForTarget(parentSessionId, agentType) {
|
|
10155
|
+
const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.providerCategory === "extension" && entry.providerType === agentType);
|
|
10156
|
+
return child?.sessionId || null;
|
|
10157
|
+
}
|
|
10158
|
+
async connectManagedSession(cdp, parentSessionId, runtimeSessionId) {
|
|
10159
|
+
const target = this.getSessionTarget(runtimeSessionId);
|
|
10160
|
+
if (!target || target.providerCategory !== "extension") return null;
|
|
10161
|
+
const adapter = this.adaptersByType.get(target.providerType);
|
|
10162
|
+
if (!adapter) return null;
|
|
10163
|
+
const targets = await cdp.discoverAgentWebviews();
|
|
10164
|
+
const activeTarget = targets.find((entry) => entry.agentType === target.providerType);
|
|
10165
|
+
if (!activeTarget) return null;
|
|
10166
|
+
const cdpSessionId = await cdp.attachToAgent(activeTarget);
|
|
10167
|
+
if (!cdpSessionId) return null;
|
|
10168
|
+
const managed = {
|
|
10169
|
+
adapter,
|
|
10170
|
+
runtimeSessionId,
|
|
10171
|
+
parentSessionId,
|
|
10172
|
+
cdpSessionId,
|
|
10173
|
+
target: activeTarget,
|
|
10174
|
+
lastState: null,
|
|
10175
|
+
lastError: null,
|
|
10176
|
+
lastHiddenCheckTime: 0
|
|
10177
|
+
};
|
|
10178
|
+
this.managedBySessionId.set(runtimeSessionId, managed);
|
|
10179
|
+
this.logFn(`[AgentStream] Connected: ${adapter.agentName} (${parentSessionId})`);
|
|
10180
|
+
return managed;
|
|
10170
10181
|
}
|
|
10171
10182
|
/** Agent webview discovery + session connection */
|
|
10172
|
-
async
|
|
10173
|
-
const
|
|
10174
|
-
if (!this.enabled || !
|
|
10183
|
+
async syncActiveSession(cdp, parentSessionId) {
|
|
10184
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
10185
|
+
if (!this.enabled || !activeSessionId) return;
|
|
10175
10186
|
const now = Date.now();
|
|
10176
|
-
const managed = this.
|
|
10177
|
-
const lastDiscoveryTime = this.
|
|
10178
|
-
const discoveryIntervalMs = this.
|
|
10179
|
-
if (managed
|
|
10187
|
+
const managed = this.managedBySessionId.get(activeSessionId);
|
|
10188
|
+
const lastDiscoveryTime = this.lastDiscoveryTimeByParent.get(parentSessionId) || 0;
|
|
10189
|
+
const discoveryIntervalMs = this.discoveryIntervalMsByParent.get(parentSessionId) || 1e4;
|
|
10190
|
+
if (managed && now - lastDiscoveryTime < discoveryIntervalMs) {
|
|
10180
10191
|
return;
|
|
10181
10192
|
}
|
|
10182
|
-
this.
|
|
10193
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, now);
|
|
10183
10194
|
try {
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
if (activeTarget && !managed.has(activeAgentType)) {
|
|
10187
|
-
const adapter = this.allAdapters.find((a) => a.agentType === activeAgentType);
|
|
10188
|
-
if (adapter) {
|
|
10189
|
-
const sessionId = await cdp.attachToAgent(activeTarget);
|
|
10190
|
-
if (sessionId) {
|
|
10191
|
-
managed.set(activeAgentType, {
|
|
10192
|
-
adapter,
|
|
10193
|
-
sessionId,
|
|
10194
|
-
target: activeTarget,
|
|
10195
|
-
lastState: null,
|
|
10196
|
-
lastError: null,
|
|
10197
|
-
lastHiddenCheckTime: 0
|
|
10198
|
-
});
|
|
10199
|
-
this.logFn(`[AgentStream] Connected: ${adapter.agentName} (${scopeKey})`);
|
|
10200
|
-
}
|
|
10201
|
-
}
|
|
10195
|
+
if (!managed) {
|
|
10196
|
+
await this.connectManagedSession(cdp, parentSessionId, activeSessionId);
|
|
10202
10197
|
}
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10198
|
+
this.discoveryIntervalMsByParent.set(parentSessionId, this.managedBySessionId.has(activeSessionId) ? 3e4 : 1e4);
|
|
10199
|
+
} catch (e) {
|
|
10200
|
+
this.logFn(`[AgentStream] sync error (${parentSessionId}): ${e.message}`);
|
|
10201
|
+
}
|
|
10202
|
+
}
|
|
10203
|
+
/** Collect active extension session state */
|
|
10204
|
+
async collectActiveSession(cdp, parentSessionId) {
|
|
10205
|
+
if (!this.enabled) return null;
|
|
10206
|
+
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
10207
|
+
if (!activeSessionId) return null;
|
|
10208
|
+
let agent = this.managedBySessionId.get(activeSessionId);
|
|
10209
|
+
if (!agent) {
|
|
10210
|
+
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
10211
|
+
}
|
|
10212
|
+
if (!agent) return null;
|
|
10213
|
+
const type = agent.adapter.agentType;
|
|
10214
|
+
const isHidden = agent.lastState?.status === "panel_hidden";
|
|
10215
|
+
const hiddenCacheFresh = isHidden && Date.now() - agent.lastHiddenCheckTime < 3e4;
|
|
10216
|
+
if (hiddenCacheFresh) return agent.lastState;
|
|
10217
|
+
try {
|
|
10218
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10219
|
+
const state = await agent.adapter.readChat(evaluate);
|
|
10220
|
+
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") : ""}`);
|
|
10221
|
+
agent.lastState = state;
|
|
10222
|
+
agent.lastError = null;
|
|
10223
|
+
if (state.status === "panel_hidden") {
|
|
10224
|
+
agent.lastHiddenCheckTime = Date.now();
|
|
10208
10225
|
}
|
|
10209
|
-
|
|
10226
|
+
return state;
|
|
10210
10227
|
} catch (e) {
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
async collectAgentStreams(cdp, scopeKey) {
|
|
10216
|
-
if (!this.enabled) return [];
|
|
10217
|
-
const results = [];
|
|
10218
|
-
const activeAgentType = this.getActiveAgentType(scopeKey);
|
|
10219
|
-
const managed = this.managedByScope.get(scopeKey);
|
|
10220
|
-
if (activeAgentType && managed?.has(activeAgentType)) {
|
|
10221
|
-
const agent = managed.get(activeAgentType);
|
|
10222
|
-
const type = activeAgentType;
|
|
10223
|
-
const isHidden = agent.lastState?.status === "panel_hidden";
|
|
10224
|
-
const hiddenCacheFresh = isHidden && Date.now() - agent.lastHiddenCheckTime < 3e4;
|
|
10225
|
-
if (hiddenCacheFresh) {
|
|
10226
|
-
results.push(agent.lastState);
|
|
10227
|
-
} else {
|
|
10228
|
+
const errorMsg = e?.message || String(e);
|
|
10229
|
+
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
10230
|
+
agent.lastError = errorMsg;
|
|
10231
|
+
if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
|
|
10228
10232
|
try {
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
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") : ""}`);
|
|
10232
|
-
agent.lastState = state;
|
|
10233
|
-
agent.lastError = null;
|
|
10234
|
-
if (state.status === "panel_hidden") {
|
|
10235
|
-
agent.lastHiddenCheckTime = Date.now();
|
|
10236
|
-
}
|
|
10237
|
-
results.push(state);
|
|
10238
|
-
} catch (e) {
|
|
10239
|
-
const errorMsg = e?.message || String(e);
|
|
10240
|
-
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
10241
|
-
agent.lastError = errorMsg;
|
|
10242
|
-
results.push({
|
|
10243
|
-
agentType: type,
|
|
10244
|
-
agentName: agent.adapter.agentName,
|
|
10245
|
-
extensionId: agent.adapter.extensionId,
|
|
10246
|
-
status: "disconnected",
|
|
10247
|
-
messages: agent.lastState?.messages || [],
|
|
10248
|
-
inputContent: ""
|
|
10249
|
-
});
|
|
10250
|
-
if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
|
|
10251
|
-
try {
|
|
10252
|
-
await cdp.detachAgent(agent.sessionId);
|
|
10253
|
-
} catch {
|
|
10254
|
-
}
|
|
10255
|
-
managed.delete(type);
|
|
10256
|
-
this.lastDiscoveryTimeByScope.set(scopeKey, 0);
|
|
10257
|
-
}
|
|
10233
|
+
await cdp.detachAgent(agent.cdpSessionId);
|
|
10234
|
+
} catch {
|
|
10258
10235
|
}
|
|
10236
|
+
this.managedBySessionId.delete(activeSessionId);
|
|
10237
|
+
this.lastDiscoveryTimeByParent.set(parentSessionId, 0);
|
|
10259
10238
|
}
|
|
10239
|
+
return {
|
|
10240
|
+
agentType: type,
|
|
10241
|
+
agentName: agent.adapter.agentName,
|
|
10242
|
+
extensionId: agent.adapter.extensionId,
|
|
10243
|
+
status: "disconnected",
|
|
10244
|
+
messages: agent.lastState?.messages || [],
|
|
10245
|
+
inputContent: ""
|
|
10246
|
+
};
|
|
10260
10247
|
}
|
|
10261
|
-
return results;
|
|
10262
10248
|
}
|
|
10263
|
-
async
|
|
10264
|
-
await this.
|
|
10265
|
-
const
|
|
10249
|
+
async sendToSession(cdp, sessionId, text) {
|
|
10250
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
10251
|
+
const target = this.getSessionTarget(sessionId);
|
|
10252
|
+
if (!target?.parentSessionId) return false;
|
|
10253
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10254
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10255
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10266
10256
|
if (!agent) return false;
|
|
10267
10257
|
try {
|
|
10268
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10258
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10269
10259
|
await agent.adapter.sendMessage(evaluate, text);
|
|
10270
10260
|
return true;
|
|
10271
10261
|
} catch (e) {
|
|
10272
|
-
this.logFn(`[AgentStream]
|
|
10262
|
+
this.logFn(`[AgentStream] sendToSession(${sessionId}) error: ${e.message}`);
|
|
10273
10263
|
return false;
|
|
10274
10264
|
}
|
|
10275
10265
|
}
|
|
10276
|
-
async
|
|
10277
|
-
await this.
|
|
10278
|
-
const
|
|
10266
|
+
async resolveSessionAction(cdp, sessionId, action) {
|
|
10267
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
10268
|
+
const target = this.getSessionTarget(sessionId);
|
|
10269
|
+
if (!target?.parentSessionId) return false;
|
|
10270
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10271
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10272
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10279
10273
|
if (!agent) return false;
|
|
10280
10274
|
try {
|
|
10281
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10275
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10282
10276
|
return await agent.adapter.resolveAction(evaluate, action);
|
|
10283
10277
|
} catch (e) {
|
|
10284
|
-
this.logFn(`[AgentStream] resolveAction(${
|
|
10278
|
+
this.logFn(`[AgentStream] resolveAction(${sessionId}) error: ${e.message}`);
|
|
10285
10279
|
return false;
|
|
10286
10280
|
}
|
|
10287
10281
|
}
|
|
10288
|
-
async
|
|
10289
|
-
await this.
|
|
10290
|
-
const
|
|
10282
|
+
async newSession(cdp, sessionId) {
|
|
10283
|
+
await this.ensureSessionPanelOpen(sessionId);
|
|
10284
|
+
const target = this.getSessionTarget(sessionId);
|
|
10285
|
+
if (!target?.parentSessionId) return false;
|
|
10286
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10287
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10288
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10291
10289
|
if (!agent) return false;
|
|
10292
10290
|
try {
|
|
10293
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10291
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10294
10292
|
await agent.adapter.newSession(evaluate);
|
|
10295
10293
|
return true;
|
|
10296
10294
|
} catch (e) {
|
|
10297
|
-
this.logFn(`[AgentStream] newSession(${
|
|
10295
|
+
this.logFn(`[AgentStream] newSession(${sessionId}) error: ${e.message}`);
|
|
10298
10296
|
return false;
|
|
10299
10297
|
}
|
|
10300
10298
|
}
|
|
10301
|
-
async
|
|
10302
|
-
|
|
10303
|
-
if (!
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
agent = this.getManagedAgent(agentType, scopeKey);
|
|
10308
|
-
}
|
|
10299
|
+
async listSessionChats(cdp, sessionId) {
|
|
10300
|
+
const target = this.getSessionTarget(sessionId);
|
|
10301
|
+
if (!target?.parentSessionId) return [];
|
|
10302
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10303
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10304
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10309
10305
|
if (!agent || typeof agent.adapter.listChats !== "function") return [];
|
|
10310
10306
|
try {
|
|
10311
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10307
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10312
10308
|
return await agent.adapter.listChats(evaluate);
|
|
10313
10309
|
} catch (e) {
|
|
10314
|
-
this.logFn(`[AgentStream] listChats(${
|
|
10310
|
+
this.logFn(`[AgentStream] listChats(${sessionId}) error: ${e.message}`);
|
|
10315
10311
|
return [];
|
|
10316
10312
|
}
|
|
10317
10313
|
}
|
|
10318
|
-
async
|
|
10319
|
-
|
|
10320
|
-
if (!
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
agent = this.getManagedAgent(agentType, scopeKey);
|
|
10325
|
-
}
|
|
10314
|
+
async switchConversation(cdp, sessionId, conversationId) {
|
|
10315
|
+
const target = this.getSessionTarget(sessionId);
|
|
10316
|
+
if (!target?.parentSessionId) return false;
|
|
10317
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10318
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10319
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10326
10320
|
if (!agent || typeof agent.adapter.switchSession !== "function") return false;
|
|
10327
10321
|
try {
|
|
10328
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10329
|
-
return await agent.adapter.switchSession(evaluate,
|
|
10322
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10323
|
+
return await agent.adapter.switchSession(evaluate, conversationId);
|
|
10330
10324
|
} catch (e) {
|
|
10331
|
-
this.logFn(`[AgentStream] switchSession(${
|
|
10325
|
+
this.logFn(`[AgentStream] switchSession(${sessionId}) error: ${e.message}`);
|
|
10332
10326
|
return false;
|
|
10333
10327
|
}
|
|
10334
10328
|
}
|
|
10335
|
-
async
|
|
10336
|
-
const
|
|
10329
|
+
async focusSession(cdp, sessionId) {
|
|
10330
|
+
const target = this.getSessionTarget(sessionId);
|
|
10331
|
+
if (!target?.parentSessionId) return false;
|
|
10332
|
+
await this.setActiveSession(cdp, target.parentSessionId, sessionId);
|
|
10333
|
+
await this.syncActiveSession(cdp, target.parentSessionId);
|
|
10334
|
+
const agent = this.managedBySessionId.get(sessionId);
|
|
10337
10335
|
if (!agent || typeof agent.adapter.focusEditor !== "function") return false;
|
|
10338
10336
|
try {
|
|
10339
|
-
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.
|
|
10337
|
+
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
10340
10338
|
await agent.adapter.focusEditor(evaluate);
|
|
10341
10339
|
return true;
|
|
10342
10340
|
} catch (e) {
|
|
10343
|
-
this.logFn(`[AgentStream] focusEditor(${
|
|
10341
|
+
this.logFn(`[AgentStream] focusEditor(${sessionId}) error: ${e.message}`);
|
|
10344
10342
|
return false;
|
|
10345
10343
|
}
|
|
10346
10344
|
}
|
|
10347
|
-
|
|
10348
|
-
if (
|
|
10349
|
-
|
|
10345
|
+
getConnectedSessions(parentSessionId) {
|
|
10346
|
+
if (parentSessionId) {
|
|
10347
|
+
return [...this.managedBySessionId.values()].filter((entry) => entry.parentSessionId === parentSessionId).map((entry) => entry.runtimeSessionId);
|
|
10348
|
+
}
|
|
10349
|
+
return [...this.managedBySessionId.keys()];
|
|
10350
10350
|
}
|
|
10351
|
-
|
|
10352
|
-
return this.
|
|
10351
|
+
getManagedSession(sessionId) {
|
|
10352
|
+
return this.managedBySessionId.get(sessionId);
|
|
10353
10353
|
}
|
|
10354
10354
|
async dispose(cdpManagers) {
|
|
10355
|
-
for (const
|
|
10356
|
-
const
|
|
10355
|
+
for (const managed of this.managedBySessionId.values()) {
|
|
10356
|
+
const managerKey = this.getSessionTarget(managed.runtimeSessionId)?.cdpManagerKey;
|
|
10357
|
+
const cdp = managerKey ? cdpManagers.get(managerKey) : null;
|
|
10357
10358
|
if (!cdp) continue;
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
} catch {
|
|
10362
|
-
}
|
|
10359
|
+
try {
|
|
10360
|
+
await cdp.detachAgent(managed.cdpSessionId);
|
|
10361
|
+
} catch {
|
|
10363
10362
|
}
|
|
10364
10363
|
}
|
|
10365
|
-
this.
|
|
10366
|
-
this.
|
|
10367
|
-
this.
|
|
10368
|
-
this.
|
|
10364
|
+
this.managedBySessionId.clear();
|
|
10365
|
+
this.activeSessionIdByParent.clear();
|
|
10366
|
+
this.lastDiscoveryTimeByParent.clear();
|
|
10367
|
+
this.discoveryIntervalMsByParent.clear();
|
|
10368
|
+
}
|
|
10369
|
+
resolveSessionForAgent(parentSessionId, agentType) {
|
|
10370
|
+
return this.resolveSessionIdForTarget(parentSessionId, agentType);
|
|
10369
10371
|
}
|
|
10370
10372
|
};
|
|
10371
10373
|
|
|
@@ -10382,8 +10384,8 @@ var AgentStreamPoller = class {
|
|
|
10382
10384
|
return null;
|
|
10383
10385
|
}
|
|
10384
10386
|
/** Reset active IDE tracking (e.g., when IDE is stopped) */
|
|
10385
|
-
resetActiveIde(
|
|
10386
|
-
this.deps.agentStreamManager.
|
|
10387
|
+
resetActiveIde(parentSessionId) {
|
|
10388
|
+
this.deps.agentStreamManager.resetParentSession(parentSessionId);
|
|
10387
10389
|
}
|
|
10388
10390
|
/** Start polling (idempotent — ignored if already started) */
|
|
10389
10391
|
start(intervalMs = 5e3) {
|
|
@@ -10405,12 +10407,14 @@ var AgentStreamPoller = class {
|
|
|
10405
10407
|
agentStreamManager,
|
|
10406
10408
|
providerLoader,
|
|
10407
10409
|
instanceManager,
|
|
10408
|
-
cdpManagers
|
|
10410
|
+
cdpManagers,
|
|
10411
|
+
sessionRegistry
|
|
10409
10412
|
} = this.deps;
|
|
10410
10413
|
if (!agentStreamManager || cdpManagers.size === 0) return;
|
|
10411
10414
|
for (const [ideType, cdp] of cdpManagers) {
|
|
10412
10415
|
registerExtensionProviders(providerLoader, cdp, ideType);
|
|
10413
10416
|
const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
|
|
10417
|
+
const parentSessionId = ideInstance?.getInstanceId?.();
|
|
10414
10418
|
if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
|
|
10415
10419
|
const currentExtTypes = new Set(ideInstance.getExtensionTypes());
|
|
10416
10420
|
const enabledExtTypes = new Set(
|
|
@@ -10418,6 +10422,10 @@ var AgentStreamPoller = class {
|
|
|
10418
10422
|
);
|
|
10419
10423
|
for (const extType of currentExtTypes) {
|
|
10420
10424
|
if (!enabledExtTypes.has(extType)) {
|
|
10425
|
+
const extInstance = ideInstance.getExtension?.(extType);
|
|
10426
|
+
if (extInstance?.getInstanceId) {
|
|
10427
|
+
sessionRegistry.unregister(extInstance.getInstanceId());
|
|
10428
|
+
}
|
|
10421
10429
|
ideInstance.removeExtension(extType);
|
|
10422
10430
|
LOG.info("AgentStream", `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
10423
10431
|
}
|
|
@@ -10428,46 +10436,61 @@ var AgentStreamPoller = class {
|
|
|
10428
10436
|
if (extProvider) {
|
|
10429
10437
|
const extSettings = providerLoader.getSettings(extType);
|
|
10430
10438
|
ideInstance.addExtension(extProvider, extSettings);
|
|
10439
|
+
const extInstance = ideInstance.getExtension?.(extType);
|
|
10440
|
+
if (parentSessionId && extInstance?.getInstanceId) {
|
|
10441
|
+
sessionRegistry.register({
|
|
10442
|
+
sessionId: extInstance.getInstanceId(),
|
|
10443
|
+
parentSessionId,
|
|
10444
|
+
providerType: extType,
|
|
10445
|
+
providerCategory: "extension",
|
|
10446
|
+
transport: "cdp-webview",
|
|
10447
|
+
cdpManagerKey: ideType,
|
|
10448
|
+
instanceKey: `ide:${ideType}`
|
|
10449
|
+
});
|
|
10450
|
+
}
|
|
10431
10451
|
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
10432
10452
|
}
|
|
10433
10453
|
}
|
|
10434
10454
|
}
|
|
10435
10455
|
}
|
|
10436
|
-
const
|
|
10437
|
-
if (
|
|
10438
|
-
const
|
|
10439
|
-
|
|
10440
|
-
)
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
await agentStreamManager.switchActiveAgent(cdp, ideType, null);
|
|
10456
|
+
const activeSessionId = parentSessionId ? agentStreamManager.getActiveSessionId(parentSessionId) : null;
|
|
10457
|
+
if (activeSessionId) {
|
|
10458
|
+
const activeTarget = sessionRegistry.get(activeSessionId);
|
|
10459
|
+
const enabledExtTypes = new Set(providerLoader.getEnabledExtensionProviders(ideType).map((p) => p.type));
|
|
10460
|
+
if (!activeTarget || !enabledExtTypes.has(activeTarget.providerType)) {
|
|
10461
|
+
LOG.info("AgentStream", `Active agent ${activeTarget?.providerType || activeSessionId} was disabled for ${ideType} \u2014 detaching`);
|
|
10462
|
+
await agentStreamManager.setActiveSession(cdp, parentSessionId, null);
|
|
10444
10463
|
this.deps.onStreamsUpdated?.(ideType, []);
|
|
10445
10464
|
}
|
|
10446
10465
|
}
|
|
10447
10466
|
if (!cdp.isConnected) {
|
|
10448
|
-
if (
|
|
10449
|
-
agentStreamManager.
|
|
10467
|
+
if (parentSessionId && activeSessionId) {
|
|
10468
|
+
agentStreamManager.resetParentSession(parentSessionId);
|
|
10450
10469
|
this.deps.onStreamsUpdated?.(ideType, []);
|
|
10451
10470
|
}
|
|
10452
10471
|
continue;
|
|
10453
10472
|
}
|
|
10454
|
-
let
|
|
10455
|
-
if (!
|
|
10473
|
+
let resolvedActiveSessionId = activeSessionId;
|
|
10474
|
+
if (!resolvedActiveSessionId && parentSessionId) {
|
|
10456
10475
|
try {
|
|
10457
10476
|
const discovered = await cdp.discoverAgentWebviews();
|
|
10458
|
-
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10477
|
+
for (const target of discovered) {
|
|
10478
|
+
const sessionId = agentStreamManager.resolveSessionForAgent(parentSessionId, target.agentType);
|
|
10479
|
+
if (sessionId) {
|
|
10480
|
+
resolvedActiveSessionId = sessionId;
|
|
10481
|
+
await agentStreamManager.setActiveSession(cdp, parentSessionId, sessionId);
|
|
10482
|
+
LOG.info("AgentStream", `Auto-activated: ${target.agentType} (${ideType})`);
|
|
10483
|
+
break;
|
|
10484
|
+
}
|
|
10462
10485
|
}
|
|
10463
10486
|
} catch {
|
|
10464
10487
|
}
|
|
10465
10488
|
}
|
|
10466
|
-
if (!
|
|
10489
|
+
if (!resolvedActiveSessionId || !parentSessionId) continue;
|
|
10467
10490
|
try {
|
|
10468
|
-
await agentStreamManager.
|
|
10469
|
-
const
|
|
10470
|
-
this.deps.onStreamsUpdated?.(ideType,
|
|
10491
|
+
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
10492
|
+
const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
10493
|
+
this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
|
|
10471
10494
|
} catch {
|
|
10472
10495
|
}
|
|
10473
10496
|
}
|
|
@@ -10556,6 +10579,7 @@ var ProviderInstanceManager = class {
|
|
|
10556
10579
|
...event,
|
|
10557
10580
|
providerType: instance.type,
|
|
10558
10581
|
instanceId: state.instanceId,
|
|
10582
|
+
targetSessionId: state.instanceId,
|
|
10559
10583
|
providerCategory: state.category
|
|
10560
10584
|
});
|
|
10561
10585
|
}
|
|
@@ -14366,6 +14390,63 @@ function launchIDE(ide, workspacePath) {
|
|
|
14366
14390
|
}
|
|
14367
14391
|
}
|
|
14368
14392
|
|
|
14393
|
+
// src/sessions/registry.ts
|
|
14394
|
+
var SessionRegistry = class {
|
|
14395
|
+
bySessionId = /* @__PURE__ */ new Map();
|
|
14396
|
+
byManagerKey = /* @__PURE__ */ new Map();
|
|
14397
|
+
byInstanceKey = /* @__PURE__ */ new Map();
|
|
14398
|
+
byParentSessionId = /* @__PURE__ */ new Map();
|
|
14399
|
+
register(target) {
|
|
14400
|
+
this.unregister(target.sessionId);
|
|
14401
|
+
this.bySessionId.set(target.sessionId, target);
|
|
14402
|
+
if (target.cdpManagerKey) this.addIndex(this.byManagerKey, target.cdpManagerKey, target.sessionId);
|
|
14403
|
+
if (target.instanceKey) this.addIndex(this.byInstanceKey, target.instanceKey, target.sessionId);
|
|
14404
|
+
if (target.parentSessionId) this.addIndex(this.byParentSessionId, target.parentSessionId, target.sessionId);
|
|
14405
|
+
}
|
|
14406
|
+
get(sessionId) {
|
|
14407
|
+
if (!sessionId) return void 0;
|
|
14408
|
+
return this.bySessionId.get(sessionId);
|
|
14409
|
+
}
|
|
14410
|
+
unregister(sessionId) {
|
|
14411
|
+
if (!sessionId) return;
|
|
14412
|
+
const target = this.bySessionId.get(sessionId);
|
|
14413
|
+
if (!target) return;
|
|
14414
|
+
this.bySessionId.delete(sessionId);
|
|
14415
|
+
if (target.cdpManagerKey) this.removeIndex(this.byManagerKey, target.cdpManagerKey, sessionId);
|
|
14416
|
+
if (target.instanceKey) this.removeIndex(this.byInstanceKey, target.instanceKey, sessionId);
|
|
14417
|
+
if (target.parentSessionId) this.removeIndex(this.byParentSessionId, target.parentSessionId, sessionId);
|
|
14418
|
+
}
|
|
14419
|
+
unregisterByManagerKey(managerKey) {
|
|
14420
|
+
for (const sessionId of [...this.byManagerKey.get(managerKey) || []]) {
|
|
14421
|
+
this.unregister(sessionId);
|
|
14422
|
+
}
|
|
14423
|
+
}
|
|
14424
|
+
unregisterByInstanceKey(instanceKey) {
|
|
14425
|
+
for (const sessionId of [...this.byInstanceKey.get(instanceKey) || []]) {
|
|
14426
|
+
this.unregister(sessionId);
|
|
14427
|
+
}
|
|
14428
|
+
}
|
|
14429
|
+
listChildren(parentSessionId) {
|
|
14430
|
+
const ids = this.byParentSessionId.get(parentSessionId);
|
|
14431
|
+
if (!ids) return [];
|
|
14432
|
+
return [...ids].map((id) => this.bySessionId.get(id)).filter(Boolean);
|
|
14433
|
+
}
|
|
14434
|
+
addIndex(index, key, sessionId) {
|
|
14435
|
+
let set = index.get(key);
|
|
14436
|
+
if (!set) {
|
|
14437
|
+
set = /* @__PURE__ */ new Set();
|
|
14438
|
+
index.set(key, set);
|
|
14439
|
+
}
|
|
14440
|
+
set.add(sessionId);
|
|
14441
|
+
}
|
|
14442
|
+
removeIndex(index, key, sessionId) {
|
|
14443
|
+
const set = index.get(key);
|
|
14444
|
+
if (!set) return;
|
|
14445
|
+
set.delete(sessionId);
|
|
14446
|
+
if (set.size === 0) index.delete(key);
|
|
14447
|
+
}
|
|
14448
|
+
};
|
|
14449
|
+
|
|
14369
14450
|
// src/boot/daemon-lifecycle.ts
|
|
14370
14451
|
init_logger();
|
|
14371
14452
|
init_config();
|
|
@@ -14405,11 +14486,14 @@ async function initDaemonComponents(config) {
|
|
|
14405
14486
|
});
|
|
14406
14487
|
const instanceManager = new ProviderInstanceManager();
|
|
14407
14488
|
const cdpManagers = /* @__PURE__ */ new Map();
|
|
14408
|
-
const
|
|
14489
|
+
const sessionRegistry = new SessionRegistry();
|
|
14409
14490
|
const detectedIdesRef = { value: [] };
|
|
14491
|
+
let agentStreamManager = null;
|
|
14492
|
+
let poller = null;
|
|
14410
14493
|
const cliManager = new DaemonCliManager({
|
|
14411
14494
|
...config.cliManagerDeps,
|
|
14412
|
-
getInstanceManager: () => instanceManager
|
|
14495
|
+
getInstanceManager: () => instanceManager,
|
|
14496
|
+
getSessionRegistry: () => sessionRegistry
|
|
14413
14497
|
}, providerLoader);
|
|
14414
14498
|
LOG.info("Init", "Detecting IDEs...");
|
|
14415
14499
|
detectedIdesRef.value = await detectIDEs();
|
|
@@ -14419,7 +14503,7 @@ async function initDaemonComponents(config) {
|
|
|
14419
14503
|
providerLoader,
|
|
14420
14504
|
instanceManager,
|
|
14421
14505
|
cdpManagers,
|
|
14422
|
-
|
|
14506
|
+
sessionRegistry
|
|
14423
14507
|
};
|
|
14424
14508
|
const cdpInitializer = new DaemonCdpInitializer({
|
|
14425
14509
|
providerLoader,
|
|
@@ -14428,6 +14512,19 @@ async function initDaemonComponents(config) {
|
|
|
14428
14512
|
onConnected: async (ideType, manager, managerKey) => {
|
|
14429
14513
|
await setupIdeInstance(cdpSetupContext, { ideType, manager, managerKey });
|
|
14430
14514
|
await config.onCdpManagerSetup?.(ideType, manager, managerKey);
|
|
14515
|
+
},
|
|
14516
|
+
onDisconnected: async (_ideType, _manager, managerKey) => {
|
|
14517
|
+
sessionRegistry.unregisterByManagerKey(managerKey);
|
|
14518
|
+
const instanceKey = `ide:${managerKey}`;
|
|
14519
|
+
const ideInstance = instanceManager.getInstance(instanceKey);
|
|
14520
|
+
if (ideInstance) {
|
|
14521
|
+
instanceManager.removeInstance(instanceKey);
|
|
14522
|
+
LOG.info("CDP", `Instance removed after disconnect: ${instanceKey}`);
|
|
14523
|
+
}
|
|
14524
|
+
if (ideInstance?.getInstanceId) {
|
|
14525
|
+
agentStreamManager?.resetParentSession(ideInstance.getInstanceId());
|
|
14526
|
+
}
|
|
14527
|
+
config.onStatusChange?.();
|
|
14431
14528
|
}
|
|
14432
14529
|
});
|
|
14433
14530
|
await cdpInitializer.connectAll(detectedIdesRef.value);
|
|
@@ -14439,14 +14536,14 @@ async function initDaemonComponents(config) {
|
|
|
14439
14536
|
adapters: cliManager.adapters,
|
|
14440
14537
|
providerLoader,
|
|
14441
14538
|
instanceManager,
|
|
14442
|
-
|
|
14539
|
+
sessionRegistry
|
|
14443
14540
|
});
|
|
14444
|
-
|
|
14541
|
+
agentStreamManager = new DaemonAgentStreamManager(
|
|
14445
14542
|
LOG.forComponent("AgentStream").asLogFn(),
|
|
14446
|
-
providerLoader
|
|
14543
|
+
providerLoader,
|
|
14544
|
+
sessionRegistry
|
|
14447
14545
|
);
|
|
14448
14546
|
commandHandler.setAgentStreamManager(agentStreamManager);
|
|
14449
|
-
let poller;
|
|
14450
14547
|
const router = new DaemonCommandRouter({
|
|
14451
14548
|
commandHandler,
|
|
14452
14549
|
cliManager,
|
|
@@ -14454,7 +14551,7 @@ async function initDaemonComponents(config) {
|
|
|
14454
14551
|
providerLoader,
|
|
14455
14552
|
instanceManager,
|
|
14456
14553
|
detectedIdes: detectedIdesRef,
|
|
14457
|
-
|
|
14554
|
+
sessionRegistry,
|
|
14458
14555
|
onCdpManagerCreated: async (ideType, manager) => {
|
|
14459
14556
|
await setupIdeInstance(cdpSetupContext, { ideType, manager });
|
|
14460
14557
|
await config.onCdpManagerSetup?.(ideType, manager, ideType);
|
|
@@ -14469,6 +14566,7 @@ async function initDaemonComponents(config) {
|
|
|
14469
14566
|
providerLoader,
|
|
14470
14567
|
instanceManager,
|
|
14471
14568
|
cdpManagers,
|
|
14569
|
+
sessionRegistry,
|
|
14472
14570
|
onStreamsUpdated: config.onStreamsUpdated
|
|
14473
14571
|
});
|
|
14474
14572
|
poller.start();
|
|
@@ -14483,7 +14581,7 @@ async function initDaemonComponents(config) {
|
|
|
14483
14581
|
poller,
|
|
14484
14582
|
cdpInitializer,
|
|
14485
14583
|
cdpManagers,
|
|
14486
|
-
|
|
14584
|
+
sessionRegistry,
|
|
14487
14585
|
detectedIdes: detectedIdesRef
|
|
14488
14586
|
};
|
|
14489
14587
|
}
|
|
@@ -14556,10 +14654,7 @@ export {
|
|
|
14556
14654
|
ProviderLoader,
|
|
14557
14655
|
VersionArchive,
|
|
14558
14656
|
addCliHistory,
|
|
14559
|
-
|
|
14560
|
-
buildManagedAcps,
|
|
14561
|
-
buildManagedClis,
|
|
14562
|
-
buildManagedIdes,
|
|
14657
|
+
buildSessionEntries,
|
|
14563
14658
|
buildStatusSnapshot,
|
|
14564
14659
|
connectCdpManager,
|
|
14565
14660
|
detectAllVersions,
|