adhdev 0.5.2 → 0.5.3
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/cli-entrypoint.js +1737 -1622
- package/dist/cli-entrypoint.js.map +1 -1
- package/dist/index.js +1728 -1613
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16514,7 +16514,7 @@ var require_dist = __commonJS({
|
|
|
16514
16514
|
DaemonStatusReporter: () => DaemonStatusReporter2,
|
|
16515
16515
|
DevServer: () => DevServer2,
|
|
16516
16516
|
IdeProviderInstance: () => IdeProviderInstance,
|
|
16517
|
-
LOG: () =>
|
|
16517
|
+
LOG: () => LOG5,
|
|
16518
16518
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
16519
16519
|
ProviderInstanceManager: () => ProviderInstanceManager,
|
|
16520
16520
|
ProviderLoader: () => ProviderLoader2,
|
|
@@ -16818,7 +16818,7 @@ var require_dist = __commonJS({
|
|
|
16818
16818
|
origConsoleLog(line);
|
|
16819
16819
|
}
|
|
16820
16820
|
}
|
|
16821
|
-
var
|
|
16821
|
+
var LOG5 = {
|
|
16822
16822
|
debug: (category, msg) => daemonLog(category, msg, "debug"),
|
|
16823
16823
|
info: (category, msg) => daemonLog(category, msg, "info"),
|
|
16824
16824
|
warn: (category, msg) => daemonLog(category, msg, "warn"),
|
|
@@ -16932,7 +16932,7 @@ var require_dist = __commonJS({
|
|
|
16932
16932
|
this._targetId = targetId || null;
|
|
16933
16933
|
this._targetFilter = targetFilter || {};
|
|
16934
16934
|
this.logFn = logFn || ((msg) => {
|
|
16935
|
-
|
|
16935
|
+
LOG5.info("CDP", msg);
|
|
16936
16936
|
});
|
|
16937
16937
|
}
|
|
16938
16938
|
/** Set target filter (can be updated after construction) */
|
|
@@ -17705,7 +17705,7 @@ var require_dist = __commonJS({
|
|
|
17705
17705
|
} catch {
|
|
17706
17706
|
}
|
|
17707
17707
|
const result = await this.sendInternal("Page.captureScreenshot", {
|
|
17708
|
-
format: "
|
|
17708
|
+
format: "webp",
|
|
17709
17709
|
quality,
|
|
17710
17710
|
...clip ? { clip } : {},
|
|
17711
17711
|
optimizeForSpeed: true,
|
|
@@ -18402,14 +18402,14 @@ var require_dist = __commonJS({
|
|
|
18402
18402
|
try {
|
|
18403
18403
|
await ext.onTick();
|
|
18404
18404
|
} catch (e) {
|
|
18405
|
-
|
|
18405
|
+
LOG5.warn("IdeInstance", `[IdeInstance:${this.type}] Extension ${id} tick error: ${e?.message}`);
|
|
18406
18406
|
}
|
|
18407
18407
|
}
|
|
18408
18408
|
this.tickErrorCount = 0;
|
|
18409
18409
|
} catch (e) {
|
|
18410
18410
|
this.tickErrorCount++;
|
|
18411
18411
|
if (this.tickErrorCount <= 3 || this.tickErrorCount % 10 === 0) {
|
|
18412
|
-
|
|
18412
|
+
LOG5.warn("IdeInstance", `[IdeInstance:${this.type}] onTick error (${this.tickErrorCount}): ${e?.message || e}`);
|
|
18413
18413
|
}
|
|
18414
18414
|
} finally {
|
|
18415
18415
|
this.tickBusy = false;
|
|
@@ -18486,7 +18486,7 @@ var require_dist = __commonJS({
|
|
|
18486
18486
|
});
|
|
18487
18487
|
ext.onEvent("extension_connected", { ideType: this.type });
|
|
18488
18488
|
this.extensions.set(provider.type, ext);
|
|
18489
|
-
|
|
18489
|
+
LOG5.info("IdeInstance", `[IdeInstance:${this.type}] Extension added: ${provider.type}`);
|
|
18490
18490
|
}
|
|
18491
18491
|
/** Extension Instance remove */
|
|
18492
18492
|
removeExtension(type) {
|
|
@@ -18596,7 +18596,7 @@ var require_dist = __commonJS({
|
|
|
18596
18596
|
const msg = e?.message || String(e);
|
|
18597
18597
|
if (msg.includes("Timeout") || msg.includes("timeout") || msg.includes("Target closed")) {
|
|
18598
18598
|
} else {
|
|
18599
|
-
|
|
18599
|
+
LOG5.warn("IdeInstance", `[IdeInstance:${this.type}] readChat internal error: ${msg}`);
|
|
18600
18600
|
}
|
|
18601
18601
|
}
|
|
18602
18602
|
}
|
|
@@ -18791,7 +18791,7 @@ var require_dist = __commonJS({
|
|
|
18791
18791
|
// ── Internal ────────────────────────────
|
|
18792
18792
|
getLogFn(ideType) {
|
|
18793
18793
|
if (this.opts.logFn) return this.opts.logFn(ideType);
|
|
18794
|
-
return (msg) =>
|
|
18794
|
+
return (msg) => LOG5.info(`CDP:${ideType}`, msg);
|
|
18795
18795
|
}
|
|
18796
18796
|
/**
|
|
18797
18797
|
* Single-window connection (standalone mode).
|
|
@@ -18810,7 +18810,7 @@ var require_dist = __commonJS({
|
|
|
18810
18810
|
if (!manager) return;
|
|
18811
18811
|
registerExtensionProviders(this.ctx.providerLoader, manager, ide);
|
|
18812
18812
|
this.ctx.cdpManagers.set(ide, manager);
|
|
18813
|
-
|
|
18813
|
+
LOG5.info("CDP", `Connected: ${ide} (port ${port})`);
|
|
18814
18814
|
await setupIdeInstance(this.ctx, { ideType: ide, manager });
|
|
18815
18815
|
this.opts.onConnected?.(ide, ide, manager);
|
|
18816
18816
|
}
|
|
@@ -18843,7 +18843,7 @@ var require_dist = __commonJS({
|
|
|
18843
18843
|
);
|
|
18844
18844
|
if (!manager) continue;
|
|
18845
18845
|
this.ctx.cdpManagers.set(managerKey, manager);
|
|
18846
|
-
|
|
18846
|
+
LOG5.info("CDP", `Connected: ${managerKey} (port ${port}, page "${target.title}")`);
|
|
18847
18847
|
await setupIdeInstance(this.ctx, {
|
|
18848
18848
|
ideType: ide,
|
|
18849
18849
|
manager,
|
|
@@ -18885,9 +18885,9 @@ var require_dist = __commonJS({
|
|
|
18885
18885
|
await this.connectIdePort(port, ide);
|
|
18886
18886
|
}
|
|
18887
18887
|
if (cdpManagers.size > 0) {
|
|
18888
|
-
|
|
18888
|
+
LOG5.info("CDP", `${cdpManagers.size} IDE(s) connected: ${[...cdpManagers.entries()].map(([k, m]) => `${k}:${m.getPort()}`).join(", ")}`);
|
|
18889
18889
|
} else {
|
|
18890
|
-
|
|
18890
|
+
LOG5.warn("CDP", `No IDEs connected \u2014 tried: ${filtered.map((p) => `${p.ide}:${p.port}`).join(", ")}`);
|
|
18891
18891
|
}
|
|
18892
18892
|
}
|
|
18893
18893
|
// ─── Per-port connection (multi-window aware) ───
|
|
@@ -18903,7 +18903,7 @@ var require_dist = __commonJS({
|
|
|
18903
18903
|
const provider = providerLoader.getMeta(ide);
|
|
18904
18904
|
const manager = new DaemonCdpManager2(
|
|
18905
18905
|
port,
|
|
18906
|
-
|
|
18906
|
+
LOG5.forComponent(`CDP:${ide}`).asLogFn(),
|
|
18907
18907
|
void 0,
|
|
18908
18908
|
provider?.targetFilter
|
|
18909
18909
|
);
|
|
@@ -18911,7 +18911,7 @@ var require_dist = __commonJS({
|
|
|
18911
18911
|
if (connected) {
|
|
18912
18912
|
registerExtensionProviders(providerLoader, manager, ide);
|
|
18913
18913
|
cdpManagers.set(ide, manager);
|
|
18914
|
-
|
|
18914
|
+
LOG5.info("CDP", `Connected: ${ide} (port ${port})`);
|
|
18915
18915
|
await this.config.onConnected?.(ide, manager, ide);
|
|
18916
18916
|
}
|
|
18917
18917
|
return;
|
|
@@ -18929,7 +18929,7 @@ var require_dist = __commonJS({
|
|
|
18929
18929
|
const provider = providerLoader.getMeta(ide);
|
|
18930
18930
|
const manager = new DaemonCdpManager2(
|
|
18931
18931
|
port,
|
|
18932
|
-
|
|
18932
|
+
LOG5.forComponent(`CDP:${managerKey}`).asLogFn(),
|
|
18933
18933
|
target.id,
|
|
18934
18934
|
provider?.targetFilter
|
|
18935
18935
|
);
|
|
@@ -18937,7 +18937,7 @@ var require_dist = __commonJS({
|
|
|
18937
18937
|
if (connected) {
|
|
18938
18938
|
registerExtensionProviders(providerLoader, manager, ide);
|
|
18939
18939
|
cdpManagers.set(managerKey, manager);
|
|
18940
|
-
|
|
18940
|
+
LOG5.info("CDP", `Connected: ${managerKey} (port ${port}${targets.length > 1 ? `, page "${target.title}"` : ""})`);
|
|
18941
18941
|
await this.config.onConnected?.(ide, manager, managerKey);
|
|
18942
18942
|
}
|
|
18943
18943
|
}
|
|
@@ -18987,1475 +18987,1438 @@ var require_dist = __commonJS({
|
|
|
18987
18987
|
}
|
|
18988
18988
|
}
|
|
18989
18989
|
};
|
|
18990
|
-
var fs32 = __toESM2(require("fs"));
|
|
18991
|
-
var path32 = __toESM2(require("path"));
|
|
18992
|
-
var os4 = __toESM2(require("os"));
|
|
18993
18990
|
init_config();
|
|
18994
|
-
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
if (!key) {
|
|
19004
|
-
return null;
|
|
19005
|
-
}
|
|
19006
|
-
const m = this.ctx.cdpManagers.get(key.toLowerCase());
|
|
19007
|
-
if (m?.isConnected) return m;
|
|
19008
|
-
return null;
|
|
19009
|
-
}
|
|
19010
|
-
/** Current IDE type extracted from command args (per-request) */
|
|
19011
|
-
_currentIdeType;
|
|
19012
|
-
/** Current provider type — agentType priority, ideType use */
|
|
19013
|
-
_currentProviderType;
|
|
19014
|
-
historyWriter;
|
|
19015
|
-
/** Extract ideType from _targetInstance
|
|
19016
|
-
* UUID-based: query directly from instanceIdMap
|
|
19017
|
-
* Legacy: composite ID parsing ('doId:ide:uuid' → uuid → map lookup)
|
|
19018
|
-
*/
|
|
19019
|
-
extractIdeType(args) {
|
|
19020
|
-
if (args?._targetInstance) {
|
|
19021
|
-
let raw = args._targetInstance;
|
|
19022
|
-
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
19023
|
-
const cliMatch = raw.match(/:cli:(.+)$/);
|
|
19024
|
-
const acpMatch = raw.match(/:acp:(.+)$/);
|
|
19025
|
-
if (ideMatch) raw = ideMatch[1];
|
|
19026
|
-
else if (cliMatch) raw = cliMatch[1];
|
|
19027
|
-
else if (acpMatch) raw = acpMatch[1];
|
|
19028
|
-
if (this.ctx.instanceIdMap?.has(raw)) {
|
|
19029
|
-
return this.ctx.instanceIdMap.get(raw);
|
|
19030
|
-
}
|
|
19031
|
-
const lastUnderscore = raw.lastIndexOf("_");
|
|
19032
|
-
if (lastUnderscore > 0) return raw.substring(0, lastUnderscore);
|
|
19033
|
-
return raw;
|
|
19034
|
-
}
|
|
19035
|
-
return void 0;
|
|
19036
|
-
}
|
|
19037
|
-
constructor(ctx) {
|
|
19038
|
-
this.ctx = ctx;
|
|
19039
|
-
this.domHandlers = new CdpDomHandlers((ideType) => this.getCdp(ideType));
|
|
19040
|
-
this.historyWriter = new ChatHistoryWriter();
|
|
19041
|
-
}
|
|
19042
|
-
/**
|
|
19043
|
-
* Get provider module — _currentProviderType (agentType priority) use.
|
|
19044
|
-
* Extension: agentType='cline' → provider.type='cline' (category=extension)
|
|
19045
|
-
* CLI: ideType='gemini-cli' → provider.type='gemini-cli' (category=cli)
|
|
19046
|
-
* IDE: ideType='cursor' → provider.type='cursor' (category=ide)
|
|
19047
|
-
*/
|
|
19048
|
-
getProvider(overrideType) {
|
|
19049
|
-
const key = overrideType || this._currentProviderType || this._currentIdeType;
|
|
19050
|
-
if (!key || !this.ctx.providerLoader) return void 0;
|
|
19051
|
-
const result = this.ctx.providerLoader.resolve(key);
|
|
19052
|
-
if (result) return result;
|
|
19053
|
-
const baseType = key.split("_")[0];
|
|
19054
|
-
if (baseType !== key) return this.ctx.providerLoader.resolve(baseType);
|
|
19055
|
-
return void 0;
|
|
19056
|
-
}
|
|
19057
|
-
/** Get a provider script by name from ProviderLoader.
|
|
19058
|
-
* Returns the script string or null. */
|
|
19059
|
-
getProviderScript(scriptName, params, ideType) {
|
|
19060
|
-
const provider = this.getProvider(ideType);
|
|
19061
|
-
if (provider?.scripts) {
|
|
19062
|
-
const fn = provider.scripts[scriptName];
|
|
19063
|
-
if (typeof fn === "function") {
|
|
19064
|
-
const firstVal = params ? Object.values(params)[0] : void 0;
|
|
19065
|
-
const script = firstVal ? fn(firstVal) : fn();
|
|
19066
|
-
if (script) return script;
|
|
19067
|
-
}
|
|
19068
|
-
}
|
|
19069
|
-
return null;
|
|
19070
|
-
}
|
|
19071
|
-
// ─── Category dispatch engine ───────────────────
|
|
19072
|
-
/**
|
|
19073
|
-
* Look up Extension provider webview session ID from AgentStreamManager.
|
|
19074
|
-
* provider.type (e.g. 'cline') → ManagedAgent sessionId
|
|
19075
|
-
*/
|
|
19076
|
-
getExtensionSessionId(provider) {
|
|
19077
|
-
if (provider.category !== "extension" || !this.agentStream) return null;
|
|
19078
|
-
const managed = this.agentStream.getManagedAgent(provider.type);
|
|
19079
|
-
return managed?.sessionId || null;
|
|
19080
|
-
}
|
|
19081
|
-
/**
|
|
19082
|
-
* per-category CDP script execute:
|
|
19083
|
-
* IDE → cdp.evaluate(script) (main window)
|
|
19084
|
-
* Extension → cdp.evaluateInSession(sessionId, script) (webview)
|
|
19085
|
-
* CLI → null (separate handling needed)
|
|
19086
|
-
*/
|
|
19087
|
-
async evaluateProviderScript(scriptName, params, timeout = 3e4) {
|
|
19088
|
-
const provider = this.getProvider();
|
|
19089
|
-
const script = this.getProviderScript(scriptName, params);
|
|
19090
|
-
if (!script) return null;
|
|
19091
|
-
const cdp = this.getCdp();
|
|
19092
|
-
if (!cdp?.isConnected) return null;
|
|
19093
|
-
if (provider?.category === "extension") {
|
|
19094
|
-
let sessionId = this.getExtensionSessionId(provider);
|
|
19095
|
-
if (!sessionId && this.agentStream) {
|
|
19096
|
-
await this.agentStream.switchActiveAgent(cdp, provider.type);
|
|
19097
|
-
await this.agentStream.syncAgentSessions(cdp);
|
|
19098
|
-
sessionId = this.getExtensionSessionId(provider);
|
|
19099
|
-
}
|
|
19100
|
-
if (!sessionId) return null;
|
|
19101
|
-
const result2 = await cdp.evaluateInSession(sessionId, script, timeout);
|
|
19102
|
-
return { result: result2, category: "extension" };
|
|
19103
|
-
}
|
|
19104
|
-
const result = await cdp.evaluate(script, timeout);
|
|
19105
|
-
return { result, category: provider?.category || "ide" };
|
|
18991
|
+
async function handleChatHistory(h, args) {
|
|
18992
|
+
const { agentType, offset, limit, instanceId } = args;
|
|
18993
|
+
try {
|
|
18994
|
+
const provider = h.getProvider(agentType);
|
|
18995
|
+
const agentStr = provider?.type || agentType || h.currentIdeType || "";
|
|
18996
|
+
const result = readChatHistory2(agentStr, offset || 0, limit || 30, instanceId);
|
|
18997
|
+
return { success: true, ...result, agent: agentStr };
|
|
18998
|
+
} catch (e) {
|
|
18999
|
+
return { success: false, error: e.message };
|
|
19106
19000
|
}
|
|
19107
|
-
|
|
19108
|
-
|
|
19109
|
-
|
|
19110
|
-
|
|
19111
|
-
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19001
|
+
}
|
|
19002
|
+
async function handleReadChat(h, args) {
|
|
19003
|
+
const provider = h.getProvider();
|
|
19004
|
+
const _log = (msg) => LOG5.debug("Command", `[read_chat] ${msg}`);
|
|
19005
|
+
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
19006
|
+
const adapter = h.getCliAdapter(provider.type);
|
|
19007
|
+
if (adapter) {
|
|
19008
|
+
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
19009
|
+
const status = adapter.getStatus?.();
|
|
19010
|
+
if (status) {
|
|
19011
|
+
return { success: true, messages: status.messages || [], status: status.status, activeModal: status.activeModal };
|
|
19116
19012
|
}
|
|
19117
19013
|
}
|
|
19118
|
-
return
|
|
19014
|
+
return { success: false, error: `${provider.category} adapter not found` };
|
|
19119
19015
|
}
|
|
19120
|
-
|
|
19121
|
-
this.agentStream = manager;
|
|
19122
|
-
}
|
|
19123
|
-
async handle(cmd, args) {
|
|
19124
|
-
this._currentIdeType = this.extractIdeType(args);
|
|
19125
|
-
this._currentProviderType = args?.agentType || args?.providerType || this._currentIdeType;
|
|
19126
|
-
if (!this._currentIdeType && !this._currentProviderType) {
|
|
19127
|
-
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
19128
|
-
if (cdpCommands.includes(cmd)) {
|
|
19129
|
-
return { success: false, error: "No ideType specified \u2014 cannot route command" };
|
|
19130
|
-
}
|
|
19131
|
-
}
|
|
19132
|
-
switch (cmd) {
|
|
19133
|
-
// ─── CDP directly handle ───────────────────
|
|
19134
|
-
case "read_chat":
|
|
19135
|
-
return this.handleReadChat(args);
|
|
19136
|
-
case "chat_history":
|
|
19137
|
-
return this.handleChatHistory(args);
|
|
19138
|
-
case "send_chat":
|
|
19139
|
-
return this.handleSendChat(args);
|
|
19140
|
-
case "list_chats":
|
|
19141
|
-
return this.handleListChats(args);
|
|
19142
|
-
case "new_chat":
|
|
19143
|
-
return this.handleNewChat(args);
|
|
19144
|
-
case "switch_chat":
|
|
19145
|
-
return this.handleSwitchChat(args);
|
|
19146
|
-
case "set_mode":
|
|
19147
|
-
return this.handleSetMode(args);
|
|
19148
|
-
case "change_model":
|
|
19149
|
-
return this.handleChangeModel(args);
|
|
19150
|
-
case "set_thought_level":
|
|
19151
|
-
return this.handleSetThoughtLevel(args);
|
|
19152
|
-
case "resolve_action":
|
|
19153
|
-
return this.handleResolveAction(args);
|
|
19154
|
-
case "cdp_eval":
|
|
19155
|
-
return this.handleCdpEval(args);
|
|
19156
|
-
case "cdp_screenshot":
|
|
19157
|
-
case "screenshot":
|
|
19158
|
-
return this.handleScreenshot(args);
|
|
19159
|
-
case "cdp_command_exec":
|
|
19160
|
-
return this.handleCdpCommand(args);
|
|
19161
|
-
case "cdp_batch":
|
|
19162
|
-
return this.handleCdpBatch(args);
|
|
19163
|
-
case "cdp_remote_action":
|
|
19164
|
-
return this.handleCdpRemoteAction(args);
|
|
19165
|
-
case "cdp_discover_agents":
|
|
19166
|
-
return this.handleDiscoverAgents(args);
|
|
19167
|
-
case "cdp_dom_dump":
|
|
19168
|
-
return this.domHandlers.handleDomDump(args);
|
|
19169
|
-
case "cdp_dom_query":
|
|
19170
|
-
return this.domHandlers.handleDomQuery(args);
|
|
19171
|
-
case "cdp_dom_debug":
|
|
19172
|
-
return this.domHandlers.handleDomDebug(args);
|
|
19173
|
-
// ─── file directly handle ──────────────────
|
|
19174
|
-
case "file_read":
|
|
19175
|
-
return this.handleFileRead(args);
|
|
19176
|
-
case "file_write":
|
|
19177
|
-
return this.handleFileWrite(args);
|
|
19178
|
-
case "file_list":
|
|
19179
|
-
return this.handleFileList(args);
|
|
19180
|
-
case "file_list_browse":
|
|
19181
|
-
return this.handleFileListBrowse(args);
|
|
19182
|
-
// ─── vscode API → Extension delegate ────
|
|
19183
|
-
case "vscode_command_exec":
|
|
19184
|
-
case "execute_vscode_command": {
|
|
19185
|
-
const resolvedCmd = args?.commandId || args?.command;
|
|
19186
|
-
if (resolvedCmd === "adhdev.captureCdpScreenshot") {
|
|
19187
|
-
return this.handleScreenshot(args);
|
|
19188
|
-
}
|
|
19189
|
-
return this.delegateToExtension(resolvedCmd || cmd, args?.args);
|
|
19190
|
-
}
|
|
19191
|
-
case "get_open_editors":
|
|
19192
|
-
return this.delegateToExtension("adhdev.getOpenEditors", [args]);
|
|
19193
|
-
case "open_tab":
|
|
19194
|
-
return this.delegateToExtension("vscode.open", [args?.uri || args?.path]);
|
|
19195
|
-
case "close_tab":
|
|
19196
|
-
return this.delegateToExtension("workbench.action.closeActiveEditor", []);
|
|
19197
|
-
case "open_folder":
|
|
19198
|
-
return this.delegateToExtension("vscode.openFolder", [args?.path]);
|
|
19199
|
-
case "open_folder_picker":
|
|
19200
|
-
return this.delegateToExtension("workbench.action.files.openFolder", []);
|
|
19201
|
-
case "open_recent":
|
|
19202
|
-
return this.delegateToExtension("workbench.action.openRecent", []);
|
|
19203
|
-
case "get_commands":
|
|
19204
|
-
return this.delegateToExtension("adhdev.getCommands", []);
|
|
19205
|
-
case "get_recent_workspaces":
|
|
19206
|
-
return this.handleGetRecentWorkspaces(args);
|
|
19207
|
-
// ─── script manage ───────────────────
|
|
19208
|
-
case "refresh_scripts":
|
|
19209
|
-
return this.handleRefreshScripts(args);
|
|
19210
|
-
// ─── Agent Stream commands ───────────────
|
|
19211
|
-
case "agent_stream_switch":
|
|
19212
|
-
return this.handleAgentStreamSwitch(args);
|
|
19213
|
-
case "agent_stream_read":
|
|
19214
|
-
return this.handleAgentStreamRead(args);
|
|
19215
|
-
case "agent_stream_send":
|
|
19216
|
-
return this.handleAgentStreamSend(args);
|
|
19217
|
-
case "agent_stream_resolve":
|
|
19218
|
-
return this.handleAgentStreamResolve(args);
|
|
19219
|
-
case "agent_stream_new":
|
|
19220
|
-
return this.handleAgentStreamNew(args);
|
|
19221
|
-
case "agent_stream_list_chats":
|
|
19222
|
-
return this.handleAgentStreamListChats(args);
|
|
19223
|
-
case "agent_stream_switch_session":
|
|
19224
|
-
return this.handleAgentStreamSwitchSession(args);
|
|
19225
|
-
case "agent_stream_focus":
|
|
19226
|
-
return this.handleAgentStreamFocus(args);
|
|
19227
|
-
// ─── PTY Raw I/O (terminal view) ─────────
|
|
19228
|
-
case "pty_input":
|
|
19229
|
-
return this.handlePtyInput(args);
|
|
19230
|
-
case "pty_resize":
|
|
19231
|
-
return this.handlePtyResize(args);
|
|
19232
|
-
// ─── Provider Settings ──────────────
|
|
19233
|
-
case "get_provider_settings":
|
|
19234
|
-
return this.handleGetProviderSettings(args);
|
|
19235
|
-
case "set_provider_setting":
|
|
19236
|
-
return this.handleSetProviderSetting(args);
|
|
19237
|
-
// ─── IDE Extension Settings (per-IDE on/off) ──────────────
|
|
19238
|
-
case "get_ide_extensions":
|
|
19239
|
-
return this.handleGetIdeExtensions(args);
|
|
19240
|
-
case "set_ide_extension":
|
|
19241
|
-
return this.handleSetIdeExtension(args);
|
|
19242
|
-
// ─── Extension Model / Mode Control ──────────────
|
|
19243
|
-
case "list_extension_models":
|
|
19244
|
-
return await this.handleExtensionScript(args, "listModels");
|
|
19245
|
-
case "set_extension_model":
|
|
19246
|
-
return await this.handleExtensionScript(args, "setModel");
|
|
19247
|
-
case "list_extension_modes":
|
|
19248
|
-
return await this.handleExtensionScript(args, "listModes");
|
|
19249
|
-
case "set_extension_mode":
|
|
19250
|
-
return await this.handleExtensionScript(args, "setMode");
|
|
19251
|
-
default:
|
|
19252
|
-
return { success: false, error: `Unknown command: ${cmd}` };
|
|
19253
|
-
}
|
|
19254
|
-
}
|
|
19255
|
-
// ─── CDP-based chat commands ──────────────────────
|
|
19256
|
-
async handleChatHistory(args) {
|
|
19257
|
-
const { agentType, offset, limit, instanceId } = args;
|
|
19016
|
+
if (provider?.category === "extension") {
|
|
19258
19017
|
try {
|
|
19259
|
-
const
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
return { success: true, ...result, agent: agentStr };
|
|
19263
|
-
} catch (e) {
|
|
19264
|
-
return { success: false, error: e.message };
|
|
19265
|
-
}
|
|
19266
|
-
}
|
|
19267
|
-
async handleReadChat(args) {
|
|
19268
|
-
const provider = this.getProvider();
|
|
19269
|
-
const _log = (msg) => LOG4.debug("Command", `[read_chat] ${msg}`);
|
|
19270
|
-
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
19271
|
-
const adapter = this.getCliAdapter(provider.type);
|
|
19272
|
-
if (adapter) {
|
|
19273
|
-
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
19274
|
-
const status = adapter.getStatus?.();
|
|
19275
|
-
if (status) {
|
|
19276
|
-
return { success: true, messages: status.messages || [], status: status.status, activeModal: status.activeModal };
|
|
19277
|
-
}
|
|
19278
|
-
}
|
|
19279
|
-
return { success: false, error: `${provider.category} adapter not found` };
|
|
19280
|
-
}
|
|
19281
|
-
if (provider?.category === "extension") {
|
|
19282
|
-
try {
|
|
19283
|
-
const evalResult = await this.evaluateProviderScript("readChat", void 0, 5e4);
|
|
19284
|
-
if (evalResult?.result) {
|
|
19285
|
-
let parsed = evalResult.result;
|
|
19286
|
-
if (typeof parsed === "string") {
|
|
19287
|
-
try {
|
|
19288
|
-
parsed = JSON.parse(parsed);
|
|
19289
|
-
} catch {
|
|
19290
|
-
}
|
|
19291
|
-
}
|
|
19292
|
-
if (parsed && typeof parsed === "object") {
|
|
19293
|
-
_log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
|
|
19294
|
-
this.historyWriter.appendNewMessages(
|
|
19295
|
-
provider.type || "unknown_extension",
|
|
19296
|
-
parsed.messages || [],
|
|
19297
|
-
parsed.title,
|
|
19298
|
-
args?.instanceId
|
|
19299
|
-
);
|
|
19300
|
-
return { success: true, ...parsed };
|
|
19301
|
-
}
|
|
19302
|
-
}
|
|
19303
|
-
} catch (e) {
|
|
19304
|
-
_log(`Extension error: ${e.message}`);
|
|
19305
|
-
}
|
|
19306
|
-
if (this.agentStream) {
|
|
19307
|
-
const cdp2 = this.getCdp();
|
|
19308
|
-
if (cdp2) {
|
|
19309
|
-
const streams = await this.agentStream.collectAgentStreams(cdp2);
|
|
19310
|
-
const stream = streams.find((s) => s.agentType === provider.type);
|
|
19311
|
-
if (stream) {
|
|
19312
|
-
this.historyWriter.appendNewMessages(
|
|
19313
|
-
stream.agentType,
|
|
19314
|
-
stream.messages || [],
|
|
19315
|
-
void 0,
|
|
19316
|
-
args?.instanceId
|
|
19317
|
-
);
|
|
19318
|
-
return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
|
|
19319
|
-
}
|
|
19320
|
-
}
|
|
19321
|
-
}
|
|
19322
|
-
return { success: true, messages: [], status: "idle" };
|
|
19323
|
-
}
|
|
19324
|
-
const cdp = this.getCdp();
|
|
19325
|
-
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19326
|
-
const webviewScript = this.getProviderScript("webviewReadChat") || this.getProviderScript("webview_read_chat");
|
|
19327
|
-
if (webviewScript) {
|
|
19328
|
-
try {
|
|
19329
|
-
const matchText = provider?.webviewMatchText;
|
|
19330
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19331
|
-
const raw = await cdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
19332
|
-
if (raw) {
|
|
19333
|
-
let parsed = raw;
|
|
19334
|
-
if (typeof parsed === "string") {
|
|
19335
|
-
try {
|
|
19336
|
-
parsed = JSON.parse(parsed);
|
|
19337
|
-
} catch {
|
|
19338
|
-
}
|
|
19339
|
-
}
|
|
19340
|
-
if (parsed && typeof parsed === "object") {
|
|
19341
|
-
_log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
|
|
19342
|
-
this.historyWriter.appendNewMessages(
|
|
19343
|
-
provider?.type || this._currentIdeType || "unknown_webview",
|
|
19344
|
-
parsed.messages || [],
|
|
19345
|
-
parsed.title,
|
|
19346
|
-
args?.instanceId
|
|
19347
|
-
);
|
|
19348
|
-
return { success: true, ...parsed };
|
|
19349
|
-
}
|
|
19350
|
-
}
|
|
19351
|
-
} catch (e) {
|
|
19352
|
-
_log(`Webview readChat error: ${e.message}`);
|
|
19353
|
-
}
|
|
19354
|
-
return { success: true, messages: [], status: "idle" };
|
|
19355
|
-
}
|
|
19356
|
-
const script = this.getProviderScript("readChat") || this.getProviderScript("read_chat");
|
|
19357
|
-
if (script) {
|
|
19358
|
-
try {
|
|
19359
|
-
const result = await cdp.evaluate(script, 5e4);
|
|
19360
|
-
let parsed = result;
|
|
19018
|
+
const evalResult = await h.evaluateProviderScript("readChat", void 0, 5e4);
|
|
19019
|
+
if (evalResult?.result) {
|
|
19020
|
+
let parsed = evalResult.result;
|
|
19361
19021
|
if (typeof parsed === "string") {
|
|
19362
19022
|
try {
|
|
19363
19023
|
parsed = JSON.parse(parsed);
|
|
19364
19024
|
} catch {
|
|
19365
19025
|
}
|
|
19366
19026
|
}
|
|
19367
|
-
if (parsed && typeof parsed === "object"
|
|
19368
|
-
_log(`OK: ${parsed.messages?.length} msgs`);
|
|
19369
|
-
|
|
19370
|
-
provider
|
|
19027
|
+
if (parsed && typeof parsed === "object") {
|
|
19028
|
+
_log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
|
|
19029
|
+
h.historyWriter.appendNewMessages(
|
|
19030
|
+
provider.type || "unknown_extension",
|
|
19371
19031
|
parsed.messages || [],
|
|
19372
19032
|
parsed.title,
|
|
19373
19033
|
args?.instanceId
|
|
19374
19034
|
);
|
|
19375
19035
|
return { success: true, ...parsed };
|
|
19376
19036
|
}
|
|
19377
|
-
} catch (e) {
|
|
19378
|
-
LOG4.info("Command", `[read_chat] Script error: ${e.message}`);
|
|
19379
|
-
}
|
|
19380
|
-
}
|
|
19381
|
-
return { success: true, messages: [], status: "idle" };
|
|
19382
|
-
}
|
|
19383
|
-
async handleSendChat(args) {
|
|
19384
|
-
const text = args?.text || args?.message;
|
|
19385
|
-
if (!text) return { success: false, error: "text required" };
|
|
19386
|
-
const _log = (msg) => LOG4.debug("Command", `[send_chat] ${msg}`);
|
|
19387
|
-
const provider = this.getProvider();
|
|
19388
|
-
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
19389
|
-
const adapter = this.getCliAdapter(provider.type);
|
|
19390
|
-
if (adapter) {
|
|
19391
|
-
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
19392
|
-
try {
|
|
19393
|
-
await adapter.sendMessage(text);
|
|
19394
|
-
return { success: true, sent: true, method: `${provider.category}-adapter`, targetAgent: adapter.cliType };
|
|
19395
|
-
} catch (e) {
|
|
19396
|
-
return { success: false, error: `${provider.category} send failed: ${e.message}` };
|
|
19397
|
-
}
|
|
19398
19037
|
}
|
|
19399
|
-
}
|
|
19400
|
-
|
|
19401
|
-
|
|
19402
|
-
|
|
19403
|
-
|
|
19404
|
-
|
|
19405
|
-
|
|
19406
|
-
|
|
19407
|
-
|
|
19408
|
-
|
|
19409
|
-
|
|
19410
|
-
|
|
19411
|
-
|
|
19412
|
-
|
|
19413
|
-
|
|
19414
|
-
|
|
19415
|
-
}
|
|
19416
|
-
if (parsed?.needsTypeAndSend) {
|
|
19417
|
-
_log(`Extension needsTypeAndSend \u2192 AgentStreamManager`);
|
|
19418
|
-
}
|
|
19419
|
-
}
|
|
19420
|
-
} catch (e) {
|
|
19421
|
-
_log(`Extension script error: ${e.message}`);
|
|
19422
|
-
}
|
|
19423
|
-
if (this.agentStream && this.getCdp()) {
|
|
19424
|
-
const ok = await this.agentStream.sendToAgent(this.getCdp(), provider.type, text, this._currentIdeType);
|
|
19425
|
-
if (ok) {
|
|
19426
|
-
_log(`AgentStreamManager sent OK`);
|
|
19427
|
-
return { success: true, sent: true, method: "agent-stream" };
|
|
19428
|
-
}
|
|
19429
|
-
}
|
|
19430
|
-
return { success: false, error: `Extension '${provider.type}' send failed` };
|
|
19431
|
-
}
|
|
19432
|
-
const targetCdp = this.getCdp();
|
|
19433
|
-
if (!targetCdp?.isConnected) {
|
|
19434
|
-
_log(`No CDP for ${this._currentIdeType}`);
|
|
19435
|
-
return { success: false, error: `CDP for ${this._currentIdeType || "unknown"} not connected` };
|
|
19436
|
-
}
|
|
19437
|
-
_log(`Targeting IDE: ${this._currentIdeType}`);
|
|
19438
|
-
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
19439
|
-
try {
|
|
19440
|
-
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
19441
|
-
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
19442
|
-
const matchText = provider.webviewMatchText;
|
|
19443
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19444
|
-
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
19445
|
-
let wvParsed = wvResult;
|
|
19446
|
-
if (typeof wvResult === "string") {
|
|
19447
|
-
try {
|
|
19448
|
-
wvParsed = JSON.parse(wvResult);
|
|
19449
|
-
} catch {
|
|
19450
|
-
}
|
|
19451
|
-
}
|
|
19452
|
-
if (wvParsed?.sent) {
|
|
19453
|
-
_log(`webviewSendMessage (priority) OK`);
|
|
19454
|
-
return { success: true, sent: true, method: "webview-script-priority" };
|
|
19455
|
-
}
|
|
19456
|
-
_log(`webviewSendMessage (priority) did not confirm sent, falling through`);
|
|
19038
|
+
} catch (e) {
|
|
19039
|
+
_log(`Extension error: ${e.message}`);
|
|
19040
|
+
}
|
|
19041
|
+
if (h.agentStream) {
|
|
19042
|
+
const cdp2 = h.getCdp();
|
|
19043
|
+
if (cdp2) {
|
|
19044
|
+
const streams = await h.agentStream.collectAgentStreams(cdp2);
|
|
19045
|
+
const stream = streams.find((s) => s.agentType === provider.type);
|
|
19046
|
+
if (stream) {
|
|
19047
|
+
h.historyWriter.appendNewMessages(
|
|
19048
|
+
stream.agentType,
|
|
19049
|
+
stream.messages || [],
|
|
19050
|
+
void 0,
|
|
19051
|
+
args?.instanceId
|
|
19052
|
+
);
|
|
19053
|
+
return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
|
|
19457
19054
|
}
|
|
19458
|
-
} catch (e) {
|
|
19459
|
-
_log(`webviewSendMessage (priority) failed: ${e.message}, falling through`);
|
|
19460
19055
|
}
|
|
19461
19056
|
}
|
|
19462
|
-
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
|
|
19475
|
-
try {
|
|
19476
|
-
const result = await targetCdp.evaluate(sendScript, 3e4);
|
|
19477
|
-
let parsed = result;
|
|
19478
|
-
if (typeof result === "string") {
|
|
19057
|
+
return { success: true, messages: [], status: "idle" };
|
|
19058
|
+
}
|
|
19059
|
+
const cdp = h.getCdp();
|
|
19060
|
+
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19061
|
+
const webviewScript = h.getProviderScript("webviewReadChat") || h.getProviderScript("webview_read_chat");
|
|
19062
|
+
if (webviewScript) {
|
|
19063
|
+
try {
|
|
19064
|
+
const matchText = provider?.webviewMatchText;
|
|
19065
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19066
|
+
const raw = await cdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
19067
|
+
if (raw) {
|
|
19068
|
+
let parsed = raw;
|
|
19069
|
+
if (typeof parsed === "string") {
|
|
19479
19070
|
try {
|
|
19480
|
-
parsed = JSON.parse(
|
|
19071
|
+
parsed = JSON.parse(parsed);
|
|
19481
19072
|
} catch {
|
|
19482
19073
|
}
|
|
19483
19074
|
}
|
|
19484
|
-
if (parsed
|
|
19485
|
-
_log(`
|
|
19486
|
-
|
|
19487
|
-
|
|
19488
|
-
|
|
19489
|
-
|
|
19490
|
-
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
return { success: true, sent: true, method: "typeAndSend-script" };
|
|
19494
|
-
}
|
|
19495
|
-
} catch (e) {
|
|
19496
|
-
_log(`typeAndSend(script.selector) failed: ${e.message}`);
|
|
19497
|
-
}
|
|
19498
|
-
}
|
|
19499
|
-
if (parsed?.needsTypeAndSend && provider?.scripts?.webviewSendMessage) {
|
|
19500
|
-
try {
|
|
19501
|
-
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
19502
|
-
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
19503
|
-
const matchText = provider.webviewMatchText;
|
|
19504
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19505
|
-
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
19506
|
-
let wvParsed = wvResult;
|
|
19507
|
-
if (typeof wvResult === "string") {
|
|
19508
|
-
try {
|
|
19509
|
-
wvParsed = JSON.parse(wvResult);
|
|
19510
|
-
} catch {
|
|
19511
|
-
}
|
|
19512
|
-
}
|
|
19513
|
-
if (wvParsed?.sent) {
|
|
19514
|
-
_log(`webviewSendMessage OK`);
|
|
19515
|
-
return { success: true, sent: true, method: "webview-script" };
|
|
19516
|
-
}
|
|
19517
|
-
}
|
|
19518
|
-
} catch (e) {
|
|
19519
|
-
_log(`webviewSendMessage failed: ${e.message}`);
|
|
19520
|
-
}
|
|
19075
|
+
if (parsed && typeof parsed === "object") {
|
|
19076
|
+
_log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
|
|
19077
|
+
h.historyWriter.appendNewMessages(
|
|
19078
|
+
provider?.type || h.currentIdeType || "unknown_webview",
|
|
19079
|
+
parsed.messages || [],
|
|
19080
|
+
parsed.title,
|
|
19081
|
+
args?.instanceId
|
|
19082
|
+
);
|
|
19083
|
+
return { success: true, ...parsed };
|
|
19521
19084
|
}
|
|
19522
|
-
|
|
19523
|
-
|
|
19524
|
-
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19532
|
-
|
|
19085
|
+
}
|
|
19086
|
+
} catch (e) {
|
|
19087
|
+
_log(`Webview readChat error: ${e.message}`);
|
|
19088
|
+
}
|
|
19089
|
+
return { success: true, messages: [], status: "idle" };
|
|
19090
|
+
}
|
|
19091
|
+
const script = h.getProviderScript("readChat") || h.getProviderScript("read_chat");
|
|
19092
|
+
if (script) {
|
|
19093
|
+
try {
|
|
19094
|
+
const result = await cdp.evaluate(script, 5e4);
|
|
19095
|
+
let parsed = result;
|
|
19096
|
+
if (typeof parsed === "string") {
|
|
19097
|
+
try {
|
|
19098
|
+
parsed = JSON.parse(parsed);
|
|
19099
|
+
} catch {
|
|
19533
19100
|
}
|
|
19534
|
-
} catch (e) {
|
|
19535
|
-
_log(`sendMessage script failed: ${e.message}`);
|
|
19536
19101
|
}
|
|
19102
|
+
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
19103
|
+
_log(`OK: ${parsed.messages?.length} msgs`);
|
|
19104
|
+
h.historyWriter.appendNewMessages(
|
|
19105
|
+
provider?.type || h.currentIdeType || "unknown_ide",
|
|
19106
|
+
parsed.messages || [],
|
|
19107
|
+
parsed.title,
|
|
19108
|
+
args?.instanceId
|
|
19109
|
+
);
|
|
19110
|
+
return { success: true, ...parsed };
|
|
19111
|
+
}
|
|
19112
|
+
} catch (e) {
|
|
19113
|
+
LOG5.info("Command", `[read_chat] Script error: ${e.message}`);
|
|
19537
19114
|
}
|
|
19538
|
-
_log("All methods failed");
|
|
19539
|
-
return { success: false, error: "No provider method could send the message" };
|
|
19540
19115
|
}
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19116
|
+
return { success: true, messages: [], status: "idle" };
|
|
19117
|
+
}
|
|
19118
|
+
async function handleSendChat(h, args) {
|
|
19119
|
+
const text = args?.text || args?.message;
|
|
19120
|
+
if (!text) return { success: false, error: "text required" };
|
|
19121
|
+
const _log = (msg) => LOG5.debug("Command", `[send_chat] ${msg}`);
|
|
19122
|
+
const provider = h.getProvider();
|
|
19123
|
+
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
19124
|
+
const adapter = h.getCliAdapter(provider.type);
|
|
19125
|
+
if (adapter) {
|
|
19126
|
+
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
19544
19127
|
try {
|
|
19545
|
-
|
|
19546
|
-
|
|
19547
|
-
return { success: true, chats };
|
|
19128
|
+
await adapter.sendMessage(text);
|
|
19129
|
+
return { success: true, sent: true, method: `${provider.category}-adapter`, targetAgent: adapter.cliType };
|
|
19548
19130
|
} catch (e) {
|
|
19549
|
-
|
|
19131
|
+
return { success: false, error: `${provider.category} send failed: ${e.message}` };
|
|
19550
19132
|
}
|
|
19551
19133
|
}
|
|
19134
|
+
}
|
|
19135
|
+
if (provider?.category === "extension") {
|
|
19136
|
+
_log(`Extension: ${provider.type}`);
|
|
19552
19137
|
try {
|
|
19553
|
-
const
|
|
19554
|
-
if (
|
|
19555
|
-
|
|
19556
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19557
|
-
const raw = await this.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19558
|
-
let parsed = raw;
|
|
19138
|
+
const evalResult = await h.evaluateProviderScript("sendMessage", { MESSAGE: text }, 3e4);
|
|
19139
|
+
if (evalResult?.result) {
|
|
19140
|
+
let parsed = evalResult.result;
|
|
19559
19141
|
if (typeof parsed === "string") {
|
|
19560
19142
|
try {
|
|
19561
19143
|
parsed = JSON.parse(parsed);
|
|
19562
19144
|
} catch {
|
|
19563
19145
|
}
|
|
19564
19146
|
}
|
|
19565
|
-
if (parsed?.
|
|
19566
|
-
|
|
19567
|
-
return { success: true,
|
|
19147
|
+
if (parsed?.sent) {
|
|
19148
|
+
_log(`Extension script sent OK`);
|
|
19149
|
+
return { success: true, sent: true, method: "extension-script" };
|
|
19150
|
+
}
|
|
19151
|
+
if (parsed?.needsTypeAndSend) {
|
|
19152
|
+
_log(`Extension needsTypeAndSend \u2192 AgentStreamManager`);
|
|
19568
19153
|
}
|
|
19569
19154
|
}
|
|
19570
19155
|
} catch (e) {
|
|
19571
|
-
|
|
19156
|
+
_log(`Extension script error: ${e.message}`);
|
|
19157
|
+
}
|
|
19158
|
+
if (h.agentStream && h.getCdp()) {
|
|
19159
|
+
const ok = await h.agentStream.sendToAgent(h.getCdp(), provider.type, text, h.currentIdeType);
|
|
19160
|
+
if (ok) {
|
|
19161
|
+
_log(`AgentStreamManager sent OK`);
|
|
19162
|
+
return { success: true, sent: true, method: "agent-stream" };
|
|
19163
|
+
}
|
|
19572
19164
|
}
|
|
19165
|
+
return { success: false, error: `Extension '${provider.type}' send failed` };
|
|
19166
|
+
}
|
|
19167
|
+
const targetCdp = h.getCdp();
|
|
19168
|
+
if (!targetCdp?.isConnected) {
|
|
19169
|
+
_log(`No CDP for ${h.currentIdeType}`);
|
|
19170
|
+
return { success: false, error: `CDP for ${h.currentIdeType || "unknown"} not connected` };
|
|
19171
|
+
}
|
|
19172
|
+
_log(`Targeting IDE: ${h.currentIdeType}`);
|
|
19173
|
+
if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
|
|
19573
19174
|
try {
|
|
19574
|
-
const
|
|
19575
|
-
if (
|
|
19576
|
-
|
|
19577
|
-
|
|
19175
|
+
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
19176
|
+
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
19177
|
+
const matchText = provider.webviewMatchText;
|
|
19178
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19179
|
+
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
19180
|
+
let wvParsed = wvResult;
|
|
19181
|
+
if (typeof wvResult === "string") {
|
|
19578
19182
|
try {
|
|
19579
|
-
|
|
19183
|
+
wvParsed = JSON.parse(wvResult);
|
|
19580
19184
|
} catch {
|
|
19581
19185
|
}
|
|
19582
19186
|
}
|
|
19583
|
-
if (
|
|
19584
|
-
|
|
19585
|
-
return { success: true,
|
|
19187
|
+
if (wvParsed?.sent) {
|
|
19188
|
+
_log(`webviewSendMessage (priority) OK`);
|
|
19189
|
+
return { success: true, sent: true, method: "webview-script-priority" };
|
|
19586
19190
|
}
|
|
19191
|
+
_log(`webviewSendMessage (priority) did not confirm sent, falling through`);
|
|
19587
19192
|
}
|
|
19588
19193
|
} catch (e) {
|
|
19589
|
-
|
|
19194
|
+
_log(`webviewSendMessage (priority) failed: ${e.message}, falling through`);
|
|
19590
19195
|
}
|
|
19591
|
-
return { success: false, error: "listSessions script not available for this provider" };
|
|
19592
19196
|
}
|
|
19593
|
-
|
|
19594
|
-
const provider = this.getProvider();
|
|
19595
|
-
if (provider?.category === "extension" && this.agentStream && this.getCdp()) {
|
|
19596
|
-
const ok = await this.agentStream.newAgentSession(this.getCdp(), provider.type, this._currentIdeType);
|
|
19597
|
-
return { success: ok };
|
|
19598
|
-
}
|
|
19197
|
+
if (provider?.inputMethod === "cdp-type-and-send" && provider.inputSelector) {
|
|
19599
19198
|
try {
|
|
19600
|
-
const
|
|
19601
|
-
if (
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
const raw = await this.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19605
|
-
if (raw) return { success: true, result: raw };
|
|
19199
|
+
const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
|
|
19200
|
+
if (sent) {
|
|
19201
|
+
_log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
|
|
19202
|
+
return { success: true, sent: true, method: "typeAndSend-provider" };
|
|
19606
19203
|
}
|
|
19607
19204
|
} catch (e) {
|
|
19608
|
-
|
|
19205
|
+
_log(`typeAndSend(provider) failed: ${e.message}`);
|
|
19609
19206
|
}
|
|
19207
|
+
}
|
|
19208
|
+
const sendScript = h.getProviderScript("sendMessage", { MESSAGE: text });
|
|
19209
|
+
if (sendScript) {
|
|
19610
19210
|
try {
|
|
19611
|
-
const
|
|
19612
|
-
|
|
19211
|
+
const result = await targetCdp.evaluate(sendScript, 3e4);
|
|
19212
|
+
let parsed = result;
|
|
19213
|
+
if (typeof result === "string") {
|
|
19214
|
+
try {
|
|
19215
|
+
parsed = JSON.parse(result);
|
|
19216
|
+
} catch {
|
|
19217
|
+
}
|
|
19218
|
+
}
|
|
19219
|
+
if (parsed?.sent) {
|
|
19220
|
+
_log(`sendMessage script OK`);
|
|
19221
|
+
return { success: true, sent: true, method: "script" };
|
|
19222
|
+
}
|
|
19223
|
+
if (parsed?.needsTypeAndSend && parsed?.selector) {
|
|
19224
|
+
try {
|
|
19225
|
+
const sent = await targetCdp.typeAndSend(parsed.selector, text);
|
|
19226
|
+
if (sent) {
|
|
19227
|
+
_log(`typeAndSend(script.selector=${parsed.selector}) success`);
|
|
19228
|
+
return { success: true, sent: true, method: "typeAndSend-script" };
|
|
19229
|
+
}
|
|
19230
|
+
} catch (e) {
|
|
19231
|
+
_log(`typeAndSend(script.selector) failed: ${e.message}`);
|
|
19232
|
+
}
|
|
19233
|
+
}
|
|
19234
|
+
if (parsed?.needsTypeAndSend && provider?.scripts?.webviewSendMessage) {
|
|
19235
|
+
try {
|
|
19236
|
+
const webviewScript = provider.scripts.webviewSendMessage(text);
|
|
19237
|
+
if (webviewScript && targetCdp.evaluateInWebviewFrame) {
|
|
19238
|
+
const matchText = provider.webviewMatchText;
|
|
19239
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19240
|
+
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
19241
|
+
let wvParsed = wvResult;
|
|
19242
|
+
if (typeof wvResult === "string") {
|
|
19243
|
+
try {
|
|
19244
|
+
wvParsed = JSON.parse(wvResult);
|
|
19245
|
+
} catch {
|
|
19246
|
+
}
|
|
19247
|
+
}
|
|
19248
|
+
if (wvParsed?.sent) {
|
|
19249
|
+
_log(`webviewSendMessage OK`);
|
|
19250
|
+
return { success: true, sent: true, method: "webview-script" };
|
|
19251
|
+
}
|
|
19252
|
+
}
|
|
19253
|
+
} catch (e) {
|
|
19254
|
+
_log(`webviewSendMessage failed: ${e.message}`);
|
|
19255
|
+
}
|
|
19256
|
+
}
|
|
19257
|
+
if (parsed?.needsTypeAndSend && parsed?.clickCoords) {
|
|
19258
|
+
try {
|
|
19259
|
+
const { x, y } = parsed.clickCoords;
|
|
19260
|
+
const sent = await targetCdp.typeAndSendAt(x, y, text);
|
|
19261
|
+
if (sent) {
|
|
19262
|
+
_log(`typeAndSendAt(${x},${y}) success`);
|
|
19263
|
+
return { success: true, sent: true, method: "typeAndSendAt-script" };
|
|
19264
|
+
}
|
|
19265
|
+
} catch (e) {
|
|
19266
|
+
_log(`typeAndSendAt failed: ${e.message}`);
|
|
19267
|
+
}
|
|
19268
|
+
}
|
|
19613
19269
|
} catch (e) {
|
|
19614
|
-
|
|
19270
|
+
_log(`sendMessage script failed: ${e.message}`);
|
|
19615
19271
|
}
|
|
19616
|
-
return { success: false, error: "newSession script not available for this provider" };
|
|
19617
19272
|
}
|
|
19618
|
-
|
|
19619
|
-
|
|
19620
|
-
|
|
19621
|
-
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
if (provider?.category === "extension" && this.agentStream && this.getCdp()) {
|
|
19625
|
-
const ok = await this.agentStream.switchAgentSession(this.getCdp(), provider.type, sessionId);
|
|
19626
|
-
return { success: ok, result: ok ? "switched" : "failed" };
|
|
19627
|
-
}
|
|
19628
|
-
const cdp = this.getCdp(ideType);
|
|
19629
|
-
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19273
|
+
_log("All methods failed");
|
|
19274
|
+
return { success: false, error: "No provider method could send the message" };
|
|
19275
|
+
}
|
|
19276
|
+
async function handleListChats(h, args) {
|
|
19277
|
+
const provider = h.getProvider();
|
|
19278
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
19630
19279
|
try {
|
|
19631
|
-
const
|
|
19632
|
-
|
|
19633
|
-
|
|
19634
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19635
|
-
const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19636
|
-
if (raw) return { success: true, result: raw };
|
|
19637
|
-
}
|
|
19280
|
+
const chats = await h.agentStream.listAgentChats(h.getCdp(), provider.type);
|
|
19281
|
+
LOG5.info("Command", `[list_chats] Extension: ${chats.length} chats`);
|
|
19282
|
+
return { success: true, chats };
|
|
19638
19283
|
} catch (e) {
|
|
19639
|
-
|
|
19284
|
+
LOG5.info("Command", `[list_chats] Extension error: ${e.message}`);
|
|
19640
19285
|
}
|
|
19641
|
-
|
|
19642
|
-
|
|
19643
|
-
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
19652
|
-
|
|
19653
|
-
const y = Math.round(parsed.clickY);
|
|
19654
|
-
LOG4.info("Command", `[switch_chat] CDP click at (${x}, ${y}) for "${parsed.title}"`);
|
|
19655
|
-
await cdp.send("Input.dispatchMouseEvent", {
|
|
19656
|
-
type: "mousePressed",
|
|
19657
|
-
x,
|
|
19658
|
-
y,
|
|
19659
|
-
button: "left",
|
|
19660
|
-
clickCount: 1
|
|
19661
|
-
});
|
|
19662
|
-
await cdp.send("Input.dispatchMouseEvent", {
|
|
19663
|
-
type: "mouseReleased",
|
|
19664
|
-
x,
|
|
19665
|
-
y,
|
|
19666
|
-
button: "left",
|
|
19667
|
-
clickCount: 1
|
|
19668
|
-
});
|
|
19669
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
19670
|
-
const wsResult = await cdp.evaluate(`
|
|
19671
|
-
(() => {
|
|
19672
|
-
const inp = Array.from(document.querySelectorAll('input[type="text"]'))
|
|
19673
|
-
.find(i => i.offsetWidth > 0 && (i.placeholder || '').includes('Select where'));
|
|
19674
|
-
if (!inp) return null;
|
|
19675
|
-
const rows = inp.closest('[class*="quickInput"]')?.querySelectorAll('[class*="cursor-pointer"]');
|
|
19676
|
-
if (rows && rows.length > 0) {
|
|
19677
|
-
const r = rows[0].getBoundingClientRect();
|
|
19678
|
-
return JSON.stringify({ x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) });
|
|
19679
|
-
}
|
|
19680
|
-
return null;
|
|
19681
|
-
})()
|
|
19682
|
-
`, 5e3);
|
|
19683
|
-
if (wsResult) {
|
|
19684
|
-
try {
|
|
19685
|
-
const ws = JSON.parse(wsResult);
|
|
19686
|
-
await cdp.send("Input.dispatchMouseEvent", {
|
|
19687
|
-
type: "mousePressed",
|
|
19688
|
-
x: ws.x,
|
|
19689
|
-
y: ws.y,
|
|
19690
|
-
button: "left",
|
|
19691
|
-
clickCount: 1
|
|
19692
|
-
});
|
|
19693
|
-
await cdp.send("Input.dispatchMouseEvent", {
|
|
19694
|
-
type: "mouseReleased",
|
|
19695
|
-
x: ws.x,
|
|
19696
|
-
y: ws.y,
|
|
19697
|
-
button: "left",
|
|
19698
|
-
clickCount: 1
|
|
19699
|
-
});
|
|
19700
|
-
} catch {
|
|
19701
|
-
}
|
|
19286
|
+
}
|
|
19287
|
+
try {
|
|
19288
|
+
const webviewScript = h.getProviderScript("webviewListSessions") || h.getProviderScript("webview_list_sessions");
|
|
19289
|
+
if (webviewScript) {
|
|
19290
|
+
const matchText = provider?.webviewMatchText;
|
|
19291
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19292
|
+
const raw = await h.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19293
|
+
let parsed = raw;
|
|
19294
|
+
if (typeof parsed === "string") {
|
|
19295
|
+
try {
|
|
19296
|
+
parsed = JSON.parse(parsed);
|
|
19297
|
+
} catch {
|
|
19702
19298
|
}
|
|
19703
|
-
return { success: true, result: "switched" };
|
|
19704
19299
|
}
|
|
19705
|
-
if (parsed?.
|
|
19706
|
-
|
|
19300
|
+
if (parsed?.sessions) {
|
|
19301
|
+
LOG5.info("Command", `[list_chats] Webview OK: ${parsed.sessions.length} chats`);
|
|
19302
|
+
return { success: true, chats: parsed.sessions };
|
|
19707
19303
|
}
|
|
19708
|
-
return { success: true, result: raw };
|
|
19709
|
-
} catch (e) {
|
|
19710
|
-
LOG4.error("Command", `[switch_chat] error: ${e.message}`);
|
|
19711
|
-
return { success: false, error: e.message };
|
|
19712
19304
|
}
|
|
19305
|
+
} catch (e) {
|
|
19306
|
+
LOG5.info("Command", `[list_chats] Webview error: ${e.message}`);
|
|
19713
19307
|
}
|
|
19714
|
-
|
|
19715
|
-
const
|
|
19716
|
-
|
|
19717
|
-
|
|
19718
|
-
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
|
|
19722
|
-
acpInstance.onEvent("set_mode", { mode });
|
|
19723
|
-
return { success: true, mode };
|
|
19308
|
+
try {
|
|
19309
|
+
const evalResult = await h.evaluateProviderScript("listSessions");
|
|
19310
|
+
if (evalResult) {
|
|
19311
|
+
let parsed = evalResult.result;
|
|
19312
|
+
if (typeof parsed === "string") {
|
|
19313
|
+
try {
|
|
19314
|
+
parsed = JSON.parse(parsed);
|
|
19315
|
+
} catch {
|
|
19724
19316
|
}
|
|
19725
19317
|
}
|
|
19726
|
-
|
|
19318
|
+
if (Array.isArray(parsed)) {
|
|
19319
|
+
LOG5.info("Command", `[list_chats] OK: ${parsed.length} chats`);
|
|
19320
|
+
return { success: true, chats: parsed };
|
|
19321
|
+
}
|
|
19727
19322
|
}
|
|
19728
|
-
|
|
19323
|
+
} catch (e) {
|
|
19324
|
+
LOG5.info("Command", `[list_chats] error: ${e.message}`);
|
|
19325
|
+
}
|
|
19326
|
+
return { success: false, error: "listSessions script not available for this provider" };
|
|
19327
|
+
}
|
|
19328
|
+
async function handleNewChat(h, args) {
|
|
19329
|
+
const provider = h.getProvider();
|
|
19330
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
19331
|
+
const ok = await h.agentStream.newAgentSession(h.getCdp(), provider.type, h.currentIdeType);
|
|
19332
|
+
return { success: ok };
|
|
19333
|
+
}
|
|
19334
|
+
try {
|
|
19335
|
+
const webviewScript = h.getProviderScript("webviewNewSession") || h.getProviderScript("webview_new_session");
|
|
19729
19336
|
if (webviewScript) {
|
|
19730
|
-
const
|
|
19731
|
-
|
|
19337
|
+
const matchText = provider?.webviewMatchText;
|
|
19338
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19339
|
+
const raw = await h.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19340
|
+
if (raw) return { success: true, result: raw };
|
|
19341
|
+
}
|
|
19342
|
+
} catch (e) {
|
|
19343
|
+
return { success: false, error: `webviewNewSession failed: ${e.message}` };
|
|
19344
|
+
}
|
|
19345
|
+
try {
|
|
19346
|
+
const evalResult = await h.evaluateProviderScript("newSession");
|
|
19347
|
+
if (evalResult) return { success: true };
|
|
19348
|
+
} catch (e) {
|
|
19349
|
+
return { success: false, error: `newSession failed: ${e.message}` };
|
|
19350
|
+
}
|
|
19351
|
+
return { success: false, error: "newSession script not available for this provider" };
|
|
19352
|
+
}
|
|
19353
|
+
async function handleSwitchChat(h, args) {
|
|
19354
|
+
const provider = h.getProvider();
|
|
19355
|
+
const ideType = h.currentIdeType;
|
|
19356
|
+
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
19357
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
19358
|
+
LOG5.info("Command", `[switch_chat] sessionId=${sessionId}, ideType=${ideType}`);
|
|
19359
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
19360
|
+
const ok = await h.agentStream.switchAgentSession(h.getCdp(), provider.type, sessionId);
|
|
19361
|
+
return { success: ok, result: ok ? "switched" : "failed" };
|
|
19362
|
+
}
|
|
19363
|
+
const cdp = h.getCdp(ideType);
|
|
19364
|
+
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19365
|
+
try {
|
|
19366
|
+
const webviewScript = h.getProviderScript("webviewSwitchSession", { SESSION_ID: JSON.stringify(sessionId) });
|
|
19367
|
+
if (webviewScript) {
|
|
19368
|
+
const matchText = provider?.webviewMatchText;
|
|
19369
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19370
|
+
const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19371
|
+
if (raw) return { success: true, result: raw };
|
|
19372
|
+
}
|
|
19373
|
+
} catch (e) {
|
|
19374
|
+
return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
|
|
19375
|
+
}
|
|
19376
|
+
const script = h.getProviderScript("switchSession", { SESSION_ID: JSON.stringify(sessionId) }) || h.getProviderScript("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
|
|
19377
|
+
if (!script) return { success: false, error: "switch_session script not available" };
|
|
19378
|
+
try {
|
|
19379
|
+
const raw = await cdp.evaluate(script, 15e3);
|
|
19380
|
+
LOG5.info("Command", `[switch_chat] result: ${raw}`);
|
|
19381
|
+
let parsed = null;
|
|
19382
|
+
try {
|
|
19383
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
19384
|
+
} catch {
|
|
19385
|
+
}
|
|
19386
|
+
if (parsed?.action === "click" && parsed.clickX && parsed.clickY) {
|
|
19387
|
+
const x = Math.round(parsed.clickX);
|
|
19388
|
+
const y = Math.round(parsed.clickY);
|
|
19389
|
+
LOG5.info("Command", `[switch_chat] CDP click at (${x}, ${y}) for "${parsed.title}"`);
|
|
19390
|
+
await cdp.send("Input.dispatchMouseEvent", {
|
|
19391
|
+
type: "mousePressed",
|
|
19392
|
+
x,
|
|
19393
|
+
y,
|
|
19394
|
+
button: "left",
|
|
19395
|
+
clickCount: 1
|
|
19396
|
+
});
|
|
19397
|
+
await cdp.send("Input.dispatchMouseEvent", {
|
|
19398
|
+
type: "mouseReleased",
|
|
19399
|
+
x,
|
|
19400
|
+
y,
|
|
19401
|
+
button: "left",
|
|
19402
|
+
clickCount: 1
|
|
19403
|
+
});
|
|
19404
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
19405
|
+
const wsResult = await cdp.evaluate(`
|
|
19406
|
+
(() => {
|
|
19407
|
+
const inp = Array.from(document.querySelectorAll('input[type="text"]'))
|
|
19408
|
+
.find(i => i.offsetWidth > 0 && (i.placeholder || '').includes('Select where'));
|
|
19409
|
+
if (!inp) return null;
|
|
19410
|
+
const rows = inp.closest('[class*="quickInput"]')?.querySelectorAll('[class*="cursor-pointer"]');
|
|
19411
|
+
if (rows && rows.length > 0) {
|
|
19412
|
+
const r = rows[0].getBoundingClientRect();
|
|
19413
|
+
return JSON.stringify({ x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) });
|
|
19414
|
+
}
|
|
19415
|
+
return null;
|
|
19416
|
+
})()
|
|
19417
|
+
`, 5e3);
|
|
19418
|
+
if (wsResult) {
|
|
19732
19419
|
try {
|
|
19733
|
-
const
|
|
19734
|
-
|
|
19735
|
-
|
|
19736
|
-
|
|
19737
|
-
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19741
|
-
|
|
19742
|
-
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19420
|
+
const ws = JSON.parse(wsResult);
|
|
19421
|
+
await cdp.send("Input.dispatchMouseEvent", {
|
|
19422
|
+
type: "mousePressed",
|
|
19423
|
+
x: ws.x,
|
|
19424
|
+
y: ws.y,
|
|
19425
|
+
button: "left",
|
|
19426
|
+
clickCount: 1
|
|
19427
|
+
});
|
|
19428
|
+
await cdp.send("Input.dispatchMouseEvent", {
|
|
19429
|
+
type: "mouseReleased",
|
|
19430
|
+
x: ws.x,
|
|
19431
|
+
y: ws.y,
|
|
19432
|
+
button: "left",
|
|
19433
|
+
clickCount: 1
|
|
19434
|
+
});
|
|
19435
|
+
} catch {
|
|
19746
19436
|
}
|
|
19747
19437
|
}
|
|
19438
|
+
return { success: true, result: "switched" };
|
|
19439
|
+
}
|
|
19440
|
+
if (parsed?.error) return { success: false, error: parsed.error };
|
|
19441
|
+
return { success: true, result: raw };
|
|
19442
|
+
} catch (e) {
|
|
19443
|
+
LOG5.error("Command", `[switch_chat] error: ${e.message}`);
|
|
19444
|
+
return { success: false, error: e.message };
|
|
19445
|
+
}
|
|
19446
|
+
}
|
|
19447
|
+
async function handleSetMode(h, args) {
|
|
19448
|
+
const provider = h.getProvider();
|
|
19449
|
+
const mode = args?.mode || "agent";
|
|
19450
|
+
if (provider?.category === "acp") {
|
|
19451
|
+
const adapter = h.getCliAdapter(provider.type);
|
|
19452
|
+
if (adapter) {
|
|
19453
|
+
const acpInstance = adapter._acpInstance;
|
|
19454
|
+
if (acpInstance && typeof acpInstance.onEvent === "function") {
|
|
19455
|
+
acpInstance.onEvent("set_mode", { mode });
|
|
19456
|
+
return { success: true, mode };
|
|
19457
|
+
}
|
|
19748
19458
|
}
|
|
19749
|
-
|
|
19750
|
-
|
|
19459
|
+
return { success: false, error: "ACP adapter not found" };
|
|
19460
|
+
}
|
|
19461
|
+
const webviewScript = h.getProviderScript("webviewSetMode", { MODE: JSON.stringify(mode) });
|
|
19462
|
+
if (webviewScript) {
|
|
19463
|
+
const cdp = h.getCdp();
|
|
19464
|
+
if (cdp?.isConnected) {
|
|
19751
19465
|
try {
|
|
19752
|
-
const
|
|
19753
|
-
|
|
19754
|
-
|
|
19755
|
-
|
|
19756
|
-
|
|
19757
|
-
|
|
19758
|
-
|
|
19759
|
-
|
|
19466
|
+
const matchText = provider?.webviewMatchText;
|
|
19467
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19468
|
+
const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19469
|
+
let result = raw;
|
|
19470
|
+
if (typeof raw === "string") {
|
|
19471
|
+
try {
|
|
19472
|
+
result = JSON.parse(raw);
|
|
19473
|
+
} catch {
|
|
19760
19474
|
}
|
|
19761
|
-
if (parsed?.success) return { success: true, mode, method: "script" };
|
|
19762
19475
|
}
|
|
19476
|
+
if (result?.success) return { success: true, mode, method: "webview-script" };
|
|
19763
19477
|
} catch (e) {
|
|
19764
|
-
|
|
19478
|
+
LOG5.info("Command", `[set_mode] webview script error: ${e.message}`);
|
|
19765
19479
|
}
|
|
19766
19480
|
}
|
|
19767
|
-
return this.delegateToExtension(`composerMode.${mode}`, []);
|
|
19768
19481
|
}
|
|
19769
|
-
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
19773
|
-
|
|
19774
|
-
|
|
19775
|
-
|
|
19776
|
-
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
acpInstance.onEvent("change_model", { model });
|
|
19780
|
-
LOG4.info("Command", `[change_model] Dispatched change_model event to ACP instance`);
|
|
19781
|
-
return { success: true, model };
|
|
19782
|
-
}
|
|
19783
|
-
}
|
|
19784
|
-
return { success: false, error: "ACP adapter not found" };
|
|
19785
|
-
}
|
|
19786
|
-
const webviewScript = this.getProviderScript("webviewSetModel", { MODEL: JSON.stringify(model) });
|
|
19787
|
-
if (webviewScript) {
|
|
19788
|
-
const cdp = this.getCdp();
|
|
19789
|
-
if (cdp?.isConnected) {
|
|
19790
|
-
try {
|
|
19791
|
-
const matchText = provider?.webviewMatchText;
|
|
19792
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19793
|
-
const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19794
|
-
let result = raw;
|
|
19795
|
-
if (typeof raw === "string") {
|
|
19796
|
-
try {
|
|
19797
|
-
result = JSON.parse(raw);
|
|
19798
|
-
} catch {
|
|
19799
|
-
}
|
|
19482
|
+
const mainScript = h.getProviderScript("setMode", { MODE: JSON.stringify(mode) });
|
|
19483
|
+
if (mainScript) {
|
|
19484
|
+
try {
|
|
19485
|
+
const evalResult = await h.evaluateProviderScript("setMode", { MODE: JSON.stringify(mode) }, 15e3);
|
|
19486
|
+
if (evalResult?.result) {
|
|
19487
|
+
let parsed = evalResult.result;
|
|
19488
|
+
if (typeof parsed === "string") {
|
|
19489
|
+
try {
|
|
19490
|
+
parsed = JSON.parse(parsed);
|
|
19491
|
+
} catch {
|
|
19800
19492
|
}
|
|
19801
|
-
if (result?.success) return { success: true, model, method: "webview-script" };
|
|
19802
|
-
} catch (e) {
|
|
19803
|
-
LOG4.info("Command", `[change_model] webview script error: ${e.message}`);
|
|
19804
19493
|
}
|
|
19494
|
+
if (parsed?.success) return { success: true, mode, method: "script" };
|
|
19495
|
+
}
|
|
19496
|
+
} catch (e) {
|
|
19497
|
+
LOG5.info("Command", `[set_mode] script error: ${e.message}`);
|
|
19498
|
+
}
|
|
19499
|
+
}
|
|
19500
|
+
return { success: false, error: `setMode '${mode}' not supported by this provider` };
|
|
19501
|
+
}
|
|
19502
|
+
async function handleChangeModel(h, args) {
|
|
19503
|
+
const provider = h.getProvider();
|
|
19504
|
+
const model = args?.model;
|
|
19505
|
+
LOG5.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} ideType=${h.currentIdeType} providerType=${h.currentProviderType}`);
|
|
19506
|
+
if (provider?.category === "acp") {
|
|
19507
|
+
const adapter = h.getCliAdapter(provider.type);
|
|
19508
|
+
LOG5.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
19509
|
+
if (adapter) {
|
|
19510
|
+
const acpInstance = adapter._acpInstance;
|
|
19511
|
+
if (acpInstance && typeof acpInstance.onEvent === "function") {
|
|
19512
|
+
acpInstance.onEvent("change_model", { model });
|
|
19513
|
+
LOG5.info("Command", `[change_model] Dispatched change_model event to ACP instance`);
|
|
19514
|
+
return { success: true, model };
|
|
19805
19515
|
}
|
|
19806
19516
|
}
|
|
19807
|
-
|
|
19808
|
-
|
|
19517
|
+
return { success: false, error: "ACP adapter not found" };
|
|
19518
|
+
}
|
|
19519
|
+
const webviewScript = h.getProviderScript("webviewSetModel", { MODEL: JSON.stringify(model) });
|
|
19520
|
+
if (webviewScript) {
|
|
19521
|
+
const cdp = h.getCdp();
|
|
19522
|
+
if (cdp?.isConnected) {
|
|
19809
19523
|
try {
|
|
19810
|
-
const
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
|
|
19524
|
+
const matchText = provider?.webviewMatchText;
|
|
19525
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19526
|
+
const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
19527
|
+
let result = raw;
|
|
19528
|
+
if (typeof raw === "string") {
|
|
19529
|
+
try {
|
|
19530
|
+
result = JSON.parse(raw);
|
|
19531
|
+
} catch {
|
|
19818
19532
|
}
|
|
19819
|
-
if (parsed?.success) return { success: true, model, method: "script" };
|
|
19820
19533
|
}
|
|
19534
|
+
if (result?.success) return { success: true, model, method: "webview-script" };
|
|
19821
19535
|
} catch (e) {
|
|
19822
|
-
|
|
19536
|
+
LOG5.info("Command", `[change_model] webview script error: ${e.message}`);
|
|
19823
19537
|
}
|
|
19824
19538
|
}
|
|
19825
|
-
const settingsKey = provider?.vscodeCommands?.changeModel;
|
|
19826
|
-
if (settingsKey) {
|
|
19827
|
-
return this.delegateToExtension("workbench.action.openSettings", [settingsKey]);
|
|
19828
|
-
}
|
|
19829
|
-
return { success: false, error: "changeModel not supported by this IDE provider" };
|
|
19830
19539
|
}
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
const configId = args?.configId;
|
|
19834
|
-
const value = args?.value;
|
|
19835
|
-
if (!configId || !value) return { success: false, error: "configId and value required" };
|
|
19836
|
-
const provider = this.getProvider();
|
|
19837
|
-
if (!provider || provider.category !== "acp") {
|
|
19838
|
-
return { success: false, error: "set_thought_level only for ACP providers" };
|
|
19839
|
-
}
|
|
19840
|
-
const adapter = this.getCliAdapter(provider.type);
|
|
19841
|
-
const acpInstance = adapter?._acpInstance;
|
|
19842
|
-
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
19540
|
+
const mainScript = h.getProviderScript("setModel", { MODEL: JSON.stringify(model) });
|
|
19541
|
+
if (mainScript) {
|
|
19843
19542
|
try {
|
|
19844
|
-
await
|
|
19845
|
-
|
|
19846
|
-
|
|
19847
|
-
|
|
19848
|
-
return { success: false, error: e?.message };
|
|
19849
|
-
}
|
|
19850
|
-
}
|
|
19851
|
-
/** resolveAction — unified (common for IDE/Extension) */
|
|
19852
|
-
async handleResolveAction(args) {
|
|
19853
|
-
const provider = this.getProvider();
|
|
19854
|
-
const action = args?.action || "approve";
|
|
19855
|
-
const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
|
|
19856
|
-
LOG4.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
|
|
19857
|
-
if (provider?.category === "extension" && this.agentStream && this.getCdp()) {
|
|
19858
|
-
const ok = await this.agentStream.resolveAgentAction(
|
|
19859
|
-
this.getCdp(),
|
|
19860
|
-
provider.type,
|
|
19861
|
-
action,
|
|
19862
|
-
this._currentIdeType
|
|
19863
|
-
);
|
|
19864
|
-
return { success: ok };
|
|
19865
|
-
}
|
|
19866
|
-
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
19867
|
-
const script = this.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || this.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
19868
|
-
if (script) {
|
|
19869
|
-
const cdp = this.getCdp();
|
|
19870
|
-
if (cdp?.isConnected) {
|
|
19543
|
+
const evalResult = await h.evaluateProviderScript("setModel", { MODEL: JSON.stringify(model) }, 15e3);
|
|
19544
|
+
if (evalResult?.result) {
|
|
19545
|
+
let parsed = evalResult.result;
|
|
19546
|
+
if (typeof parsed === "string") {
|
|
19871
19547
|
try {
|
|
19872
|
-
|
|
19873
|
-
|
|
19874
|
-
const raw = await cdp.evaluateInWebviewFrame?.(script, matchFn);
|
|
19875
|
-
let result = raw;
|
|
19876
|
-
if (typeof raw === "string") {
|
|
19877
|
-
try {
|
|
19878
|
-
result = JSON.parse(raw);
|
|
19879
|
-
} catch {
|
|
19880
|
-
}
|
|
19881
|
-
}
|
|
19882
|
-
LOG4.info("Command", `[resolveAction] webview script result: ${JSON.stringify(result)}`);
|
|
19883
|
-
if (result?.resolved) {
|
|
19884
|
-
return { success: true, clicked: result.clicked };
|
|
19885
|
-
}
|
|
19886
|
-
if (result?.found && result.x != null && result.y != null) {
|
|
19887
|
-
LOG4.info("Command", `[resolveAction] Webview coordinate click not fully supported via CDP. Click directly in script.`);
|
|
19888
|
-
}
|
|
19889
|
-
if (result?.found || result?.resolved) return { success: true };
|
|
19890
|
-
} catch (e) {
|
|
19891
|
-
return { success: false, error: `webviewResolveAction failed: ${e.message}` };
|
|
19548
|
+
parsed = JSON.parse(parsed);
|
|
19549
|
+
} catch {
|
|
19892
19550
|
}
|
|
19893
19551
|
}
|
|
19552
|
+
if (parsed?.success) return { success: true, model, method: "script" };
|
|
19894
19553
|
}
|
|
19554
|
+
} catch (e) {
|
|
19555
|
+
LOG5.info("Command", `[change_model] script error: ${e.message}`);
|
|
19895
19556
|
}
|
|
19896
|
-
|
|
19897
|
-
|
|
19898
|
-
|
|
19899
|
-
|
|
19900
|
-
|
|
19557
|
+
}
|
|
19558
|
+
return { success: false, error: "changeModel not supported by this IDE provider" };
|
|
19559
|
+
}
|
|
19560
|
+
async function handleSetThoughtLevel(h, args) {
|
|
19561
|
+
const configId = args?.configId;
|
|
19562
|
+
const value = args?.value;
|
|
19563
|
+
if (!configId || !value) return { success: false, error: "configId and value required" };
|
|
19564
|
+
const provider = h.getProvider();
|
|
19565
|
+
if (!provider || provider.category !== "acp") {
|
|
19566
|
+
return { success: false, error: "set_thought_level only for ACP providers" };
|
|
19567
|
+
}
|
|
19568
|
+
const adapter = h.getCliAdapter(provider.type);
|
|
19569
|
+
const acpInstance = adapter?._acpInstance;
|
|
19570
|
+
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
19571
|
+
try {
|
|
19572
|
+
await acpInstance.setConfigOption(configId, value);
|
|
19573
|
+
LOG5.info("Command", `[set_thought_level] ${configId}=${value} for ${provider.type}`);
|
|
19574
|
+
return { success: true, configId, value };
|
|
19575
|
+
} catch (e) {
|
|
19576
|
+
return { success: false, error: e?.message };
|
|
19577
|
+
}
|
|
19578
|
+
}
|
|
19579
|
+
async function handleResolveAction(h, args) {
|
|
19580
|
+
const provider = h.getProvider();
|
|
19581
|
+
const action = args?.action || "approve";
|
|
19582
|
+
const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
|
|
19583
|
+
LOG5.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
|
|
19584
|
+
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
19585
|
+
const ok = await h.agentStream.resolveAgentAction(
|
|
19586
|
+
h.getCdp(),
|
|
19587
|
+
provider.type,
|
|
19588
|
+
action,
|
|
19589
|
+
h.currentIdeType
|
|
19590
|
+
);
|
|
19591
|
+
return { success: ok };
|
|
19592
|
+
}
|
|
19593
|
+
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
19594
|
+
const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
19595
|
+
if (script) {
|
|
19596
|
+
const cdp = h.getCdp();
|
|
19597
|
+
if (cdp?.isConnected) {
|
|
19901
19598
|
try {
|
|
19902
|
-
const
|
|
19599
|
+
const matchText = provider?.webviewMatchText;
|
|
19600
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
19601
|
+
const raw = await cdp.evaluateInWebviewFrame?.(script, matchFn);
|
|
19903
19602
|
let result = raw;
|
|
19904
19603
|
if (typeof raw === "string") {
|
|
19905
19604
|
try {
|
|
19906
19605
|
result = JSON.parse(raw);
|
|
19907
19606
|
} catch {
|
|
19908
|
-
}
|
|
19909
|
-
}
|
|
19910
|
-
|
|
19911
|
-
if (result?.resolved) {
|
|
19912
|
-
|
|
19913
|
-
|
|
19914
|
-
}
|
|
19915
|
-
if (result?.found
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
type: "mousePressed",
|
|
19920
|
-
x,
|
|
19921
|
-
y,
|
|
19922
|
-
button: "left",
|
|
19923
|
-
clickCount: 1
|
|
19924
|
-
});
|
|
19925
|
-
await cdp.send("Input.dispatchMouseEvent", {
|
|
19926
|
-
type: "mouseReleased",
|
|
19927
|
-
x,
|
|
19928
|
-
y,
|
|
19929
|
-
button: "left",
|
|
19930
|
-
clickCount: 1
|
|
19931
|
-
});
|
|
19932
|
-
LOG4.info("Command", `[resolveAction] CDP click at (${x}, ${y}) \u2014 "${result.text}"`);
|
|
19933
|
-
return { success: true, clicked: result.text };
|
|
19934
|
-
}
|
|
19935
|
-
return { success: false, error: result?.found === false ? `Button not found: ${button}` : "No coordinates" };
|
|
19936
|
-
} catch (e) {
|
|
19937
|
-
return { success: false, error: `resolveAction failed: ${e.message}` };
|
|
19938
|
-
}
|
|
19939
|
-
}
|
|
19940
|
-
}
|
|
19941
|
-
return { success: false, error: "resolveAction script not available for this provider" };
|
|
19942
|
-
}
|
|
19943
|
-
// ─── CDP direct commands ──────────────────────────
|
|
19944
|
-
async handleCdpEval(args) {
|
|
19945
|
-
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19946
|
-
const expression = args?.expression || args?.script;
|
|
19947
|
-
if (!expression) return { success: false, error: "expression required" };
|
|
19948
|
-
try {
|
|
19949
|
-
const result = await this.getCdp().evaluate(expression, 5e4);
|
|
19950
|
-
return { success: true, result };
|
|
19951
|
-
} catch (e) {
|
|
19952
|
-
return { success: false, error: e.message };
|
|
19953
|
-
}
|
|
19954
|
-
}
|
|
19955
|
-
async handleScreenshot(args) {
|
|
19956
|
-
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19957
|
-
try {
|
|
19958
|
-
const buf = await this.getCdp().captureScreenshot();
|
|
19959
|
-
if (buf) {
|
|
19960
|
-
const b64 = buf.toString("base64");
|
|
19961
|
-
return { success: true, result: b64, base64: b64, screenshot: b64, format: "jpeg" };
|
|
19607
|
+
}
|
|
19608
|
+
}
|
|
19609
|
+
LOG5.info("Command", `[resolveAction] webview script result: ${JSON.stringify(result)}`);
|
|
19610
|
+
if (result?.resolved) return { success: true, clicked: result.clicked };
|
|
19611
|
+
if (result?.found && result.x != null && result.y != null) {
|
|
19612
|
+
LOG5.info("Command", `[resolveAction] Webview coordinate click not fully supported via CDP. Click directly in script.`);
|
|
19613
|
+
}
|
|
19614
|
+
if (result?.found || result?.resolved) return { success: true };
|
|
19615
|
+
} catch (e) {
|
|
19616
|
+
return { success: false, error: `webviewResolveAction failed: ${e.message}` };
|
|
19617
|
+
}
|
|
19962
19618
|
}
|
|
19963
|
-
return { success: false, error: "Screenshot failed" };
|
|
19964
|
-
} catch (e) {
|
|
19965
|
-
return { success: false, error: e.message };
|
|
19966
19619
|
}
|
|
19967
19620
|
}
|
|
19968
|
-
|
|
19969
|
-
|
|
19970
|
-
|
|
19971
|
-
|
|
19972
|
-
|
|
19973
|
-
try {
|
|
19974
|
-
const result = await this.getCdp().sendCdpCommand(method, params);
|
|
19975
|
-
return { success: true, result };
|
|
19976
|
-
} catch (e) {
|
|
19977
|
-
return { success: false, error: e.message };
|
|
19978
|
-
}
|
|
19979
|
-
}
|
|
19980
|
-
async handleCdpBatch(args) {
|
|
19981
|
-
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19982
|
-
const commands = args?.commands;
|
|
19983
|
-
const stopOnError = args?.stopOnError !== false;
|
|
19984
|
-
if (!commands?.length) return { success: false, error: "commands array required" };
|
|
19985
|
-
const results = [];
|
|
19986
|
-
for (const cmd of commands) {
|
|
19621
|
+
if (provider?.scripts?.resolveAction) {
|
|
19622
|
+
const script = provider.scripts.resolveAction({ action, button, buttonText: button });
|
|
19623
|
+
if (script) {
|
|
19624
|
+
const cdp = h.getCdp();
|
|
19625
|
+
if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19987
19626
|
try {
|
|
19988
|
-
const
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
}
|
|
19995
|
-
return { success: true, results };
|
|
19996
|
-
}
|
|
19997
|
-
async handleCdpRemoteAction(args) {
|
|
19998
|
-
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19999
|
-
const action = args?.action;
|
|
20000
|
-
const params = args?.params || args;
|
|
20001
|
-
try {
|
|
20002
|
-
switch (action) {
|
|
20003
|
-
case "input_key": {
|
|
20004
|
-
const { key, modifiers } = params;
|
|
20005
|
-
await this.getCdp().send("Input.dispatchKeyEvent", {
|
|
20006
|
-
type: "keyDown",
|
|
20007
|
-
key,
|
|
20008
|
-
...modifiers?.ctrl ? { modifiers: 2 } : {},
|
|
20009
|
-
...modifiers?.shift ? { modifiers: 8 } : {}
|
|
20010
|
-
});
|
|
20011
|
-
await this.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key });
|
|
20012
|
-
return { success: true };
|
|
20013
|
-
}
|
|
20014
|
-
case "input_click": {
|
|
20015
|
-
let { x, y, nx, ny, button: btn } = params;
|
|
20016
|
-
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
20017
|
-
const viewport = await this.getCdp().evaluate(
|
|
20018
|
-
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
20019
|
-
);
|
|
20020
|
-
const { w, h } = JSON.parse(viewport);
|
|
20021
|
-
x = Math.round(nx * w);
|
|
20022
|
-
y = Math.round(ny * h);
|
|
20023
|
-
}
|
|
20024
|
-
if (x === void 0 || y === void 0) {
|
|
20025
|
-
return { success: false, error: "No coordinates provided (x,y or nx,ny required)" };
|
|
19627
|
+
const raw = await cdp.evaluate(script, 3e4);
|
|
19628
|
+
let result = raw;
|
|
19629
|
+
if (typeof raw === "string") {
|
|
19630
|
+
try {
|
|
19631
|
+
result = JSON.parse(raw);
|
|
19632
|
+
} catch {
|
|
20026
19633
|
}
|
|
20027
|
-
|
|
19634
|
+
}
|
|
19635
|
+
LOG5.info("Command", `[resolveAction] script result: ${JSON.stringify(result)}`);
|
|
19636
|
+
if (result?.resolved) {
|
|
19637
|
+
LOG5.info("Command", `[resolveAction] script-click resolved \u2014 "${result.clicked}"`);
|
|
19638
|
+
return { success: true, clicked: result.clicked };
|
|
19639
|
+
}
|
|
19640
|
+
if (result?.found && result.x != null && result.y != null) {
|
|
19641
|
+
const x = result.x;
|
|
19642
|
+
const y = result.y;
|
|
19643
|
+
await cdp.send("Input.dispatchMouseEvent", {
|
|
20028
19644
|
type: "mousePressed",
|
|
20029
19645
|
x,
|
|
20030
19646
|
y,
|
|
20031
|
-
button:
|
|
19647
|
+
button: "left",
|
|
20032
19648
|
clickCount: 1
|
|
20033
19649
|
});
|
|
20034
|
-
await
|
|
19650
|
+
await cdp.send("Input.dispatchMouseEvent", {
|
|
20035
19651
|
type: "mouseReleased",
|
|
20036
19652
|
x,
|
|
20037
19653
|
y,
|
|
20038
|
-
button:
|
|
19654
|
+
button: "left",
|
|
20039
19655
|
clickCount: 1
|
|
20040
19656
|
});
|
|
20041
|
-
|
|
20042
|
-
|
|
20043
|
-
case "input_type": {
|
|
20044
|
-
const { text } = params;
|
|
20045
|
-
for (const char of text || "") {
|
|
20046
|
-
await this.getCdp().send("Input.dispatchKeyEvent", {
|
|
20047
|
-
type: "keyDown",
|
|
20048
|
-
text: char,
|
|
20049
|
-
key: char
|
|
20050
|
-
});
|
|
20051
|
-
await this.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key: char });
|
|
20052
|
-
}
|
|
20053
|
-
return { success: true };
|
|
20054
|
-
}
|
|
20055
|
-
case "page_screenshot":
|
|
20056
|
-
return this.handleScreenshot(args);
|
|
20057
|
-
case "page_eval":
|
|
20058
|
-
return this.handleCdpEval(params);
|
|
20059
|
-
case "dom_query": {
|
|
20060
|
-
const html = await this.getCdp().querySelector(params?.selector);
|
|
20061
|
-
return { success: true, html };
|
|
20062
|
-
}
|
|
20063
|
-
case "input_wheel": {
|
|
20064
|
-
let { x, y, nx, ny, deltaX, deltaY } = params;
|
|
20065
|
-
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
20066
|
-
const viewport = await this.getCdp().evaluate(
|
|
20067
|
-
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
20068
|
-
);
|
|
20069
|
-
const { w, h } = JSON.parse(viewport);
|
|
20070
|
-
x = Math.round(nx * w);
|
|
20071
|
-
y = Math.round(ny * h);
|
|
20072
|
-
}
|
|
20073
|
-
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
20074
|
-
type: "mouseWheel",
|
|
20075
|
-
x: x || 0,
|
|
20076
|
-
y: y || 0,
|
|
20077
|
-
deltaX: deltaX || 0,
|
|
20078
|
-
deltaY: deltaY || 0
|
|
20079
|
-
});
|
|
20080
|
-
return { success: true };
|
|
19657
|
+
LOG5.info("Command", `[resolveAction] CDP click at (${x}, ${y}) \u2014 "${result.text}"`);
|
|
19658
|
+
return { success: true, clicked: result.text };
|
|
20081
19659
|
}
|
|
20082
|
-
|
|
20083
|
-
|
|
19660
|
+
return { success: false, error: result?.found === false ? `Button not found: ${button}` : "No coordinates" };
|
|
19661
|
+
} catch (e) {
|
|
19662
|
+
return { success: false, error: `resolveAction failed: ${e.message}` };
|
|
20084
19663
|
}
|
|
20085
|
-
} catch (e) {
|
|
20086
|
-
return { success: false, error: e.message };
|
|
20087
19664
|
}
|
|
20088
19665
|
}
|
|
20089
|
-
|
|
20090
|
-
|
|
20091
|
-
|
|
20092
|
-
|
|
19666
|
+
return { success: false, error: "resolveAction script not available for this provider" };
|
|
19667
|
+
}
|
|
19668
|
+
var fs32 = __toESM2(require("fs"));
|
|
19669
|
+
var path32 = __toESM2(require("path"));
|
|
19670
|
+
var os4 = __toESM2(require("os"));
|
|
19671
|
+
async function handleCdpEval(h, args) {
|
|
19672
|
+
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19673
|
+
const expression = args?.expression || args?.script;
|
|
19674
|
+
if (!expression) return { success: false, error: "expression required" };
|
|
19675
|
+
try {
|
|
19676
|
+
const result = await h.getCdp().evaluate(expression, 5e4);
|
|
19677
|
+
return { success: true, result };
|
|
19678
|
+
} catch (e) {
|
|
19679
|
+
return { success: false, error: e.message };
|
|
20093
19680
|
}
|
|
20094
|
-
|
|
20095
|
-
|
|
20096
|
-
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20100
|
-
|
|
20101
|
-
return { success:
|
|
19681
|
+
}
|
|
19682
|
+
async function handleScreenshot(h, args) {
|
|
19683
|
+
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19684
|
+
try {
|
|
19685
|
+
const buf = await h.getCdp().captureScreenshot();
|
|
19686
|
+
if (buf) {
|
|
19687
|
+
const b64 = buf.toString("base64");
|
|
19688
|
+
return { success: true, result: b64, base64: b64, screenshot: b64, format: "webp" };
|
|
20102
19689
|
}
|
|
19690
|
+
return { success: false, error: "Screenshot failed" };
|
|
19691
|
+
} catch (e) {
|
|
19692
|
+
return { success: false, error: e.message };
|
|
20103
19693
|
}
|
|
20104
|
-
|
|
20105
|
-
|
|
20106
|
-
|
|
20107
|
-
|
|
20108
|
-
|
|
20109
|
-
|
|
20110
|
-
|
|
20111
|
-
|
|
20112
|
-
}
|
|
19694
|
+
}
|
|
19695
|
+
async function handleCdpCommand(h, args) {
|
|
19696
|
+
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19697
|
+
const method = args?.method;
|
|
19698
|
+
const params = args?.params || {};
|
|
19699
|
+
if (!method) return { success: false, error: "method required" };
|
|
19700
|
+
try {
|
|
19701
|
+
const result = await h.getCdp().sendCdpCommand(method, params);
|
|
19702
|
+
return { success: true, result };
|
|
19703
|
+
} catch (e) {
|
|
19704
|
+
return { success: false, error: e.message };
|
|
20113
19705
|
}
|
|
20114
|
-
|
|
19706
|
+
}
|
|
19707
|
+
async function handleCdpBatch(h, args) {
|
|
19708
|
+
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19709
|
+
const commands = args?.commands;
|
|
19710
|
+
const stopOnError = args?.stopOnError !== false;
|
|
19711
|
+
if (!commands?.length) return { success: false, error: "commands array required" };
|
|
19712
|
+
const results = [];
|
|
19713
|
+
for (const cmd of commands) {
|
|
20115
19714
|
try {
|
|
20116
|
-
const
|
|
20117
|
-
|
|
20118
|
-
const files = entries.map((e) => ({
|
|
20119
|
-
name: e.name,
|
|
20120
|
-
type: e.isDirectory() ? "directory" : "file",
|
|
20121
|
-
size: e.isFile() ? fs32.statSync(path32.join(dirPath, e.name)).size : void 0
|
|
20122
|
-
}));
|
|
20123
|
-
return { success: true, files, path: dirPath };
|
|
19715
|
+
const result = await h.getCdp().sendCdpCommand(cmd.method, cmd.params || {});
|
|
19716
|
+
results.push({ method: cmd.method, success: true, result });
|
|
20124
19717
|
} catch (e) {
|
|
20125
|
-
|
|
20126
|
-
|
|
20127
|
-
}
|
|
20128
|
-
async handleFileListBrowse(args) {
|
|
20129
|
-
return this.handleFileList(args);
|
|
20130
|
-
}
|
|
20131
|
-
resolveSafePath(requestedPath) {
|
|
20132
|
-
const home = os4.homedir();
|
|
20133
|
-
let resolved;
|
|
20134
|
-
if (requestedPath.startsWith("~")) {
|
|
20135
|
-
resolved = path32.join(home, requestedPath.slice(1));
|
|
20136
|
-
} else if (path32.isAbsolute(requestedPath)) {
|
|
20137
|
-
resolved = requestedPath;
|
|
20138
|
-
} else {
|
|
20139
|
-
resolved = path32.resolve(requestedPath);
|
|
19718
|
+
results.push({ method: cmd.method, success: false, error: e.message });
|
|
19719
|
+
if (stopOnError) break;
|
|
20140
19720
|
}
|
|
20141
|
-
return resolved;
|
|
20142
19721
|
}
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
}
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20151
|
-
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20158
|
-
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
19722
|
+
return { success: true, results };
|
|
19723
|
+
}
|
|
19724
|
+
async function handleCdpRemoteAction(h, args) {
|
|
19725
|
+
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19726
|
+
const action = args?.action;
|
|
19727
|
+
const params = args?.params || args;
|
|
19728
|
+
try {
|
|
19729
|
+
switch (action) {
|
|
19730
|
+
case "input_key": {
|
|
19731
|
+
const { key, modifiers } = params;
|
|
19732
|
+
await h.getCdp().send("Input.dispatchKeyEvent", {
|
|
19733
|
+
type: "keyDown",
|
|
19734
|
+
key,
|
|
19735
|
+
...modifiers?.ctrl ? { modifiers: 2 } : {},
|
|
19736
|
+
...modifiers?.shift ? { modifiers: 8 } : {}
|
|
19737
|
+
});
|
|
19738
|
+
await h.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key });
|
|
19739
|
+
return { success: true };
|
|
19740
|
+
}
|
|
19741
|
+
case "input_click": {
|
|
19742
|
+
let { x, y, nx, ny, button: btn } = params;
|
|
19743
|
+
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
19744
|
+
const viewport = await h.getCdp().evaluate(
|
|
19745
|
+
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
19746
|
+
);
|
|
19747
|
+
const { w, h: vh } = JSON.parse(viewport);
|
|
19748
|
+
x = Math.round(nx * w);
|
|
19749
|
+
y = Math.round(ny * vh);
|
|
20162
19750
|
}
|
|
19751
|
+
if (x === void 0 || y === void 0) {
|
|
19752
|
+
return { success: false, error: "No coordinates provided (x,y or nx,ny required)" };
|
|
19753
|
+
}
|
|
19754
|
+
await h.getCdp().send("Input.dispatchMouseEvent", {
|
|
19755
|
+
type: "mousePressed",
|
|
19756
|
+
x,
|
|
19757
|
+
y,
|
|
19758
|
+
button: btn || "left",
|
|
19759
|
+
clickCount: 1
|
|
19760
|
+
});
|
|
19761
|
+
await h.getCdp().send("Input.dispatchMouseEvent", {
|
|
19762
|
+
type: "mouseReleased",
|
|
19763
|
+
x,
|
|
19764
|
+
y,
|
|
19765
|
+
button: btn || "left",
|
|
19766
|
+
clickCount: 1
|
|
19767
|
+
});
|
|
19768
|
+
return { success: true, x, y };
|
|
20163
19769
|
}
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20168
|
-
|
|
20169
|
-
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
}
|
|
20174
|
-
return { success: false, error: "ProviderLoader not initialized" };
|
|
20175
|
-
}
|
|
20176
|
-
// ─── Agent Stream commands ───────────────────────
|
|
20177
|
-
async handleAgentStreamSwitch(args) {
|
|
20178
|
-
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
20179
|
-
const agentType = args?.agentType || args?.agent || null;
|
|
20180
|
-
await this.agentStream.switchActiveAgent(this.getCdp(), agentType);
|
|
20181
|
-
return { success: true, activeAgent: agentType };
|
|
20182
|
-
}
|
|
20183
|
-
async handleAgentStreamRead(args) {
|
|
20184
|
-
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
20185
|
-
const streams = await this.agentStream.collectAgentStreams(this.getCdp());
|
|
20186
|
-
return { success: true, streams };
|
|
20187
|
-
}
|
|
20188
|
-
async handleAgentStreamSend(args) {
|
|
20189
|
-
const agentType = args?.agentType || args?.agent;
|
|
20190
|
-
const text = args?.text || args?.message;
|
|
20191
|
-
if (!text) return { success: false, error: "text required" };
|
|
20192
|
-
if (agentType && this.ctx.adapters) {
|
|
20193
|
-
for (const [key, adapter] of this.ctx.adapters.entries()) {
|
|
20194
|
-
if (adapter.cliType === agentType || key.includes(agentType)) {
|
|
20195
|
-
LOG4.info("Command", `[agent_stream_send] Routing to CLI adapter: ${adapter.cliType}`);
|
|
20196
|
-
try {
|
|
20197
|
-
await adapter.sendMessage(text);
|
|
20198
|
-
return { success: true, sent: true, targetAgent: adapter.cliType };
|
|
20199
|
-
} catch (e) {
|
|
20200
|
-
LOG4.info("Command", `[agent_stream_send] CLI adapter failed: ${e.message}`);
|
|
20201
|
-
return { success: false, error: `CLI send failed: ${e.message}` };
|
|
20202
|
-
}
|
|
19770
|
+
case "input_type": {
|
|
19771
|
+
const { text } = params;
|
|
19772
|
+
for (const char of text || "") {
|
|
19773
|
+
await h.getCdp().send("Input.dispatchKeyEvent", {
|
|
19774
|
+
type: "keyDown",
|
|
19775
|
+
text: char,
|
|
19776
|
+
key: char
|
|
19777
|
+
});
|
|
19778
|
+
await h.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key: char });
|
|
20203
19779
|
}
|
|
19780
|
+
return { success: true };
|
|
19781
|
+
}
|
|
19782
|
+
case "page_screenshot":
|
|
19783
|
+
return handleScreenshot(h, args);
|
|
19784
|
+
case "page_eval":
|
|
19785
|
+
return handleCdpEval(h, params);
|
|
19786
|
+
case "dom_query": {
|
|
19787
|
+
const html = await h.getCdp().querySelector(params?.selector);
|
|
19788
|
+
return { success: true, html };
|
|
19789
|
+
}
|
|
19790
|
+
case "input_wheel": {
|
|
19791
|
+
let { x, y, nx, ny, deltaX, deltaY } = params;
|
|
19792
|
+
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
19793
|
+
const viewport = await h.getCdp().evaluate(
|
|
19794
|
+
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
19795
|
+
);
|
|
19796
|
+
const { w, h: vh } = JSON.parse(viewport);
|
|
19797
|
+
x = Math.round(nx * w);
|
|
19798
|
+
y = Math.round(ny * vh);
|
|
19799
|
+
}
|
|
19800
|
+
await h.getCdp().send("Input.dispatchMouseEvent", {
|
|
19801
|
+
type: "mouseWheel",
|
|
19802
|
+
x: x || 0,
|
|
19803
|
+
y: y || 0,
|
|
19804
|
+
deltaX: deltaX || 0,
|
|
19805
|
+
deltaY: deltaY || 0
|
|
19806
|
+
});
|
|
19807
|
+
return { success: true };
|
|
20204
19808
|
}
|
|
19809
|
+
default:
|
|
19810
|
+
return { success: false, error: `Unknown remote action: ${action}` };
|
|
20205
19811
|
}
|
|
20206
|
-
|
|
20207
|
-
|
|
20208
|
-
if (!resolvedAgent) return { success: false, error: "agentType required" };
|
|
20209
|
-
const ok = await this.agentStream.sendToAgent(this.getCdp(), resolvedAgent, text, this._currentIdeType);
|
|
20210
|
-
return { success: ok };
|
|
19812
|
+
} catch (e) {
|
|
19813
|
+
return { success: false, error: e.message };
|
|
20211
19814
|
}
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20216
|
-
|
|
20217
|
-
|
|
20218
|
-
|
|
19815
|
+
}
|
|
19816
|
+
async function handleDiscoverAgents(h, args) {
|
|
19817
|
+
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19818
|
+
const agents = await h.getCdp().discoverAgentWebviews();
|
|
19819
|
+
return { success: true, agents };
|
|
19820
|
+
}
|
|
19821
|
+
function resolveSafePath(requestedPath) {
|
|
19822
|
+
const home = os4.homedir();
|
|
19823
|
+
let resolved;
|
|
19824
|
+
if (requestedPath.startsWith("~")) {
|
|
19825
|
+
resolved = path32.join(home, requestedPath.slice(1));
|
|
19826
|
+
} else if (path32.isAbsolute(requestedPath)) {
|
|
19827
|
+
resolved = requestedPath;
|
|
19828
|
+
} else {
|
|
19829
|
+
resolved = path32.resolve(requestedPath);
|
|
20219
19830
|
}
|
|
20220
|
-
|
|
20221
|
-
|
|
20222
|
-
|
|
20223
|
-
|
|
20224
|
-
const
|
|
20225
|
-
|
|
19831
|
+
return resolved;
|
|
19832
|
+
}
|
|
19833
|
+
async function handleFileRead(h, args) {
|
|
19834
|
+
try {
|
|
19835
|
+
const filePath = resolveSafePath(args?.path);
|
|
19836
|
+
const content = fs32.readFileSync(filePath, "utf-8");
|
|
19837
|
+
return { success: true, content, path: filePath };
|
|
19838
|
+
} catch (e) {
|
|
19839
|
+
return { success: false, error: e.message };
|
|
20226
19840
|
}
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
|
|
20230
|
-
|
|
20231
|
-
|
|
20232
|
-
|
|
20233
|
-
|
|
20234
|
-
|
|
20235
|
-
|
|
20236
|
-
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
20237
|
-
const sessionId = args?.sessionId || args?.id;
|
|
20238
|
-
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
20239
|
-
const ok = await this.agentStream.switchAgentSession(this.getCdp(), agentType, sessionId);
|
|
20240
|
-
return { success: ok };
|
|
19841
|
+
}
|
|
19842
|
+
async function handleFileWrite(h, args) {
|
|
19843
|
+
try {
|
|
19844
|
+
const filePath = resolveSafePath(args?.path);
|
|
19845
|
+
fs32.mkdirSync(path32.dirname(filePath), { recursive: true });
|
|
19846
|
+
fs32.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
19847
|
+
return { success: true, path: filePath };
|
|
19848
|
+
} catch (e) {
|
|
19849
|
+
return { success: false, error: e.message };
|
|
20241
19850
|
}
|
|
20242
|
-
|
|
20243
|
-
|
|
20244
|
-
|
|
20245
|
-
|
|
20246
|
-
|
|
20247
|
-
const
|
|
20248
|
-
|
|
19851
|
+
}
|
|
19852
|
+
async function handleFileList(h, args) {
|
|
19853
|
+
try {
|
|
19854
|
+
const dirPath = resolveSafePath(args?.path || ".");
|
|
19855
|
+
const entries = fs32.readdirSync(dirPath, { withFileTypes: true });
|
|
19856
|
+
const files = entries.map((e) => ({
|
|
19857
|
+
name: e.name,
|
|
19858
|
+
type: e.isDirectory() ? "directory" : "file",
|
|
19859
|
+
size: e.isFile() ? fs32.statSync(path32.join(dirPath, e.name)).size : void 0
|
|
19860
|
+
}));
|
|
19861
|
+
return { success: true, files, path: dirPath };
|
|
19862
|
+
} catch (e) {
|
|
19863
|
+
return { success: false, error: e.message };
|
|
19864
|
+
}
|
|
19865
|
+
}
|
|
19866
|
+
async function handleFileListBrowse(h, args) {
|
|
19867
|
+
return handleFileList(h, args);
|
|
19868
|
+
}
|
|
19869
|
+
init_config();
|
|
19870
|
+
async function handleAgentStreamSwitch(h, args) {
|
|
19871
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19872
|
+
const agentType = args?.agentType || args?.agent || null;
|
|
19873
|
+
await h.agentStream.switchActiveAgent(h.getCdp(), agentType);
|
|
19874
|
+
return { success: true, activeAgent: agentType };
|
|
19875
|
+
}
|
|
19876
|
+
async function handleAgentStreamRead(h, args) {
|
|
19877
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19878
|
+
const streams = await h.agentStream.collectAgentStreams(h.getCdp());
|
|
19879
|
+
return { success: true, streams };
|
|
19880
|
+
}
|
|
19881
|
+
async function handleAgentStreamSend(h, args) {
|
|
19882
|
+
const agentType = args?.agentType || args?.agent;
|
|
19883
|
+
const text = args?.text || args?.message;
|
|
19884
|
+
if (!text) return { success: false, error: "text required" };
|
|
19885
|
+
if (agentType && h.ctx.adapters) {
|
|
19886
|
+
for (const [key, adapter] of h.ctx.adapters.entries()) {
|
|
19887
|
+
if (adapter.cliType === agentType || key.includes(agentType)) {
|
|
19888
|
+
LOG5.info("Command", `[agent_stream_send] Routing to CLI adapter: ${adapter.cliType}`);
|
|
19889
|
+
try {
|
|
19890
|
+
await adapter.sendMessage(text);
|
|
19891
|
+
return { success: true, sent: true, targetAgent: adapter.cliType };
|
|
19892
|
+
} catch (e) {
|
|
19893
|
+
LOG5.info("Command", `[agent_stream_send] CLI adapter failed: ${e.message}`);
|
|
19894
|
+
return { success: false, error: `CLI send failed: ${e.message}` };
|
|
19895
|
+
}
|
|
19896
|
+
}
|
|
19897
|
+
}
|
|
20249
19898
|
}
|
|
20250
|
-
|
|
20251
|
-
|
|
20252
|
-
|
|
20253
|
-
|
|
20254
|
-
|
|
20255
|
-
|
|
20256
|
-
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20263
|
-
|
|
20264
|
-
|
|
20265
|
-
|
|
19899
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19900
|
+
const resolvedAgent = agentType || h.agentStream.activeAgentType;
|
|
19901
|
+
if (!resolvedAgent) return { success: false, error: "agentType required" };
|
|
19902
|
+
const ok = await h.agentStream.sendToAgent(h.getCdp(), resolvedAgent, text, h.currentIdeType);
|
|
19903
|
+
return { success: ok };
|
|
19904
|
+
}
|
|
19905
|
+
async function handleAgentStreamResolve(h, args) {
|
|
19906
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19907
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
19908
|
+
const action = args?.action || "approve";
|
|
19909
|
+
if (!agentType) return { success: false, error: "agentType required" };
|
|
19910
|
+
const ok = await h.agentStream.resolveAgentAction(h.getCdp(), agentType, action, h.currentIdeType);
|
|
19911
|
+
return { success: ok };
|
|
19912
|
+
}
|
|
19913
|
+
async function handleAgentStreamNew(h, args) {
|
|
19914
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19915
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
19916
|
+
if (!agentType) return { success: false, error: "agentType required" };
|
|
19917
|
+
const ok = await h.agentStream.newAgentSession(h.getCdp(), agentType, h.currentIdeType);
|
|
19918
|
+
return { success: ok };
|
|
19919
|
+
}
|
|
19920
|
+
async function handleAgentStreamListChats(h, args) {
|
|
19921
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19922
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
19923
|
+
if (!agentType) return { success: false, error: "agentType required" };
|
|
19924
|
+
const chats = await h.agentStream.listAgentChats(h.getCdp(), agentType);
|
|
19925
|
+
return { success: true, chats };
|
|
19926
|
+
}
|
|
19927
|
+
async function handleAgentStreamSwitchSession(h, args) {
|
|
19928
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19929
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
19930
|
+
const sessionId = args?.sessionId || args?.id;
|
|
19931
|
+
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
19932
|
+
const ok = await h.agentStream.switchAgentSession(h.getCdp(), agentType, sessionId);
|
|
19933
|
+
return { success: ok };
|
|
19934
|
+
}
|
|
19935
|
+
async function handleAgentStreamFocus(h, args) {
|
|
19936
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
19937
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
19938
|
+
if (!agentType) return { success: false, error: "agentType required" };
|
|
19939
|
+
await h.agentStream.ensureAgentPanelOpen(agentType, h.currentIdeType);
|
|
19940
|
+
const ok = await h.agentStream.focusAgentEditor(h.getCdp(), agentType);
|
|
19941
|
+
return { success: ok };
|
|
19942
|
+
}
|
|
19943
|
+
function handlePtyInput(h, args) {
|
|
19944
|
+
const { cliType, data } = args || {};
|
|
19945
|
+
if (!data) return { success: false, error: "data required" };
|
|
19946
|
+
if (h.ctx.adapters) {
|
|
19947
|
+
const targetCli = cliType || "";
|
|
19948
|
+
if (!targetCli && h.ctx.adapters.size > 0) {
|
|
19949
|
+
const first = h.ctx.adapters.values().next().value;
|
|
19950
|
+
if (first && typeof first.writeRaw === "function") {
|
|
19951
|
+
first.writeRaw(data);
|
|
20266
19952
|
return { success: true };
|
|
20267
19953
|
}
|
|
20268
|
-
|
|
20269
|
-
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
|
|
19954
|
+
}
|
|
19955
|
+
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
19956
|
+
if (directAdapter && typeof directAdapter.writeRaw === "function") {
|
|
19957
|
+
directAdapter.writeRaw(data);
|
|
19958
|
+
return { success: true };
|
|
19959
|
+
}
|
|
19960
|
+
for (const [, adapter] of h.ctx.adapters) {
|
|
19961
|
+
if (adapter.cliType === targetCli && typeof adapter.writeRaw === "function") {
|
|
19962
|
+
adapter.writeRaw(data);
|
|
19963
|
+
return { success: true };
|
|
20273
19964
|
}
|
|
20274
|
-
|
|
20275
|
-
|
|
20276
|
-
|
|
20277
|
-
|
|
20278
|
-
}
|
|
19965
|
+
}
|
|
19966
|
+
for (const [key, adapter] of h.ctx.adapters) {
|
|
19967
|
+
if ((key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.writeRaw === "function") {
|
|
19968
|
+
adapter.writeRaw(data);
|
|
19969
|
+
return { success: true };
|
|
20279
19970
|
}
|
|
20280
19971
|
}
|
|
20281
|
-
return { success: false, error: `CLI adapter not found: ${cliType}` };
|
|
20282
19972
|
}
|
|
20283
|
-
|
|
20284
|
-
|
|
20285
|
-
|
|
20286
|
-
|
|
20287
|
-
|
|
20288
|
-
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
|
|
20295
|
-
|
|
20296
|
-
|
|
20297
|
-
|
|
19973
|
+
return { success: false, error: `CLI adapter not found: ${cliType}` };
|
|
19974
|
+
}
|
|
19975
|
+
function handlePtyResize(h, args) {
|
|
19976
|
+
const { cliType, cols, rows, force } = args || {};
|
|
19977
|
+
if (!cols || !rows) return { success: false, error: "cols and rows required" };
|
|
19978
|
+
if (h.ctx.adapters) {
|
|
19979
|
+
const targetCli = cliType || "";
|
|
19980
|
+
if (!targetCli && h.ctx.adapters.size > 0) {
|
|
19981
|
+
const first = h.ctx.adapters.values().next().value;
|
|
19982
|
+
if (first && typeof first.resize === "function") {
|
|
19983
|
+
if (force) {
|
|
19984
|
+
first.resize(cols - 1, rows);
|
|
19985
|
+
setTimeout(() => first.resize(cols, rows), 50);
|
|
19986
|
+
} else {
|
|
19987
|
+
first.resize(cols, rows);
|
|
20298
19988
|
}
|
|
19989
|
+
return { success: true };
|
|
19990
|
+
}
|
|
19991
|
+
}
|
|
19992
|
+
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
19993
|
+
if (directAdapter && typeof directAdapter.resize === "function") {
|
|
19994
|
+
if (force) {
|
|
19995
|
+
directAdapter.resize(cols - 1, rows);
|
|
19996
|
+
setTimeout(() => directAdapter.resize(cols, rows), 50);
|
|
19997
|
+
} else {
|
|
19998
|
+
directAdapter.resize(cols, rows);
|
|
20299
19999
|
}
|
|
20300
|
-
|
|
20301
|
-
|
|
20000
|
+
return { success: true };
|
|
20001
|
+
}
|
|
20002
|
+
for (const [key, adapter] of h.ctx.adapters) {
|
|
20003
|
+
if ((adapter.cliType === targetCli || key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.resize === "function") {
|
|
20302
20004
|
if (force) {
|
|
20303
|
-
|
|
20304
|
-
setTimeout(() =>
|
|
20005
|
+
adapter.resize(cols - 1, rows);
|
|
20006
|
+
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
20305
20007
|
} else {
|
|
20306
|
-
|
|
20008
|
+
adapter.resize(cols, rows);
|
|
20307
20009
|
}
|
|
20308
20010
|
return { success: true };
|
|
20309
20011
|
}
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20313
|
-
|
|
20314
|
-
|
|
20315
|
-
|
|
20316
|
-
|
|
20317
|
-
|
|
20318
|
-
|
|
20012
|
+
}
|
|
20013
|
+
}
|
|
20014
|
+
return { success: false, error: `CLI adapter not found: ${cliType}` };
|
|
20015
|
+
}
|
|
20016
|
+
function handleGetProviderSettings(h, args) {
|
|
20017
|
+
const loader = h.ctx.providerLoader;
|
|
20018
|
+
const { providerType } = args || {};
|
|
20019
|
+
if (providerType) {
|
|
20020
|
+
const schema = loader?.getPublicSettings(providerType) || [];
|
|
20021
|
+
const values = loader?.getSettings(providerType) || {};
|
|
20022
|
+
return { success: true, providerType, schema, values };
|
|
20023
|
+
}
|
|
20024
|
+
const allSettings = loader?.getAllPublicSettings() || {};
|
|
20025
|
+
const allValues = {};
|
|
20026
|
+
for (const type of Object.keys(allSettings)) {
|
|
20027
|
+
allValues[type] = loader?.getSettings(type) || {};
|
|
20028
|
+
}
|
|
20029
|
+
return { success: true, settings: allSettings, values: allValues };
|
|
20030
|
+
}
|
|
20031
|
+
function handleSetProviderSetting(h, args) {
|
|
20032
|
+
const loader = h.ctx.providerLoader;
|
|
20033
|
+
const { providerType, key, value } = args || {};
|
|
20034
|
+
if (!providerType || !key || value === void 0) {
|
|
20035
|
+
return { success: false, error: "providerType, key, and value are required" };
|
|
20036
|
+
}
|
|
20037
|
+
const result = loader?.setSetting(providerType, key, value);
|
|
20038
|
+
if (result) {
|
|
20039
|
+
if (h.ctx.instanceManager) {
|
|
20040
|
+
const allSettings = loader?.getSettings(providerType) || {};
|
|
20041
|
+
const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
|
|
20042
|
+
LOG5.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
|
|
20043
|
+
}
|
|
20044
|
+
return { success: true, providerType, key, value };
|
|
20045
|
+
}
|
|
20046
|
+
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
20047
|
+
}
|
|
20048
|
+
async function handleExtensionScript(h, args, scriptName) {
|
|
20049
|
+
const { agentType, ideType } = args || {};
|
|
20050
|
+
LOG5.info("Command", `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType} _currentIdeType=${h.currentIdeType}`);
|
|
20051
|
+
if (!agentType) return { success: false, error: "agentType is required" };
|
|
20052
|
+
const loader = h.ctx.providerLoader;
|
|
20053
|
+
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
20054
|
+
const provider = loader.resolve(agentType);
|
|
20055
|
+
if (!provider) return { success: false, error: `Provider not found: ${agentType}` };
|
|
20056
|
+
const webviewScriptName = `webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}`;
|
|
20057
|
+
const hasWebviewScript = provider.category === "ide" && !!provider.scripts?.[webviewScriptName];
|
|
20058
|
+
const actualScriptName = hasWebviewScript ? webviewScriptName : scriptName;
|
|
20059
|
+
if (!provider.scripts?.[actualScriptName]) {
|
|
20060
|
+
return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
|
|
20061
|
+
}
|
|
20062
|
+
const scriptFn = provider.scripts[actualScriptName];
|
|
20063
|
+
const scriptCode = scriptFn(args);
|
|
20064
|
+
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
20065
|
+
const cdpKey = provider.category === "ide" ? h.currentIdeType || agentType : h.currentIdeType || ideType;
|
|
20066
|
+
LOG5.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
20067
|
+
const cdp = h.getCdp(cdpKey);
|
|
20068
|
+
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
20069
|
+
try {
|
|
20070
|
+
let result;
|
|
20071
|
+
if (provider.category === "extension") {
|
|
20072
|
+
const sessions = cdp.getAgentSessions();
|
|
20073
|
+
let targetSessionId = null;
|
|
20074
|
+
for (const [sessionId, target] of sessions) {
|
|
20075
|
+
if (target.agentType === agentType) {
|
|
20076
|
+
targetSessionId = sessionId;
|
|
20077
|
+
break;
|
|
20319
20078
|
}
|
|
20320
20079
|
}
|
|
20080
|
+
if (!targetSessionId) {
|
|
20081
|
+
return { success: false, error: `No active session found for ${agentType}` };
|
|
20082
|
+
}
|
|
20083
|
+
result = await cdp.evaluateInSession(targetSessionId, scriptCode);
|
|
20084
|
+
} else if (hasWebviewScript && cdp.evaluateInWebviewFrame) {
|
|
20085
|
+
const matchText = provider.webviewMatchText;
|
|
20086
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
20087
|
+
result = await cdp.evaluateInWebviewFrame(scriptCode, matchFn);
|
|
20088
|
+
} else {
|
|
20089
|
+
result = await cdp.evaluate(scriptCode, 3e4);
|
|
20090
|
+
}
|
|
20091
|
+
if (typeof result === "string") {
|
|
20092
|
+
try {
|
|
20093
|
+
const parsed = JSON.parse(result);
|
|
20094
|
+
return { success: true, ...parsed };
|
|
20095
|
+
} catch {
|
|
20096
|
+
return { success: true, result };
|
|
20097
|
+
}
|
|
20098
|
+
}
|
|
20099
|
+
return { success: true, result };
|
|
20100
|
+
} catch (e) {
|
|
20101
|
+
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
20102
|
+
}
|
|
20103
|
+
}
|
|
20104
|
+
function handleGetIdeExtensions(h, args) {
|
|
20105
|
+
const { ideType } = args || {};
|
|
20106
|
+
const loader = h.ctx.providerLoader;
|
|
20107
|
+
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
20108
|
+
const allExtProviders = loader.getByCategory?.("extension") || [];
|
|
20109
|
+
const config2 = loadConfig3();
|
|
20110
|
+
if (ideType) {
|
|
20111
|
+
const extensions = allExtProviders.map((p) => ({
|
|
20112
|
+
type: p.type,
|
|
20113
|
+
name: p.name,
|
|
20114
|
+
extensionId: p.extensionId,
|
|
20115
|
+
enabled: config2.ideSettings?.[ideType]?.extensions?.[p.type]?.enabled === true
|
|
20116
|
+
}));
|
|
20117
|
+
return { success: true, ideType, extensions };
|
|
20118
|
+
}
|
|
20119
|
+
const connectedIdes = [...h.ctx.cdpManagers?.keys?.() || []];
|
|
20120
|
+
const result = {};
|
|
20121
|
+
for (const ide of connectedIdes) {
|
|
20122
|
+
result[ide] = allExtProviders.map((p) => ({
|
|
20123
|
+
type: p.type,
|
|
20124
|
+
name: p.name,
|
|
20125
|
+
extensionId: p.extensionId,
|
|
20126
|
+
enabled: config2.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
|
|
20127
|
+
}));
|
|
20128
|
+
}
|
|
20129
|
+
return { success: true, ides: result };
|
|
20130
|
+
}
|
|
20131
|
+
function handleSetIdeExtension(h, args) {
|
|
20132
|
+
const { ideType, extensionType, enabled } = args || {};
|
|
20133
|
+
if (!ideType || !extensionType || enabled === void 0) {
|
|
20134
|
+
return { success: false, error: "ideType, extensionType, and enabled are required" };
|
|
20135
|
+
}
|
|
20136
|
+
const loader = h.ctx.providerLoader;
|
|
20137
|
+
if (!loader?.setIdeExtensionEnabled) {
|
|
20138
|
+
return { success: false, error: "ProviderLoader not initialized" };
|
|
20139
|
+
}
|
|
20140
|
+
const ok = loader.setIdeExtensionEnabled(ideType, extensionType, !!enabled);
|
|
20141
|
+
if (ok) {
|
|
20142
|
+
return { success: true, ideType, extensionType, enabled: !!enabled };
|
|
20143
|
+
}
|
|
20144
|
+
return { success: false, error: "Failed to save setting" };
|
|
20145
|
+
}
|
|
20146
|
+
var DaemonCommandHandler = class {
|
|
20147
|
+
_ctx;
|
|
20148
|
+
_agentStream = null;
|
|
20149
|
+
domHandlers;
|
|
20150
|
+
_historyWriter;
|
|
20151
|
+
/** Current IDE type extracted from command args (per-request) */
|
|
20152
|
+
_currentIdeType;
|
|
20153
|
+
/** Current provider type — agentType priority, ideType use */
|
|
20154
|
+
_currentProviderType;
|
|
20155
|
+
constructor(ctx) {
|
|
20156
|
+
this._ctx = ctx;
|
|
20157
|
+
this.domHandlers = new CdpDomHandlers((ideType) => this.getCdp(ideType));
|
|
20158
|
+
this._historyWriter = new ChatHistoryWriter();
|
|
20159
|
+
}
|
|
20160
|
+
// ─── CommandHelpers implementation ─────────────────
|
|
20161
|
+
get ctx() {
|
|
20162
|
+
return this._ctx;
|
|
20163
|
+
}
|
|
20164
|
+
get agentStream() {
|
|
20165
|
+
return this._agentStream;
|
|
20166
|
+
}
|
|
20167
|
+
get historyWriter() {
|
|
20168
|
+
return this._historyWriter;
|
|
20169
|
+
}
|
|
20170
|
+
get currentIdeType() {
|
|
20171
|
+
return this._currentIdeType;
|
|
20172
|
+
}
|
|
20173
|
+
get currentProviderType() {
|
|
20174
|
+
return this._currentProviderType;
|
|
20175
|
+
}
|
|
20176
|
+
/** Get CDP manager for a specific ideType.
|
|
20177
|
+
* Returns null if no match — never falls back to another IDE. */
|
|
20178
|
+
getCdp(ideType) {
|
|
20179
|
+
const key = ideType || this._currentIdeType;
|
|
20180
|
+
if (!key) return null;
|
|
20181
|
+
const m = this._ctx.cdpManagers.get(key.toLowerCase());
|
|
20182
|
+
if (m?.isConnected) return m;
|
|
20183
|
+
return null;
|
|
20184
|
+
}
|
|
20185
|
+
/**
|
|
20186
|
+
* Get provider module — _currentProviderType (agentType priority) use.
|
|
20187
|
+
*/
|
|
20188
|
+
getProvider(overrideType) {
|
|
20189
|
+
const key = overrideType || this._currentProviderType || this._currentIdeType;
|
|
20190
|
+
if (!key || !this._ctx.providerLoader) return void 0;
|
|
20191
|
+
const result = this._ctx.providerLoader.resolve(key);
|
|
20192
|
+
if (result) return result;
|
|
20193
|
+
const baseType = key.split("_")[0];
|
|
20194
|
+
if (baseType !== key) return this._ctx.providerLoader.resolve(baseType);
|
|
20195
|
+
return void 0;
|
|
20196
|
+
}
|
|
20197
|
+
/** Get a provider script by name from ProviderLoader. */
|
|
20198
|
+
getProviderScript(scriptName, params, ideType) {
|
|
20199
|
+
const provider = this.getProvider(ideType);
|
|
20200
|
+
if (provider?.scripts) {
|
|
20201
|
+
const fn = provider.scripts[scriptName];
|
|
20202
|
+
if (typeof fn === "function") {
|
|
20203
|
+
const firstVal = params ? Object.values(params)[0] : void 0;
|
|
20204
|
+
const script = firstVal ? fn(firstVal) : fn();
|
|
20205
|
+
if (script) return script;
|
|
20206
|
+
}
|
|
20207
|
+
}
|
|
20208
|
+
return null;
|
|
20209
|
+
}
|
|
20210
|
+
/**
|
|
20211
|
+
* per-category CDP script execute:
|
|
20212
|
+
* IDE → cdp.evaluate(script) (main window)
|
|
20213
|
+
* Extension → cdp.evaluateInSession(sessionId, script) (webview)
|
|
20214
|
+
*/
|
|
20215
|
+
async evaluateProviderScript(scriptName, params, timeout = 3e4) {
|
|
20216
|
+
const provider = this.getProvider();
|
|
20217
|
+
const script = this.getProviderScript(scriptName, params);
|
|
20218
|
+
if (!script) return null;
|
|
20219
|
+
const cdp = this.getCdp();
|
|
20220
|
+
if (!cdp?.isConnected) return null;
|
|
20221
|
+
if (provider?.category === "extension") {
|
|
20222
|
+
let sessionId = this.getExtensionSessionId(provider);
|
|
20223
|
+
if (!sessionId && this._agentStream) {
|
|
20224
|
+
await this._agentStream.switchActiveAgent(cdp, provider.type);
|
|
20225
|
+
await this._agentStream.syncAgentSessions(cdp);
|
|
20226
|
+
sessionId = this.getExtensionSessionId(provider);
|
|
20227
|
+
}
|
|
20228
|
+
if (!sessionId) return null;
|
|
20229
|
+
const result2 = await cdp.evaluateInSession(sessionId, script, timeout);
|
|
20230
|
+
return { result: result2, category: "extension" };
|
|
20321
20231
|
}
|
|
20322
|
-
|
|
20232
|
+
const result = await cdp.evaluate(script, timeout);
|
|
20233
|
+
return { result, category: provider?.category || "ide" };
|
|
20323
20234
|
}
|
|
20324
|
-
|
|
20325
|
-
|
|
20326
|
-
const
|
|
20327
|
-
if (
|
|
20328
|
-
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
const allSettings = this.ctx.providerLoader?.getAllPublicSettings?.() || {};
|
|
20333
|
-
const allValues = {};
|
|
20334
|
-
for (const type of Object.keys(allSettings)) {
|
|
20335
|
-
allValues[type] = this.ctx.providerLoader?.getSettings?.(type) || {};
|
|
20235
|
+
/** CLI adapter search */
|
|
20236
|
+
getCliAdapter(type) {
|
|
20237
|
+
const target = type || this._currentIdeType;
|
|
20238
|
+
if (!target || !this._ctx.adapters) return null;
|
|
20239
|
+
for (const [key, adapter] of this._ctx.adapters.entries()) {
|
|
20240
|
+
if (adapter.cliType === target || key.startsWith(target)) {
|
|
20241
|
+
return adapter;
|
|
20242
|
+
}
|
|
20336
20243
|
}
|
|
20337
|
-
return
|
|
20244
|
+
return null;
|
|
20338
20245
|
}
|
|
20339
|
-
|
|
20340
|
-
|
|
20341
|
-
if (
|
|
20342
|
-
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20246
|
+
// ─── Private helpers ──────────────────────────────
|
|
20247
|
+
getExtensionSessionId(provider) {
|
|
20248
|
+
if (provider.category !== "extension" || !this._agentStream) return null;
|
|
20249
|
+
const managed = this._agentStream.getManagedAgent(provider.type);
|
|
20250
|
+
return managed?.sessionId || null;
|
|
20251
|
+
}
|
|
20252
|
+
/** Extract ideType from _targetInstance */
|
|
20253
|
+
extractIdeType(args) {
|
|
20254
|
+
if (args?._targetInstance) {
|
|
20255
|
+
let raw = args._targetInstance;
|
|
20256
|
+
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
20257
|
+
const cliMatch = raw.match(/:cli:(.+)$/);
|
|
20258
|
+
const acpMatch = raw.match(/:acp:(.+)$/);
|
|
20259
|
+
if (ideMatch) raw = ideMatch[1];
|
|
20260
|
+
else if (cliMatch) raw = cliMatch[1];
|
|
20261
|
+
else if (acpMatch) raw = acpMatch[1];
|
|
20262
|
+
if (this._ctx.instanceIdMap?.has(raw)) {
|
|
20263
|
+
return this._ctx.instanceIdMap.get(raw);
|
|
20350
20264
|
}
|
|
20351
|
-
|
|
20265
|
+
const lastUnderscore = raw.lastIndexOf("_");
|
|
20266
|
+
if (lastUnderscore > 0) return raw.substring(0, lastUnderscore);
|
|
20267
|
+
return raw;
|
|
20352
20268
|
}
|
|
20353
|
-
return
|
|
20269
|
+
return void 0;
|
|
20354
20270
|
}
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20360
|
-
|
|
20361
|
-
|
|
20362
|
-
|
|
20363
|
-
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
20367
|
-
const provider = loader.resolve(agentType);
|
|
20368
|
-
if (!provider) return { success: false, error: `Provider not found: ${agentType}` };
|
|
20369
|
-
const webviewScriptName = `webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}`;
|
|
20370
|
-
const hasWebviewScript = provider.category === "ide" && !!provider.scripts?.[webviewScriptName];
|
|
20371
|
-
const actualScriptName = hasWebviewScript ? webviewScriptName : scriptName;
|
|
20372
|
-
if (!provider.scripts?.[actualScriptName]) {
|
|
20373
|
-
return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
|
|
20374
|
-
}
|
|
20375
|
-
const scriptFn = provider.scripts[actualScriptName];
|
|
20376
|
-
const scriptCode = scriptFn(args);
|
|
20377
|
-
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
20378
|
-
const cdpKey = provider.category === "ide" ? this._currentIdeType || agentType : this._currentIdeType || ideType;
|
|
20379
|
-
LOG4.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
20380
|
-
const cdp = this.getCdp(cdpKey);
|
|
20381
|
-
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
20382
|
-
try {
|
|
20383
|
-
let result;
|
|
20384
|
-
if (provider.category === "extension") {
|
|
20385
|
-
const sessions = cdp.getAgentSessions();
|
|
20386
|
-
let targetSessionId = null;
|
|
20387
|
-
for (const [sessionId, target] of sessions) {
|
|
20388
|
-
if (target.agentType === agentType) {
|
|
20389
|
-
targetSessionId = sessionId;
|
|
20390
|
-
break;
|
|
20391
|
-
}
|
|
20392
|
-
}
|
|
20393
|
-
if (!targetSessionId) {
|
|
20394
|
-
return { success: false, error: `No active session found for ${agentType}` };
|
|
20395
|
-
}
|
|
20396
|
-
result = await cdp.evaluateInSession(targetSessionId, scriptCode);
|
|
20397
|
-
} else if (hasWebviewScript && cdp.evaluateInWebviewFrame) {
|
|
20398
|
-
const matchText = provider.webviewMatchText;
|
|
20399
|
-
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
20400
|
-
result = await cdp.evaluateInWebviewFrame(scriptCode, matchFn);
|
|
20401
|
-
} else {
|
|
20402
|
-
result = await cdp.evaluate(scriptCode, 3e4);
|
|
20271
|
+
setAgentStreamManager(manager) {
|
|
20272
|
+
this._agentStream = manager;
|
|
20273
|
+
}
|
|
20274
|
+
// ─── Command Dispatcher ──────────────────────────
|
|
20275
|
+
async handle(cmd, args) {
|
|
20276
|
+
this._currentIdeType = this.extractIdeType(args);
|
|
20277
|
+
this._currentProviderType = args?.agentType || args?.providerType || this._currentIdeType;
|
|
20278
|
+
if (!this._currentIdeType && !this._currentProviderType) {
|
|
20279
|
+
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
20280
|
+
if (cdpCommands.includes(cmd)) {
|
|
20281
|
+
return { success: false, error: "No ideType specified \u2014 cannot route command" };
|
|
20403
20282
|
}
|
|
20404
|
-
|
|
20405
|
-
|
|
20406
|
-
|
|
20407
|
-
|
|
20408
|
-
|
|
20409
|
-
|
|
20283
|
+
}
|
|
20284
|
+
try {
|
|
20285
|
+
return await this.dispatch(cmd, args);
|
|
20286
|
+
} catch (e) {
|
|
20287
|
+
LOG5.error("Command", `[${cmd}] Unhandled error: ${e?.message || e}`);
|
|
20288
|
+
return { success: false, error: `Internal error: ${e?.message || "unknown"}` };
|
|
20289
|
+
}
|
|
20290
|
+
}
|
|
20291
|
+
async dispatch(cmd, args) {
|
|
20292
|
+
switch (cmd) {
|
|
20293
|
+
// ─── Chat commands (chat-commands.ts) ───────────────
|
|
20294
|
+
case "read_chat":
|
|
20295
|
+
return handleReadChat(this, args);
|
|
20296
|
+
case "chat_history":
|
|
20297
|
+
return handleChatHistory(this, args);
|
|
20298
|
+
case "send_chat":
|
|
20299
|
+
return handleSendChat(this, args);
|
|
20300
|
+
case "list_chats":
|
|
20301
|
+
return handleListChats(this, args);
|
|
20302
|
+
case "new_chat":
|
|
20303
|
+
return handleNewChat(this, args);
|
|
20304
|
+
case "switch_chat":
|
|
20305
|
+
return handleSwitchChat(this, args);
|
|
20306
|
+
case "set_mode":
|
|
20307
|
+
return handleSetMode(this, args);
|
|
20308
|
+
case "change_model":
|
|
20309
|
+
return handleChangeModel(this, args);
|
|
20310
|
+
case "set_thought_level":
|
|
20311
|
+
return handleSetThoughtLevel(this, args);
|
|
20312
|
+
case "resolve_action":
|
|
20313
|
+
return handleResolveAction(this, args);
|
|
20314
|
+
// ─── CDP commands (cdp-commands.ts) ───────────────
|
|
20315
|
+
case "cdp_eval":
|
|
20316
|
+
return handleCdpEval(this, args);
|
|
20317
|
+
case "cdp_screenshot":
|
|
20318
|
+
case "screenshot":
|
|
20319
|
+
return handleScreenshot(this, args);
|
|
20320
|
+
case "cdp_command_exec":
|
|
20321
|
+
return handleCdpCommand(this, args);
|
|
20322
|
+
case "cdp_batch":
|
|
20323
|
+
return handleCdpBatch(this, args);
|
|
20324
|
+
case "cdp_remote_action":
|
|
20325
|
+
return handleCdpRemoteAction(this, args);
|
|
20326
|
+
case "cdp_discover_agents":
|
|
20327
|
+
return handleDiscoverAgents(this, args);
|
|
20328
|
+
case "cdp_dom_dump":
|
|
20329
|
+
return this.domHandlers.handleDomDump(args);
|
|
20330
|
+
case "cdp_dom_query":
|
|
20331
|
+
return this.domHandlers.handleDomQuery(args);
|
|
20332
|
+
case "cdp_dom_debug":
|
|
20333
|
+
return this.domHandlers.handleDomDebug(args);
|
|
20334
|
+
// ─── File commands (cdp-commands.ts) ──────────────
|
|
20335
|
+
case "file_read":
|
|
20336
|
+
return handleFileRead(this, args);
|
|
20337
|
+
case "file_write":
|
|
20338
|
+
return handleFileWrite(this, args);
|
|
20339
|
+
case "file_list":
|
|
20340
|
+
return handleFileList(this, args);
|
|
20341
|
+
case "file_list_browse":
|
|
20342
|
+
return handleFileListBrowse(this, args);
|
|
20343
|
+
// ─── VSCode API commands (not available) ────
|
|
20344
|
+
case "vscode_command_exec":
|
|
20345
|
+
case "execute_vscode_command": {
|
|
20346
|
+
const resolvedCmd = args?.commandId || args?.command;
|
|
20347
|
+
if (resolvedCmd === "adhdev.captureCdpScreenshot") {
|
|
20348
|
+
return handleScreenshot(this, args);
|
|
20410
20349
|
}
|
|
20350
|
+
return { success: false, error: `VSCode command not available: ${resolvedCmd || cmd}` };
|
|
20411
20351
|
}
|
|
20412
|
-
|
|
20413
|
-
|
|
20414
|
-
|
|
20352
|
+
case "get_open_editors":
|
|
20353
|
+
case "open_tab":
|
|
20354
|
+
case "close_tab":
|
|
20355
|
+
case "open_folder":
|
|
20356
|
+
case "open_folder_picker":
|
|
20357
|
+
case "open_recent":
|
|
20358
|
+
case "get_commands":
|
|
20359
|
+
return { success: false, error: `${cmd} requires bridge-extension (removed)` };
|
|
20360
|
+
case "get_recent_workspaces":
|
|
20361
|
+
return this.handleGetRecentWorkspaces(args);
|
|
20362
|
+
// ─── Script manage ───────────────────
|
|
20363
|
+
case "refresh_scripts":
|
|
20364
|
+
return this.handleRefreshScripts(args);
|
|
20365
|
+
// ─── Stream commands (stream-commands.ts) ───────────
|
|
20366
|
+
case "agent_stream_switch":
|
|
20367
|
+
return handleAgentStreamSwitch(this, args);
|
|
20368
|
+
case "agent_stream_read":
|
|
20369
|
+
return handleAgentStreamRead(this, args);
|
|
20370
|
+
case "agent_stream_send":
|
|
20371
|
+
return handleAgentStreamSend(this, args);
|
|
20372
|
+
case "agent_stream_resolve":
|
|
20373
|
+
return handleAgentStreamResolve(this, args);
|
|
20374
|
+
case "agent_stream_new":
|
|
20375
|
+
return handleAgentStreamNew(this, args);
|
|
20376
|
+
case "agent_stream_list_chats":
|
|
20377
|
+
return handleAgentStreamListChats(this, args);
|
|
20378
|
+
case "agent_stream_switch_session":
|
|
20379
|
+
return handleAgentStreamSwitchSession(this, args);
|
|
20380
|
+
case "agent_stream_focus":
|
|
20381
|
+
return handleAgentStreamFocus(this, args);
|
|
20382
|
+
// ─── PTY Raw I/O (stream-commands.ts) ─────────
|
|
20383
|
+
case "pty_input":
|
|
20384
|
+
return handlePtyInput(this, args);
|
|
20385
|
+
case "pty_resize":
|
|
20386
|
+
return handlePtyResize(this, args);
|
|
20387
|
+
// ─── Provider Settings (stream-commands.ts) ──────────
|
|
20388
|
+
case "get_provider_settings":
|
|
20389
|
+
return handleGetProviderSettings(this, args);
|
|
20390
|
+
case "set_provider_setting":
|
|
20391
|
+
return handleSetProviderSetting(this, args);
|
|
20392
|
+
// ─── IDE Extension Settings (stream-commands.ts) ──────────
|
|
20393
|
+
case "get_ide_extensions":
|
|
20394
|
+
return handleGetIdeExtensions(this, args);
|
|
20395
|
+
case "set_ide_extension":
|
|
20396
|
+
return handleSetIdeExtension(this, args);
|
|
20397
|
+
// ─── Extension Model / Mode Control (stream-commands.ts) ──────────
|
|
20398
|
+
case "list_extension_models":
|
|
20399
|
+
return handleExtensionScript(this, args, "listModels");
|
|
20400
|
+
case "set_extension_model":
|
|
20401
|
+
return handleExtensionScript(this, args, "setModel");
|
|
20402
|
+
case "list_extension_modes":
|
|
20403
|
+
return handleExtensionScript(this, args, "listModes");
|
|
20404
|
+
case "set_extension_mode":
|
|
20405
|
+
return handleExtensionScript(this, args, "setMode");
|
|
20406
|
+
default:
|
|
20407
|
+
return { success: false, error: `Unknown command: ${cmd}` };
|
|
20415
20408
|
}
|
|
20416
20409
|
}
|
|
20417
|
-
// ───
|
|
20418
|
-
|
|
20419
|
-
const { ideType } = args || {};
|
|
20420
|
-
const loader = this.ctx.providerLoader;
|
|
20421
|
-
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
20422
|
-
const allExtProviders = loader.getByCategory?.("extension") || [];
|
|
20410
|
+
// ─── Misc (kept in handler — too small to extract) ───────
|
|
20411
|
+
async handleGetRecentWorkspaces(args) {
|
|
20423
20412
|
const config2 = loadConfig3();
|
|
20424
|
-
|
|
20425
|
-
|
|
20426
|
-
type: p.type,
|
|
20427
|
-
name: p.name,
|
|
20428
|
-
extensionId: p.extensionId,
|
|
20429
|
-
enabled: config2.ideSettings?.[ideType]?.extensions?.[p.type]?.enabled === true
|
|
20430
|
-
}));
|
|
20431
|
-
return { success: true, ideType, extensions };
|
|
20432
|
-
}
|
|
20433
|
-
const connectedIdes = [...this.ctx.cdpManagers?.keys?.() || []];
|
|
20434
|
-
const result = {};
|
|
20435
|
-
for (const ide of connectedIdes) {
|
|
20436
|
-
result[ide] = allExtProviders.map((p) => ({
|
|
20437
|
-
type: p.type,
|
|
20438
|
-
name: p.name,
|
|
20439
|
-
extensionId: p.extensionId,
|
|
20440
|
-
enabled: config2.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
|
|
20441
|
-
}));
|
|
20442
|
-
}
|
|
20443
|
-
return { success: true, ides: result };
|
|
20413
|
+
const cliRecent = config2.recentCliWorkspaces || [];
|
|
20414
|
+
return { success: true, result: cliRecent };
|
|
20444
20415
|
}
|
|
20445
|
-
|
|
20446
|
-
|
|
20447
|
-
|
|
20448
|
-
return { success:
|
|
20449
|
-
}
|
|
20450
|
-
const loader = this.ctx.providerLoader;
|
|
20451
|
-
if (!loader?.setIdeExtensionEnabled) {
|
|
20452
|
-
return { success: false, error: "ProviderLoader not initialized" };
|
|
20453
|
-
}
|
|
20454
|
-
const ok = loader.setIdeExtensionEnabled(ideType, extensionType, !!enabled);
|
|
20455
|
-
if (ok) {
|
|
20456
|
-
return { success: true, ideType, extensionType, enabled: !!enabled };
|
|
20416
|
+
async handleRefreshScripts(_args) {
|
|
20417
|
+
if (this._ctx.providerLoader) {
|
|
20418
|
+
this._ctx.providerLoader.reload();
|
|
20419
|
+
return { success: true };
|
|
20457
20420
|
}
|
|
20458
|
-
return { success: false, error: "
|
|
20421
|
+
return { success: false, error: "ProviderLoader not initialized" };
|
|
20459
20422
|
}
|
|
20460
20423
|
};
|
|
20461
20424
|
var import_child_process3 = require("child_process");
|
|
@@ -20488,7 +20451,7 @@ var require_dist = __commonJS({
|
|
|
20488
20451
|
}
|
|
20489
20452
|
this.userDir = options?.userDir || path4.join(os5.homedir(), ".adhdev", "providers");
|
|
20490
20453
|
this.upstreamDir = path4.join(this.userDir, ".upstream");
|
|
20491
|
-
this.logFn = options?.logFn ||
|
|
20454
|
+
this.logFn = options?.logFn || LOG5.forComponent("Provider").asLogFn();
|
|
20492
20455
|
}
|
|
20493
20456
|
log(msg) {
|
|
20494
20457
|
this.logFn(`[ProviderLoader] ${msg}`);
|
|
@@ -21932,18 +21895,18 @@ var require_dist = __commonJS({
|
|
|
21932
21895
|
case "launch_ide": {
|
|
21933
21896
|
const launchArgs = { ...args, ideId: args?.ideId || args?.ideType };
|
|
21934
21897
|
const ideKey = launchArgs.ideId;
|
|
21935
|
-
|
|
21898
|
+
LOG5.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
21936
21899
|
const result = await launchWithCdp(launchArgs);
|
|
21937
21900
|
if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
|
|
21938
|
-
const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) :
|
|
21901
|
+
const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG5.forComponent(`CDP:${result.ideId}`).asLogFn();
|
|
21939
21902
|
const provider = this.deps.providerLoader.getMeta(result.ideId);
|
|
21940
21903
|
const manager = new DaemonCdpManager2(result.port, logFn, void 0, provider?.targetFilter);
|
|
21941
21904
|
const connected = await manager.connect();
|
|
21942
21905
|
if (connected) {
|
|
21943
21906
|
registerExtensionProviders(this.deps.providerLoader, manager, result.ideId);
|
|
21944
21907
|
this.deps.cdpManagers.set(result.ideId, manager);
|
|
21945
|
-
|
|
21946
|
-
|
|
21908
|
+
LOG5.info("CDP", `Connected: ${result.ideId} (port ${result.port})`);
|
|
21909
|
+
LOG5.info("CDP", `${this.deps.cdpManagers.size} IDE(s) connected`);
|
|
21947
21910
|
this.deps.onCdpManagerCreated?.(result.ideId, manager);
|
|
21948
21911
|
}
|
|
21949
21912
|
}
|
|
@@ -21969,7 +21932,7 @@ var require_dist = __commonJS({
|
|
|
21969
21932
|
} catch {
|
|
21970
21933
|
}
|
|
21971
21934
|
this.deps.cdpManagers.delete(ideType);
|
|
21972
|
-
|
|
21935
|
+
LOG5.info("StopIDE", `CDP disconnected: ${ideType}`);
|
|
21973
21936
|
}
|
|
21974
21937
|
const instanceKey = `ide:${ideType}`;
|
|
21975
21938
|
const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
|
|
@@ -21983,10 +21946,10 @@ var require_dist = __commonJS({
|
|
|
21983
21946
|
}
|
|
21984
21947
|
}
|
|
21985
21948
|
this.deps.instanceManager.removeInstance(instanceKey);
|
|
21986
|
-
|
|
21949
|
+
LOG5.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
21987
21950
|
}
|
|
21988
21951
|
this.deps.onStatusChange?.();
|
|
21989
|
-
|
|
21952
|
+
LOG5.info("StopIDE", `IDE stopped: ${ideType}`);
|
|
21990
21953
|
}
|
|
21991
21954
|
};
|
|
21992
21955
|
var os8 = __toESM2(require("os"));
|
|
@@ -22002,23 +21965,23 @@ var require_dist = __commonJS({
|
|
|
22002
21965
|
p2pTimer = null;
|
|
22003
21966
|
constructor(deps, opts) {
|
|
22004
21967
|
this.deps = deps;
|
|
22005
|
-
this.log = opts?.logFn ||
|
|
21968
|
+
this.log = opts?.logFn || LOG5.forComponent("Status").asLogFn();
|
|
22006
21969
|
}
|
|
22007
21970
|
// ─── Lifecycle ───────────────────────────────────
|
|
22008
21971
|
startReporting() {
|
|
22009
21972
|
setTimeout(() => {
|
|
22010
|
-
this.sendUnifiedStatusReport().catch((e) =>
|
|
21973
|
+
this.sendUnifiedStatusReport().catch((e) => LOG5.warn("Status", `Initial report failed: ${e?.message}`));
|
|
22011
21974
|
}, 2e3);
|
|
22012
21975
|
const scheduleServerReport = () => {
|
|
22013
21976
|
this.statusTimer = setTimeout(() => {
|
|
22014
|
-
this.sendUnifiedStatusReport().catch((e) =>
|
|
21977
|
+
this.sendUnifiedStatusReport().catch((e) => LOG5.warn("Status", `Periodic report failed: ${e?.message}`));
|
|
22015
21978
|
scheduleServerReport();
|
|
22016
21979
|
}, 3e4);
|
|
22017
21980
|
};
|
|
22018
21981
|
scheduleServerReport();
|
|
22019
21982
|
this.p2pTimer = setInterval(() => {
|
|
22020
21983
|
if (this.deps.p2p?.isConnected) {
|
|
22021
|
-
this.sendUnifiedStatusReport({ p2pOnly: true }).catch((e) =>
|
|
21984
|
+
this.sendUnifiedStatusReport({ p2pOnly: true }).catch((e) => LOG5.warn("Status", `P2P status send failed: ${e?.message}`));
|
|
22022
21985
|
}
|
|
22023
21986
|
}, 5e3);
|
|
22024
21987
|
}
|
|
@@ -22039,17 +22002,17 @@ var require_dist = __commonJS({
|
|
|
22039
22002
|
const now = Date.now();
|
|
22040
22003
|
const elapsed = now - this.lastStatusSentAt;
|
|
22041
22004
|
if (elapsed >= 5e3) {
|
|
22042
|
-
this.sendUnifiedStatusReport().catch((e) =>
|
|
22005
|
+
this.sendUnifiedStatusReport().catch((e) => LOG5.warn("Status", `Throttled report failed: ${e?.message}`));
|
|
22043
22006
|
} else if (!this.statusPendingThrottle) {
|
|
22044
22007
|
this.statusPendingThrottle = true;
|
|
22045
22008
|
setTimeout(() => {
|
|
22046
22009
|
this.statusPendingThrottle = false;
|
|
22047
|
-
this.sendUnifiedStatusReport().catch((e) =>
|
|
22010
|
+
this.sendUnifiedStatusReport().catch((e) => LOG5.warn("Status", `Deferred report failed: ${e?.message}`));
|
|
22048
22011
|
}, 5e3 - elapsed);
|
|
22049
22012
|
}
|
|
22050
22013
|
}
|
|
22051
22014
|
emitStatusEvent(event) {
|
|
22052
|
-
|
|
22015
|
+
LOG5.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
22053
22016
|
this.deps.serverConn?.sendMessage("status_event", event);
|
|
22054
22017
|
}
|
|
22055
22018
|
removeAgentTracking(_key) {
|
|
@@ -22084,9 +22047,9 @@ var require_dist = __commonJS({
|
|
|
22084
22047
|
if (summaryChanged) {
|
|
22085
22048
|
this.lastStatusSummary = summary;
|
|
22086
22049
|
if (logLevel === "debug") {
|
|
22087
|
-
|
|
22050
|
+
LOG5.debug("StatusReport", summary);
|
|
22088
22051
|
} else {
|
|
22089
|
-
|
|
22052
|
+
LOG5.info("StatusReport", summary);
|
|
22090
22053
|
}
|
|
22091
22054
|
}
|
|
22092
22055
|
const managedIdes = ideStates.map((s) => ({
|
|
@@ -22171,7 +22134,7 @@ var require_dist = __commonJS({
|
|
|
22171
22134
|
};
|
|
22172
22135
|
const p2pSent = this.sendP2PPayload(payload);
|
|
22173
22136
|
if (p2pSent) {
|
|
22174
|
-
|
|
22137
|
+
LOG5.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
|
|
22175
22138
|
}
|
|
22176
22139
|
if (opts?.p2pOnly) return;
|
|
22177
22140
|
const plan = serverConn.getUserPlan();
|
|
@@ -22202,7 +22165,7 @@ var require_dist = __commonJS({
|
|
|
22202
22165
|
timestamp: now
|
|
22203
22166
|
};
|
|
22204
22167
|
serverConn.sendMessage("status_report", wsPayload);
|
|
22205
|
-
|
|
22168
|
+
LOG5.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
|
|
22206
22169
|
}
|
|
22207
22170
|
}
|
|
22208
22171
|
// ─── P2P ─────────────────────────────────────────
|
|
@@ -22239,7 +22202,7 @@ var require_dist = __commonJS({
|
|
|
22239
22202
|
try {
|
|
22240
22203
|
pty = require("node-pty");
|
|
22241
22204
|
} catch {
|
|
22242
|
-
|
|
22205
|
+
LOG5.error("CLI", "[ProviderCliAdapter] node-pty not found. Install: npm install node-pty@1.0.0");
|
|
22243
22206
|
}
|
|
22244
22207
|
function stripAnsi(str) {
|
|
22245
22208
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
@@ -22319,7 +22282,7 @@ var require_dist = __commonJS({
|
|
|
22319
22282
|
const binaryPath = findBinary(spawnConfig.command);
|
|
22320
22283
|
const isWin = os9.platform() === "win32";
|
|
22321
22284
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
22322
|
-
|
|
22285
|
+
LOG5.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
22323
22286
|
let shellCmd;
|
|
22324
22287
|
let shellArgs;
|
|
22325
22288
|
if (spawnConfig.shell) {
|
|
@@ -22356,7 +22319,7 @@ var require_dist = __commonJS({
|
|
|
22356
22319
|
}
|
|
22357
22320
|
});
|
|
22358
22321
|
this.ptyProcess.onExit(({ exitCode }) => {
|
|
22359
|
-
|
|
22322
|
+
LOG5.info("CLI", `[${this.cliType}] Exit code ${exitCode}`);
|
|
22360
22323
|
this.ptyProcess = null;
|
|
22361
22324
|
this.currentStatus = "stopped";
|
|
22362
22325
|
this.ready = false;
|
|
@@ -22391,7 +22354,7 @@ var require_dist = __commonJS({
|
|
|
22391
22354
|
if (patterns.prompt.some((p) => p.test(this.startupBuffer))) {
|
|
22392
22355
|
this.ready = true;
|
|
22393
22356
|
this.currentStatus = "idle";
|
|
22394
|
-
|
|
22357
|
+
LOG5.info("CLI", `[${this.cliType}] \u2713 Ready`);
|
|
22395
22358
|
this.onStatusChange?.();
|
|
22396
22359
|
}
|
|
22397
22360
|
return;
|
|
@@ -22478,7 +22441,7 @@ var require_dist = __commonJS({
|
|
|
22478
22441
|
if (response) {
|
|
22479
22442
|
this.messages.push({ role: "assistant", content: response, timestamp: Date.now() });
|
|
22480
22443
|
if (this.messages.length > 200) this.messages = this.messages.slice(-200);
|
|
22481
|
-
|
|
22444
|
+
LOG5.info("CLI", `[${this.cliType}] Response (${response.length} chars)`);
|
|
22482
22445
|
}
|
|
22483
22446
|
this.responseBuffer = "";
|
|
22484
22447
|
this.isWaitingForResponse = false;
|
|
@@ -22718,6 +22681,10 @@ var require_dist = __commonJS({
|
|
|
22718
22681
|
var import_stream = require("stream");
|
|
22719
22682
|
var import_child_process5 = require("child_process");
|
|
22720
22683
|
var import_sdk = (init_acp(), __toCommonJS(acp_exports));
|
|
22684
|
+
function flattenContent(content) {
|
|
22685
|
+
if (typeof content === "string") return content;
|
|
22686
|
+
return content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
22687
|
+
}
|
|
22721
22688
|
var AcpProviderInstance = class {
|
|
22722
22689
|
constructor(provider, workingDir, cliArgs = []) {
|
|
22723
22690
|
this.cliArgs = cliArgs;
|
|
@@ -22729,7 +22696,7 @@ var require_dist = __commonJS({
|
|
|
22729
22696
|
}
|
|
22730
22697
|
type;
|
|
22731
22698
|
category = "acp";
|
|
22732
|
-
log =
|
|
22699
|
+
log = LOG5.forComponent("ACP");
|
|
22733
22700
|
provider;
|
|
22734
22701
|
context = null;
|
|
22735
22702
|
settings = {};
|
|
@@ -22750,6 +22717,10 @@ var require_dist = __commonJS({
|
|
|
22750
22717
|
activeToolCalls = [];
|
|
22751
22718
|
stopReason = null;
|
|
22752
22719
|
partialContent = "";
|
|
22720
|
+
/** Rich content blocks accumulated during streaming */
|
|
22721
|
+
partialBlocks = [];
|
|
22722
|
+
/** Tool calls collected during current turn */
|
|
22723
|
+
turnToolCalls = [];
|
|
22753
22724
|
// Error tracking
|
|
22754
22725
|
errorMessage = null;
|
|
22755
22726
|
errorReason = null;
|
|
@@ -22784,18 +22755,23 @@ var require_dist = __commonJS({
|
|
|
22784
22755
|
}
|
|
22785
22756
|
getState() {
|
|
22786
22757
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
22787
|
-
const recentMessages = this.messages.slice(-50).map((m) =>
|
|
22788
|
-
|
|
22789
|
-
|
|
22790
|
-
|
|
22791
|
-
|
|
22792
|
-
|
|
22793
|
-
|
|
22794
|
-
|
|
22758
|
+
const recentMessages = this.messages.slice(-50).map((m) => {
|
|
22759
|
+
const content = this.truncateContent(m.content);
|
|
22760
|
+
return {
|
|
22761
|
+
role: m.role,
|
|
22762
|
+
content,
|
|
22763
|
+
timestamp: m.timestamp,
|
|
22764
|
+
toolCalls: m.toolCalls
|
|
22765
|
+
};
|
|
22766
|
+
});
|
|
22767
|
+
if (this.currentStatus === "generating" && (this.partialContent || this.partialBlocks.length > 0)) {
|
|
22768
|
+
const blocks = this.buildPartialBlocks();
|
|
22769
|
+
if (blocks.length > 0) {
|
|
22795
22770
|
recentMessages.push({
|
|
22796
22771
|
role: "assistant",
|
|
22797
|
-
content:
|
|
22798
|
-
timestamp: Date.now()
|
|
22772
|
+
content: blocks,
|
|
22773
|
+
timestamp: Date.now(),
|
|
22774
|
+
toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : void 0
|
|
22799
22775
|
});
|
|
22800
22776
|
}
|
|
22801
22777
|
}
|
|
@@ -23241,49 +23217,49 @@ var require_dist = __commonJS({
|
|
|
23241
23217
|
this.currentStatus = "idle";
|
|
23242
23218
|
}
|
|
23243
23219
|
}
|
|
23244
|
-
async sendPrompt(text) {
|
|
23220
|
+
async sendPrompt(text, contentBlocks) {
|
|
23245
23221
|
if (!this.connection || !this.sessionId) {
|
|
23246
23222
|
this.log.warn(`[${this.type}] Cannot send prompt: no active connection/session`);
|
|
23247
23223
|
return;
|
|
23248
23224
|
}
|
|
23225
|
+
let promptParts;
|
|
23226
|
+
if (contentBlocks && contentBlocks.length > 0) {
|
|
23227
|
+
promptParts = contentBlocks.map((b) => {
|
|
23228
|
+
if (b.type === "text") return { type: "text", text: b.text };
|
|
23229
|
+
if (b.type === "image") return { type: "image", data: b.data, mimeType: b.mimeType };
|
|
23230
|
+
if (b.type === "resource_link") return { type: "resource_link", uri: b.uri, name: b.name };
|
|
23231
|
+
if (b.type === "resource") return { type: "resource", resource: b.resource };
|
|
23232
|
+
return { type: "text", text: flattenContent([b]) };
|
|
23233
|
+
});
|
|
23234
|
+
} else {
|
|
23235
|
+
promptParts = [{ type: "text", text }];
|
|
23236
|
+
}
|
|
23249
23237
|
this.messages.push({
|
|
23250
23238
|
role: "user",
|
|
23251
|
-
content: text,
|
|
23239
|
+
content: contentBlocks && contentBlocks.length > 0 ? contentBlocks : text,
|
|
23252
23240
|
timestamp: Date.now()
|
|
23253
23241
|
});
|
|
23254
23242
|
this.currentStatus = "generating";
|
|
23255
23243
|
this.partialContent = "";
|
|
23244
|
+
this.partialBlocks = [];
|
|
23245
|
+
this.turnToolCalls = [];
|
|
23256
23246
|
this.detectStatusTransition();
|
|
23257
|
-
this.log.info(`[${this.type}] Sending prompt: "${text.slice(0, 100)}"`);
|
|
23247
|
+
this.log.info(`[${this.type}] Sending prompt: "${text.slice(0, 100)}" (${promptParts.length} parts)`);
|
|
23258
23248
|
try {
|
|
23259
23249
|
const result = await this.connection.prompt({
|
|
23260
23250
|
sessionId: this.sessionId,
|
|
23261
|
-
prompt:
|
|
23251
|
+
prompt: promptParts
|
|
23262
23252
|
});
|
|
23263
23253
|
if (result?.stopReason) {
|
|
23264
23254
|
this.stopReason = result.stopReason;
|
|
23265
23255
|
}
|
|
23266
|
-
this.log.info(`[${this.type}] Prompt completed: stopReason=${result?.stopReason} partialContent=${this.partialContent.length} chars`);
|
|
23267
|
-
|
|
23268
|
-
this.messages.push({
|
|
23269
|
-
role: "assistant",
|
|
23270
|
-
content: this.partialContent.trim(),
|
|
23271
|
-
timestamp: Date.now()
|
|
23272
|
-
});
|
|
23273
|
-
this.partialContent = "";
|
|
23274
|
-
}
|
|
23256
|
+
this.log.info(`[${this.type}] Prompt completed: stopReason=${result?.stopReason} partialContent=${this.partialContent.length} chars partialBlocks=${this.partialBlocks.length}`);
|
|
23257
|
+
this.finalizeAssistantMessage();
|
|
23275
23258
|
this.currentStatus = "idle";
|
|
23276
23259
|
this.detectStatusTransition();
|
|
23277
23260
|
} catch (e) {
|
|
23278
23261
|
this.log.warn(`[${this.type}] prompt error: ${e?.message}`);
|
|
23279
|
-
|
|
23280
|
-
this.messages.push({
|
|
23281
|
-
role: "assistant",
|
|
23282
|
-
content: this.partialContent.trim(),
|
|
23283
|
-
timestamp: Date.now()
|
|
23284
|
-
});
|
|
23285
|
-
this.partialContent = "";
|
|
23286
|
-
}
|
|
23262
|
+
this.finalizeAssistantMessage();
|
|
23287
23263
|
this.currentStatus = "idle";
|
|
23288
23264
|
this.detectStatusTransition();
|
|
23289
23265
|
}
|
|
@@ -23317,6 +23293,27 @@ var require_dist = __commonJS({
|
|
|
23317
23293
|
const content = update.content;
|
|
23318
23294
|
if (content?.type === "text" && content.text) {
|
|
23319
23295
|
this.partialContent += content.text;
|
|
23296
|
+
} else if (content?.type === "image") {
|
|
23297
|
+
this.partialBlocks.push({
|
|
23298
|
+
type: "image",
|
|
23299
|
+
data: content.data || "",
|
|
23300
|
+
mimeType: content.mimeType || "image/png",
|
|
23301
|
+
uri: content.uri
|
|
23302
|
+
});
|
|
23303
|
+
} else if (content?.type === "resource_link") {
|
|
23304
|
+
this.partialBlocks.push({
|
|
23305
|
+
type: "resource_link",
|
|
23306
|
+
uri: content.uri || "",
|
|
23307
|
+
name: content.name || "resource",
|
|
23308
|
+
title: content.title,
|
|
23309
|
+
mimeType: content.mimeType,
|
|
23310
|
+
size: content.size
|
|
23311
|
+
});
|
|
23312
|
+
} else if (content?.type === "resource") {
|
|
23313
|
+
this.partialBlocks.push({
|
|
23314
|
+
type: "resource",
|
|
23315
|
+
resource: content.resource
|
|
23316
|
+
});
|
|
23320
23317
|
}
|
|
23321
23318
|
this.currentStatus = "generating";
|
|
23322
23319
|
break;
|
|
@@ -23326,12 +23323,26 @@ var require_dist = __commonJS({
|
|
|
23326
23323
|
break;
|
|
23327
23324
|
}
|
|
23328
23325
|
case "tool_call": {
|
|
23326
|
+
const tcId = update.toolCallId || `tc_${Date.now()}`;
|
|
23327
|
+
const tcTitle = update.title || "unknown";
|
|
23328
|
+
const tcKind = update.kind;
|
|
23329
|
+
const tcStatus = this.mapToolCallStatus(update.status);
|
|
23329
23330
|
this.activeToolCalls.push({
|
|
23330
|
-
id:
|
|
23331
|
-
name:
|
|
23332
|
-
status:
|
|
23331
|
+
id: tcId,
|
|
23332
|
+
name: tcTitle,
|
|
23333
|
+
status: tcStatus,
|
|
23333
23334
|
input: update.rawInput ? typeof update.rawInput === "string" ? update.rawInput : JSON.stringify(update.rawInput) : void 0
|
|
23334
23335
|
});
|
|
23336
|
+
const acpStatus = update.status || "in_progress";
|
|
23337
|
+
this.turnToolCalls.push({
|
|
23338
|
+
toolCallId: tcId,
|
|
23339
|
+
title: tcTitle,
|
|
23340
|
+
kind: tcKind,
|
|
23341
|
+
status: acpStatus,
|
|
23342
|
+
rawInput: update.rawInput,
|
|
23343
|
+
content: this.convertToolCallContent(update.content),
|
|
23344
|
+
locations: update.locations
|
|
23345
|
+
});
|
|
23335
23346
|
break;
|
|
23336
23347
|
}
|
|
23337
23348
|
case "tool_call_update": {
|
|
@@ -23341,6 +23352,13 @@ var require_dist = __commonJS({
|
|
|
23341
23352
|
if (update.status) existing.status = this.mapToolCallStatus(update.status);
|
|
23342
23353
|
if (update.rawOutput) existing.output = typeof update.rawOutput === "string" ? update.rawOutput : JSON.stringify(update.rawOutput);
|
|
23343
23354
|
}
|
|
23355
|
+
const tcInfo = this.turnToolCalls.find((t) => t.toolCallId === toolCallId);
|
|
23356
|
+
if (tcInfo) {
|
|
23357
|
+
if (update.status) tcInfo.status = update.status;
|
|
23358
|
+
if (update.rawOutput) tcInfo.rawOutput = update.rawOutput;
|
|
23359
|
+
if (update.content) tcInfo.content = this.convertToolCallContent(update.content);
|
|
23360
|
+
if (update.locations) tcInfo.locations = update.locations;
|
|
23361
|
+
}
|
|
23344
23362
|
break;
|
|
23345
23363
|
}
|
|
23346
23364
|
case "current_mode_update": {
|
|
@@ -23433,6 +23451,62 @@ var require_dist = __commonJS({
|
|
|
23433
23451
|
return "running";
|
|
23434
23452
|
}
|
|
23435
23453
|
}
|
|
23454
|
+
// ─── Rich Content Helpers ────────────────────────────
|
|
23455
|
+
/** Truncate content for transport (text: 2000 chars, images preserved) */
|
|
23456
|
+
truncateContent(content) {
|
|
23457
|
+
if (typeof content === "string") {
|
|
23458
|
+
return content.length > 2e3 ? content.slice(0, 2e3) + "\n... (truncated)" : content;
|
|
23459
|
+
}
|
|
23460
|
+
return content.map((b) => {
|
|
23461
|
+
if (b.type === "text" && b.text.length > 2e3) {
|
|
23462
|
+
return { ...b, text: b.text.slice(0, 2e3) + "\n... (truncated)" };
|
|
23463
|
+
}
|
|
23464
|
+
return b;
|
|
23465
|
+
});
|
|
23466
|
+
}
|
|
23467
|
+
/** Build ContentBlock[] from current partial state */
|
|
23468
|
+
buildPartialBlocks() {
|
|
23469
|
+
const blocks = [];
|
|
23470
|
+
if (this.partialContent.trim()) {
|
|
23471
|
+
blocks.push({ type: "text", text: this.partialContent.trim() + "..." });
|
|
23472
|
+
}
|
|
23473
|
+
blocks.push(...this.partialBlocks);
|
|
23474
|
+
return blocks;
|
|
23475
|
+
}
|
|
23476
|
+
/** Finalize streaming content into an assistant message */
|
|
23477
|
+
finalizeAssistantMessage() {
|
|
23478
|
+
const blocks = this.buildPartialBlocks();
|
|
23479
|
+
const finalBlocks = blocks.map((b) => {
|
|
23480
|
+
if (b.type === "text" && b.text.endsWith("...")) {
|
|
23481
|
+
return { ...b, text: b.text.slice(0, -3) };
|
|
23482
|
+
}
|
|
23483
|
+
return b;
|
|
23484
|
+
}).filter((b) => b.type !== "text" || b.text.trim());
|
|
23485
|
+
if (finalBlocks.length > 0) {
|
|
23486
|
+
this.messages.push({
|
|
23487
|
+
role: "assistant",
|
|
23488
|
+
content: finalBlocks.length === 1 && finalBlocks[0].type === "text" ? finalBlocks[0].text : finalBlocks,
|
|
23489
|
+
timestamp: Date.now(),
|
|
23490
|
+
toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : void 0
|
|
23491
|
+
});
|
|
23492
|
+
}
|
|
23493
|
+
this.partialContent = "";
|
|
23494
|
+
this.partialBlocks = [];
|
|
23495
|
+
this.turnToolCalls = [];
|
|
23496
|
+
}
|
|
23497
|
+
/** Convert ACP ToolCallContent[] to our ToolCallContent[] */
|
|
23498
|
+
convertToolCallContent(acpContent) {
|
|
23499
|
+
if (!acpContent || !Array.isArray(acpContent)) return void 0;
|
|
23500
|
+
return acpContent.map((c) => {
|
|
23501
|
+
if (c.type === "diff") {
|
|
23502
|
+
return { type: "diff", path: c.path || "", oldText: c.oldText, newText: c.newText || "" };
|
|
23503
|
+
}
|
|
23504
|
+
if (c.type === "terminal") {
|
|
23505
|
+
return { type: "terminal", terminalId: c.terminalId || "" };
|
|
23506
|
+
}
|
|
23507
|
+
return { type: "content", content: c.content || { type: "text", text: JSON.stringify(c) } };
|
|
23508
|
+
});
|
|
23509
|
+
}
|
|
23436
23510
|
// ─── status transition detect ────────────────────────────
|
|
23437
23511
|
detectStatusTransition() {
|
|
23438
23512
|
const now = Date.now();
|
|
@@ -23570,13 +23644,13 @@ ${installInfo}`
|
|
|
23570
23644
|
await acpInstance.setConfigOption("model", initialModel);
|
|
23571
23645
|
console.log(import_chalk3.default.green(` \u{1F916} Initial model set: ${initialModel}`));
|
|
23572
23646
|
} catch (e) {
|
|
23573
|
-
|
|
23647
|
+
LOG5.warn("CLI", `[ACP] Initial model set failed: ${e?.message}`);
|
|
23574
23648
|
}
|
|
23575
23649
|
}
|
|
23576
23650
|
try {
|
|
23577
23651
|
addCliHistory({ cliType: normalizedType, dir: resolvedDir, cliArgs });
|
|
23578
23652
|
} catch (e) {
|
|
23579
|
-
|
|
23653
|
+
LOG5.warn("CLI", `ACP history save failed: ${e?.message}`);
|
|
23580
23654
|
}
|
|
23581
23655
|
this.deps.onStatusChange();
|
|
23582
23656
|
return;
|
|
@@ -23631,7 +23705,7 @@ ${installInfo}`
|
|
|
23631
23705
|
try {
|
|
23632
23706
|
addCliHistory({ cliType, dir: resolvedDir, cliArgs });
|
|
23633
23707
|
} catch (e) {
|
|
23634
|
-
|
|
23708
|
+
LOG5.warn("CLI", `CLI history save failed: ${e?.message}`);
|
|
23635
23709
|
}
|
|
23636
23710
|
this.deps.onStatusChange();
|
|
23637
23711
|
}
|
|
@@ -23880,7 +23954,7 @@ ${installInfo}`
|
|
|
23880
23954
|
discoveryIntervalMs = 1e4;
|
|
23881
23955
|
_activeAgentType = null;
|
|
23882
23956
|
constructor(logFn, providerLoader) {
|
|
23883
|
-
this.logFn = logFn ||
|
|
23957
|
+
this.logFn = logFn || LOG5.forComponent("AgentStream").asLogFn();
|
|
23884
23958
|
if (providerLoader) {
|
|
23885
23959
|
const allExtProviders = providerLoader.getByCategory("extension");
|
|
23886
23960
|
for (const p of allExtProviders) {
|
|
@@ -24155,7 +24229,7 @@ ${installInfo}`
|
|
|
24155
24229
|
for (const extType of currentExtTypes) {
|
|
24156
24230
|
if (!enabledExtTypes.has(extType)) {
|
|
24157
24231
|
ideInstance.removeExtension(extType);
|
|
24158
|
-
|
|
24232
|
+
LOG5.info("AgentStream", `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
24159
24233
|
}
|
|
24160
24234
|
}
|
|
24161
24235
|
for (const extType of enabledExtTypes) {
|
|
@@ -24164,7 +24238,7 @@ ${installInfo}`
|
|
|
24164
24238
|
if (extProvider) {
|
|
24165
24239
|
const extSettings = providerLoader.getSettings(extType);
|
|
24166
24240
|
ideInstance.addExtension(extProvider, extSettings);
|
|
24167
|
-
|
|
24241
|
+
LOG5.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
24168
24242
|
}
|
|
24169
24243
|
}
|
|
24170
24244
|
}
|
|
@@ -24191,7 +24265,7 @@ ${installInfo}`
|
|
|
24191
24265
|
if (discovered.length > 0) {
|
|
24192
24266
|
this._activeIdeType = ideType;
|
|
24193
24267
|
await agentStreamManager.switchActiveAgent(cdp, discovered[0].agentType);
|
|
24194
|
-
|
|
24268
|
+
LOG5.info("AgentStream", `Auto-activated: ${discovered[0].agentType} (${ideType})`);
|
|
24195
24269
|
await agentStreamManager.syncAgentSessions(cdp);
|
|
24196
24270
|
const streams = await agentStreamManager.collectAgentStreams(cdp);
|
|
24197
24271
|
this.deps.onStreamsUpdated?.(ideType, streams);
|
|
@@ -24215,7 +24289,7 @@ ${installInfo}`
|
|
|
24215
24289
|
*/
|
|
24216
24290
|
async addInstance(id, instance, context) {
|
|
24217
24291
|
if (this.instances.has(id)) {
|
|
24218
|
-
|
|
24292
|
+
LOG5.warn("InstanceMgr", `[InstanceManager] Instance ${id} already exists, disposing old one`);
|
|
24219
24293
|
this.instances.get(id).dispose();
|
|
24220
24294
|
}
|
|
24221
24295
|
this.instances.set(id, instance);
|
|
@@ -24266,7 +24340,7 @@ ${installInfo}`
|
|
|
24266
24340
|
}
|
|
24267
24341
|
}
|
|
24268
24342
|
} catch (e) {
|
|
24269
|
-
|
|
24343
|
+
LOG5.warn("InstanceMgr", `[InstanceManager] Failed to collect state from ${id}: ${e.message}`);
|
|
24270
24344
|
}
|
|
24271
24345
|
}
|
|
24272
24346
|
return states;
|
|
@@ -24289,7 +24363,7 @@ ${installInfo}`
|
|
|
24289
24363
|
try {
|
|
24290
24364
|
await instance.onTick();
|
|
24291
24365
|
} catch (e) {
|
|
24292
|
-
|
|
24366
|
+
LOG5.warn("InstanceMgr", `[InstanceManager] Tick failed for ${id}: ${e.message}`);
|
|
24293
24367
|
}
|
|
24294
24368
|
}
|
|
24295
24369
|
}, this.tickInterval);
|
|
@@ -24865,11 +24939,67 @@ async (params) => {
|
|
|
24865
24939
|
constructor(options) {
|
|
24866
24940
|
this.providerLoader = options.providerLoader;
|
|
24867
24941
|
this.cdpManagers = options.cdpManagers;
|
|
24868
|
-
this.logFn = options.logFn ||
|
|
24942
|
+
this.logFn = options.logFn || LOG5.forComponent("DevServer").asLogFn();
|
|
24869
24943
|
}
|
|
24870
24944
|
log(msg) {
|
|
24871
24945
|
this.logFn(`[DevServer] ${msg}`);
|
|
24872
24946
|
}
|
|
24947
|
+
// ─── Route Table ─────────────────────────────────────
|
|
24948
|
+
routes = [
|
|
24949
|
+
// Static routes
|
|
24950
|
+
{ method: "GET", pattern: "/api/providers", handler: (q, s) => this.handleListProviders(q, s) },
|
|
24951
|
+
{ method: "GET", pattern: "/api/providers/versions", handler: (q, s) => this.handleDetectVersions(q, s) },
|
|
24952
|
+
{ method: "POST", pattern: "/api/providers/reload", handler: (q, s) => this.handleReload(q, s) },
|
|
24953
|
+
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s) => this.handleCdpEvaluate(q, s) },
|
|
24954
|
+
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s) => this.handleCdpDomQuery(q, s) },
|
|
24955
|
+
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s) => this.handleDomInspect(q, s) },
|
|
24956
|
+
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s) => this.handleDomChildren(q, s) },
|
|
24957
|
+
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s) => this.handleDomAnalyze(q, s) },
|
|
24958
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s) => this.handleFindByText(q, s) },
|
|
24959
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s) => this.handleFindCommon(q, s) },
|
|
24960
|
+
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s) => this.handleScreenshot(q, s) },
|
|
24961
|
+
{ method: "GET", pattern: "/api/cdp/targets", handler: (q, s) => this.handleCdpTargets(q, s) },
|
|
24962
|
+
{ method: "POST", pattern: "/api/scripts/run", handler: (q, s) => this.handleScriptsRun(q, s) },
|
|
24963
|
+
{ method: "GET", pattern: "/api/status", handler: (q, s) => this.handleStatus(q, s) },
|
|
24964
|
+
{ method: "POST", pattern: "/api/watch/start", handler: (q, s) => this.handleWatchStart(q, s) },
|
|
24965
|
+
{ method: "POST", pattern: "/api/watch/stop", handler: (q, s) => this.handleWatchStop(q, s) },
|
|
24966
|
+
{ method: "GET", pattern: "/api/watch/events", handler: (q, s) => this.handleSSE(q, s) },
|
|
24967
|
+
{ method: "POST", pattern: "/api/scaffold", handler: (q, s) => this.handleScaffold(q, s) },
|
|
24968
|
+
// Dynamic routes (provider :type param)
|
|
24969
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s, p) => this.handleRunScript(p[0], q, s) },
|
|
24970
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s, p) => this.handleListFiles(p[0], q, s) },
|
|
24971
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleReadFile(p[0], q, s) },
|
|
24972
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleWriteFile(p[0], q, s) },
|
|
24973
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s, p) => this.handleSource(p[0], q, s) },
|
|
24974
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s, p) => this.handleSave(p[0], q, s) },
|
|
24975
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s, p) => this.handleProviderConfig(p[0], q, s) },
|
|
24976
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s, p) => this.handleDomContext(p[0], q, s) },
|
|
24977
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s, p) => this.handleAutoImplement(p[0], q, s) },
|
|
24978
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s, p) => this.handleAutoImplCancel(p[0], q, s) },
|
|
24979
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s, p) => this.handleAutoImplSSE(p[0], q, s) },
|
|
24980
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s, p) => this.handleSpawnTest(p[0], q, s) },
|
|
24981
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s, p) => this.handleValidate(p[0], q, s) },
|
|
24982
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s, p) => this.handleAcpChat(p[0], q, s) },
|
|
24983
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s, p) => this.handleScriptHints(p[0], q, s) }
|
|
24984
|
+
];
|
|
24985
|
+
matchRoute(method, pathname) {
|
|
24986
|
+
for (const route of this.routes) {
|
|
24987
|
+
if (route.method !== method) continue;
|
|
24988
|
+
if (typeof route.pattern === "string") {
|
|
24989
|
+
if (pathname === route.pattern) return { handler: route.handler };
|
|
24990
|
+
} else {
|
|
24991
|
+
const m = pathname.match(route.pattern);
|
|
24992
|
+
if (m) return { handler: route.handler, params: m.slice(1) };
|
|
24993
|
+
}
|
|
24994
|
+
}
|
|
24995
|
+
return null;
|
|
24996
|
+
}
|
|
24997
|
+
getEndpointList() {
|
|
24998
|
+
return this.routes.map((r) => {
|
|
24999
|
+
const path10 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
25000
|
+
return `${r.method.padEnd(5)} ${path10}`;
|
|
25001
|
+
});
|
|
25002
|
+
}
|
|
24873
25003
|
async start(port = DEV_SERVER_PORT) {
|
|
24874
25004
|
this.server = http2.createServer(async (req, res) => {
|
|
24875
25005
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -24883,112 +25013,15 @@ async (params) => {
|
|
|
24883
25013
|
const url2 = new URL(req.url || "/", `http://localhost:${port}`);
|
|
24884
25014
|
const pathname = url2.pathname;
|
|
24885
25015
|
try {
|
|
24886
|
-
|
|
24887
|
-
|
|
24888
|
-
|
|
24889
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/script$/)[1];
|
|
24890
|
-
await this.handleRunScript(type, req, res);
|
|
24891
|
-
} else if (pathname === "/api/cdp/evaluate" && req.method === "POST") {
|
|
24892
|
-
await this.handleCdpEvaluate(req, res);
|
|
24893
|
-
} else if (pathname === "/api/cdp/dom/query" && req.method === "POST") {
|
|
24894
|
-
await this.handleCdpDomQuery(req, res);
|
|
24895
|
-
} else if (pathname === "/api/cdp/screenshot" && req.method === "GET") {
|
|
24896
|
-
await this.handleScreenshot(req, res);
|
|
24897
|
-
} else if (pathname === "/api/scripts/run" && req.method === "POST") {
|
|
24898
|
-
await this.handleScriptsRun(req, res);
|
|
24899
|
-
} else if (pathname === "/api/status" && req.method === "GET") {
|
|
24900
|
-
await this.handleStatus(req, res);
|
|
24901
|
-
} else if (pathname === "/api/providers/reload" && req.method === "POST") {
|
|
24902
|
-
await this.handleReload(req, res);
|
|
24903
|
-
} else if (pathname === "/api/providers/versions" && req.method === "GET") {
|
|
24904
|
-
await this.handleDetectVersions(req, res);
|
|
24905
|
-
} else if (pathname === "/api/watch/start" && req.method === "POST") {
|
|
24906
|
-
await this.handleWatchStart(req, res);
|
|
24907
|
-
} else if (pathname === "/api/watch/stop" && req.method === "POST") {
|
|
24908
|
-
await this.handleWatchStop(req, res);
|
|
24909
|
-
} else if (pathname === "/api/watch/events" && req.method === "GET") {
|
|
24910
|
-
this.handleSSE(req, res);
|
|
24911
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/files$/) && req.method === "GET") {
|
|
24912
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/files$/)[1];
|
|
24913
|
-
await this.handleListFiles(type, req, res);
|
|
24914
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/file$/) && req.method === "GET") {
|
|
24915
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/file$/)[1];
|
|
24916
|
-
await this.handleReadFile(type, req, res);
|
|
24917
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/file$/) && req.method === "POST") {
|
|
24918
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/file$/)[1];
|
|
24919
|
-
await this.handleWriteFile(type, req, res);
|
|
24920
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/source$/) && req.method === "GET") {
|
|
24921
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/source$/)[1];
|
|
24922
|
-
await this.handleSource(type, req, res);
|
|
24923
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/save$/) && req.method === "POST") {
|
|
24924
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/save$/)[1];
|
|
24925
|
-
await this.handleSave(type, req, res);
|
|
24926
|
-
} else if (pathname === "/api/cdp/dom/inspect" && req.method === "POST") {
|
|
24927
|
-
await this.handleDomInspect(req, res);
|
|
24928
|
-
} else if (pathname === "/api/cdp/dom/children" && req.method === "POST") {
|
|
24929
|
-
await this.handleDomChildren(req, res);
|
|
24930
|
-
} else if (pathname === "/api/cdp/dom/analyze" && req.method === "POST") {
|
|
24931
|
-
await this.handleDomAnalyze(req, res);
|
|
24932
|
-
} else if (pathname === "/api/cdp/dom/find-text" && req.method === "POST") {
|
|
24933
|
-
await this.handleFindByText(req, res);
|
|
24934
|
-
} else if (pathname === "/api/cdp/dom/find-common" && req.method === "POST") {
|
|
24935
|
-
await this.handleFindCommon(req, res);
|
|
24936
|
-
} else if (pathname === "/api/cdp/targets" && req.method === "GET") {
|
|
24937
|
-
await this.handleCdpTargets(req, res);
|
|
24938
|
-
} else if (pathname === "/api/scaffold" && req.method === "POST") {
|
|
24939
|
-
await this.handleScaffold(req, res);
|
|
24940
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/dom-context$/) && req.method === "POST") {
|
|
24941
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/dom-context$/)[1];
|
|
24942
|
-
await this.handleDomContext(type, req, res);
|
|
24943
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/auto-implement$/) && req.method === "POST") {
|
|
24944
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/auto-implement$/)[1];
|
|
24945
|
-
await this.handleAutoImplement(type, req, res);
|
|
24946
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/) && req.method === "POST") {
|
|
24947
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/)[1];
|
|
24948
|
-
this.handleAutoImplCancel(type, req, res);
|
|
24949
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/auto-implement\/status$/) && req.method === "GET") {
|
|
24950
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/auto-implement\/status$/)[1];
|
|
24951
|
-
this.handleAutoImplSSE(type, req, res);
|
|
24952
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/config$/) && req.method === "GET") {
|
|
24953
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/config$/)[1];
|
|
24954
|
-
await this.handleProviderConfig(type, req, res);
|
|
24955
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/spawn-test$/) && req.method === "POST") {
|
|
24956
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/spawn-test$/)[1];
|
|
24957
|
-
await this.handleSpawnTest(type, req, res);
|
|
24958
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/validate$/) && req.method === "POST") {
|
|
24959
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/validate$/)[1];
|
|
24960
|
-
await this.handleValidate(type, req, res);
|
|
24961
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/acp-chat$/) && req.method === "POST") {
|
|
24962
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/acp-chat$/)[1];
|
|
24963
|
-
await this.handleAcpChat(type, req, res);
|
|
24964
|
-
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/script-hints$/) && req.method === "GET") {
|
|
24965
|
-
const type = pathname.match(/^\/api\/providers\/([^/]+)\/script-hints$/)[1];
|
|
24966
|
-
await this.handleScriptHints(type, req, res);
|
|
25016
|
+
const route = this.matchRoute(req.method || "GET", pathname);
|
|
25017
|
+
if (route) {
|
|
25018
|
+
await route.handler(req, res, route.params);
|
|
24967
25019
|
} else if (pathname.startsWith("/assets/") || pathname === "/favicon.ico") {
|
|
24968
25020
|
await this.serveStaticAsset(pathname, res);
|
|
24969
25021
|
} else if (pathname === "/" || pathname === "/console" || !pathname.startsWith("/api")) {
|
|
24970
25022
|
await this.serveConsole(req, res);
|
|
24971
25023
|
} else {
|
|
24972
|
-
this.json(res, 404, {
|
|
24973
|
-
error: "Not found",
|
|
24974
|
-
endpoints: [
|
|
24975
|
-
"GET / \u2014 DevConsole web UI",
|
|
24976
|
-
"GET /api/providers",
|
|
24977
|
-
"POST /api/providers/:type/script",
|
|
24978
|
-
"GET /api/providers/:type/source",
|
|
24979
|
-
"POST /api/providers/:type/save",
|
|
24980
|
-
"POST /api/cdp/evaluate",
|
|
24981
|
-
"POST /api/cdp/dom/query",
|
|
24982
|
-
"GET /api/cdp/screenshot",
|
|
24983
|
-
"GET /api/cdp/targets",
|
|
24984
|
-
"GET /api/status",
|
|
24985
|
-
"POST /api/providers/reload",
|
|
24986
|
-
"POST /api/watch/start",
|
|
24987
|
-
"POST /api/watch/stop",
|
|
24988
|
-
"GET /api/watch/events (SSE)",
|
|
24989
|
-
"POST /api/scaffold"
|
|
24990
|
-
]
|
|
24991
|
-
});
|
|
25024
|
+
this.json(res, 404, { error: "Not found", endpoints: this.getEndpointList() });
|
|
24992
25025
|
}
|
|
24993
25026
|
} catch (e) {
|
|
24994
25027
|
this.log(`Error: ${e.message}`);
|
|
@@ -25255,7 +25288,7 @@ async (params) => {
|
|
|
25255
25288
|
const buf = await cdp.captureScreenshot();
|
|
25256
25289
|
if (buf) {
|
|
25257
25290
|
res.writeHead(200, {
|
|
25258
|
-
"Content-Type": "image/
|
|
25291
|
+
"Content-Type": "image/webp",
|
|
25259
25292
|
"X-Viewport-Width": String(vpW),
|
|
25260
25293
|
"X-Viewport-Height": String(vpH)
|
|
25261
25294
|
});
|
|
@@ -27392,10 +27425,10 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27392
27425
|
...config2.cliManagerDeps,
|
|
27393
27426
|
getInstanceManager: () => instanceManager
|
|
27394
27427
|
}, providerLoader);
|
|
27395
|
-
|
|
27428
|
+
LOG5.info("Init", "Detecting IDEs...");
|
|
27396
27429
|
detectedIdesRef.value = await detectIDEs2();
|
|
27397
27430
|
const installed = detectedIdesRef.value.filter((i) => i.installed);
|
|
27398
|
-
|
|
27431
|
+
LOG5.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
|
|
27399
27432
|
const cdpSetupContext = {
|
|
27400
27433
|
providerLoader,
|
|
27401
27434
|
instanceManager,
|
|
@@ -27423,7 +27456,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27423
27456
|
instanceIdMap
|
|
27424
27457
|
});
|
|
27425
27458
|
const agentStreamManager = new DaemonAgentStreamManager(
|
|
27426
|
-
|
|
27459
|
+
LOG5.forComponent("AgentStream").asLogFn(),
|
|
27427
27460
|
providerLoader
|
|
27428
27461
|
);
|
|
27429
27462
|
commandHandler.setAgentStreamManager(agentStreamManager);
|
|
@@ -27443,7 +27476,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27443
27476
|
onIdeConnected: () => poller?.start(),
|
|
27444
27477
|
onStatusChange: config2.onStatusChange,
|
|
27445
27478
|
onPostChatCommand: config2.onPostChatCommand,
|
|
27446
|
-
getCdpLogFn: config2.getCdpLogFn || ((ideType) =>
|
|
27479
|
+
getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG5.forComponent(`CDP:${ideType}`).asLogFn())
|
|
27447
27480
|
});
|
|
27448
27481
|
poller = new AgentStreamPoller({
|
|
27449
27482
|
agentStreamManager,
|
|
@@ -27485,7 +27518,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27485
27518
|
await agentStreamManager.dispose(anyCdp);
|
|
27486
27519
|
}
|
|
27487
27520
|
} catch (e) {
|
|
27488
|
-
|
|
27521
|
+
LOG5.warn("Shutdown", `AgentStream dispose: ${e?.message}`);
|
|
27489
27522
|
}
|
|
27490
27523
|
try {
|
|
27491
27524
|
await cliManager.shutdownAll();
|
|
@@ -28467,6 +28500,161 @@ var init_daemon_p2p = __esm({
|
|
|
28467
28500
|
}
|
|
28468
28501
|
});
|
|
28469
28502
|
|
|
28503
|
+
// src/screenshot-controller.ts
|
|
28504
|
+
var import_daemon_core3, ScreenshotController;
|
|
28505
|
+
var init_screenshot_controller = __esm({
|
|
28506
|
+
"src/screenshot-controller.ts"() {
|
|
28507
|
+
"use strict";
|
|
28508
|
+
import_daemon_core3 = __toESM(require_dist());
|
|
28509
|
+
ScreenshotController = class _ScreenshotController {
|
|
28510
|
+
deps;
|
|
28511
|
+
timer = null;
|
|
28512
|
+
// Delta detection state
|
|
28513
|
+
debugCount = 0;
|
|
28514
|
+
lastSize = 0;
|
|
28515
|
+
lastHash = 0;
|
|
28516
|
+
staticFrameCount = 0;
|
|
28517
|
+
currentInterval;
|
|
28518
|
+
// Quality profiles
|
|
28519
|
+
profileDirect;
|
|
28520
|
+
profileRelay;
|
|
28521
|
+
STATIC_THRESHOLD = 3;
|
|
28522
|
+
// Daily budget state
|
|
28523
|
+
dailyBudgetMinutes;
|
|
28524
|
+
dailyBudgetMs;
|
|
28525
|
+
dailyUsedMs = 0;
|
|
28526
|
+
lastActiveTimestamp = 0;
|
|
28527
|
+
budgetDate;
|
|
28528
|
+
budgetExhausted = false;
|
|
28529
|
+
constructor(deps, planLimits) {
|
|
28530
|
+
this.deps = deps;
|
|
28531
|
+
const planMinIntervalMs = (planLimits?.screenshotIntervalSeconds ?? 0) * 1e3;
|
|
28532
|
+
this.profileDirect = {
|
|
28533
|
+
minInterval: Math.max(300, planMinIntervalMs),
|
|
28534
|
+
maxInterval: Math.max(2e3, planMinIntervalMs),
|
|
28535
|
+
quality: 25
|
|
28536
|
+
};
|
|
28537
|
+
this.profileRelay = {
|
|
28538
|
+
minInterval: Math.max(700, planMinIntervalMs),
|
|
28539
|
+
maxInterval: Math.max(3e3, planMinIntervalMs),
|
|
28540
|
+
quality: 12
|
|
28541
|
+
};
|
|
28542
|
+
this.currentInterval = this.profileDirect.maxInterval;
|
|
28543
|
+
this.dailyBudgetMinutes = planLimits?.dailyScreenshotMinutes ?? -1;
|
|
28544
|
+
this.dailyBudgetMs = this.dailyBudgetMinutes > 0 ? this.dailyBudgetMinutes * 6e4 : -1;
|
|
28545
|
+
this.budgetDate = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
28546
|
+
if (planMinIntervalMs > 0) {
|
|
28547
|
+
import_daemon_core3.LOG.info("Screenshot", `Plan limit: min interval ${planMinIntervalMs}ms (${planLimits?.screenshotIntervalSeconds}s)`);
|
|
28548
|
+
}
|
|
28549
|
+
if (this.dailyBudgetMs > 0) {
|
|
28550
|
+
import_daemon_core3.LOG.info("Screenshot", `Daily budget: ${this.dailyBudgetMinutes}min/day`);
|
|
28551
|
+
}
|
|
28552
|
+
}
|
|
28553
|
+
// ─── Lifecycle ────────────────────────────────
|
|
28554
|
+
start() {
|
|
28555
|
+
if (this.timer) return;
|
|
28556
|
+
this.timer = setTimeout(() => this.tick(), 1e3);
|
|
28557
|
+
}
|
|
28558
|
+
stop() {
|
|
28559
|
+
if (this.timer) {
|
|
28560
|
+
clearTimeout(this.timer);
|
|
28561
|
+
this.timer = null;
|
|
28562
|
+
}
|
|
28563
|
+
}
|
|
28564
|
+
// ─── Core loop ────────────────────────────────
|
|
28565
|
+
async tick() {
|
|
28566
|
+
if (!this.deps.isRunning()) return;
|
|
28567
|
+
const active = this.deps.isScreenshotActive();
|
|
28568
|
+
const ssIdeType = this.deps.getScreenshotIdeType();
|
|
28569
|
+
const cdp = this.deps.getCdp(ssIdeType);
|
|
28570
|
+
const isRelay = this.deps.isUsingRelay();
|
|
28571
|
+
const profile = isRelay ? this.profileRelay : this.profileDirect;
|
|
28572
|
+
this.checkBudgetReset();
|
|
28573
|
+
if (this.dailyBudgetMs > 0) {
|
|
28574
|
+
const now = Date.now();
|
|
28575
|
+
if (active && this.lastActiveTimestamp > 0) {
|
|
28576
|
+
this.dailyUsedMs += now - this.lastActiveTimestamp;
|
|
28577
|
+
}
|
|
28578
|
+
this.lastActiveTimestamp = active ? now : 0;
|
|
28579
|
+
if (this.dailyUsedMs >= this.dailyBudgetMs && !this.budgetExhausted) {
|
|
28580
|
+
this.budgetExhausted = true;
|
|
28581
|
+
const usedMin = Math.round(this.dailyUsedMs / 6e4);
|
|
28582
|
+
import_daemon_core3.LOG.info("Screenshot", `Daily budget exhausted: ${usedMin}/${this.dailyBudgetMinutes}min \u2014 pausing until midnight UTC`);
|
|
28583
|
+
}
|
|
28584
|
+
}
|
|
28585
|
+
if (!active || !cdp || this.budgetExhausted) {
|
|
28586
|
+
this.staticFrameCount = 0;
|
|
28587
|
+
this.currentInterval = profile.maxInterval;
|
|
28588
|
+
if (!active) this.lastActiveTimestamp = 0;
|
|
28589
|
+
this.timer = setTimeout(() => this.tick(), this.budgetExhausted ? 3e4 : this.currentInterval);
|
|
28590
|
+
return;
|
|
28591
|
+
}
|
|
28592
|
+
this.debugCount++;
|
|
28593
|
+
try {
|
|
28594
|
+
const buf = await cdp.captureScreenshot({ quality: profile.quality });
|
|
28595
|
+
if (buf) {
|
|
28596
|
+
const hash2 = _ScreenshotController.fnvHash(buf);
|
|
28597
|
+
const sizeMatch = buf.length === this.lastSize;
|
|
28598
|
+
const hashMatch = hash2 === this.lastHash;
|
|
28599
|
+
const anyNeedsFirstFrame = this.deps.hasAnyNeedingFirstFrame();
|
|
28600
|
+
if (sizeMatch && hashMatch && !anyNeedsFirstFrame) {
|
|
28601
|
+
this.staticFrameCount++;
|
|
28602
|
+
if (this.staticFrameCount >= this.STATIC_THRESHOLD) {
|
|
28603
|
+
this.currentInterval = Math.min(this.currentInterval + 200, profile.maxInterval);
|
|
28604
|
+
}
|
|
28605
|
+
if (this.debugCount <= 5 || this.debugCount % 50 === 0) {
|
|
28606
|
+
import_daemon_core3.LOG.debug("Screenshot", `skip (unchanged, static=${this.staticFrameCount}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"})`);
|
|
28607
|
+
}
|
|
28608
|
+
} else {
|
|
28609
|
+
this.lastSize = buf.length;
|
|
28610
|
+
this.lastHash = hash2;
|
|
28611
|
+
this.staticFrameCount = 0;
|
|
28612
|
+
this.currentInterval = profile.minInterval;
|
|
28613
|
+
const sent = this.deps.sendScreenshotBuffer(buf);
|
|
28614
|
+
if (this.debugCount <= 3 || anyNeedsFirstFrame) {
|
|
28615
|
+
import_daemon_core3.LOG.debug("Screenshot", `sent: ${buf.length} bytes, delivered=${sent}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"}${anyNeedsFirstFrame ? " (first-frame)" : ""}`);
|
|
28616
|
+
}
|
|
28617
|
+
}
|
|
28618
|
+
} else {
|
|
28619
|
+
if (this.debugCount <= 5) import_daemon_core3.LOG.debug("Screenshot", "captureScreenshot returned null");
|
|
28620
|
+
}
|
|
28621
|
+
} catch (e) {
|
|
28622
|
+
if (this.debugCount <= 5) import_daemon_core3.LOG.warn("Screenshot", `error: ${e?.message}`);
|
|
28623
|
+
}
|
|
28624
|
+
this.timer = setTimeout(() => this.tick(), this.currentInterval);
|
|
28625
|
+
}
|
|
28626
|
+
// ─── Budget ───────────────────────────────────
|
|
28627
|
+
checkBudgetReset() {
|
|
28628
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
28629
|
+
if (today !== this.budgetDate) {
|
|
28630
|
+
this.dailyUsedMs = 0;
|
|
28631
|
+
this.budgetDate = today;
|
|
28632
|
+
this.budgetExhausted = false;
|
|
28633
|
+
import_daemon_core3.LOG.info("Screenshot", `Daily budget reset (${this.dailyBudgetMinutes}min for today)`);
|
|
28634
|
+
}
|
|
28635
|
+
}
|
|
28636
|
+
// ─── Hash ─────────────────────────────────────
|
|
28637
|
+
/** FNV-1a hash of first 1KB + last 1KB for fast delta detection */
|
|
28638
|
+
static fnvHash(buf) {
|
|
28639
|
+
let h = 2166136261;
|
|
28640
|
+
const sampleEnd = Math.min(1024, buf.length);
|
|
28641
|
+
for (let i = 0; i < sampleEnd; i++) {
|
|
28642
|
+
h ^= buf[i];
|
|
28643
|
+
h = h * 16777619 >>> 0;
|
|
28644
|
+
}
|
|
28645
|
+
if (buf.length > 1024) {
|
|
28646
|
+
const start = Math.max(0, buf.length - 1024);
|
|
28647
|
+
for (let i = start; i < buf.length; i++) {
|
|
28648
|
+
h ^= buf[i];
|
|
28649
|
+
h = h * 16777619 >>> 0;
|
|
28650
|
+
}
|
|
28651
|
+
}
|
|
28652
|
+
return h;
|
|
28653
|
+
}
|
|
28654
|
+
};
|
|
28655
|
+
}
|
|
28656
|
+
});
|
|
28657
|
+
|
|
28470
28658
|
// src/adhdev-daemon.ts
|
|
28471
28659
|
var adhdev_daemon_exports = {};
|
|
28472
28660
|
__export(adhdev_daemon_exports, {
|
|
@@ -28513,13 +28701,14 @@ function stopDaemon() {
|
|
|
28513
28701
|
return false;
|
|
28514
28702
|
}
|
|
28515
28703
|
}
|
|
28516
|
-
var
|
|
28704
|
+
var import_daemon_core4, os2, fs2, path2, crypto2, import_chalk, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
28517
28705
|
var init_adhdev_daemon = __esm({
|
|
28518
28706
|
"src/adhdev-daemon.ts"() {
|
|
28519
28707
|
"use strict";
|
|
28520
28708
|
init_server_connection();
|
|
28521
|
-
|
|
28709
|
+
import_daemon_core4 = __toESM(require_dist());
|
|
28522
28710
|
init_daemon_p2p();
|
|
28711
|
+
init_screenshot_controller();
|
|
28523
28712
|
os2 = __toESM(require("os"));
|
|
28524
28713
|
fs2 = __toESM(require("fs"));
|
|
28525
28714
|
path2 = __toESM(require("path"));
|
|
@@ -28558,7 +28747,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28558
28747
|
AdhdevDaemon = class {
|
|
28559
28748
|
serverConn = null;
|
|
28560
28749
|
p2p = null;
|
|
28561
|
-
|
|
28750
|
+
screenshotController = null;
|
|
28562
28751
|
statusReporter = null;
|
|
28563
28752
|
components = null;
|
|
28564
28753
|
running = false;
|
|
@@ -28573,7 +28762,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28573
28762
|
installGlobalInterceptor();
|
|
28574
28763
|
} catch {
|
|
28575
28764
|
}
|
|
28576
|
-
this.localPort = options.localPort ||
|
|
28765
|
+
this.localPort = options.localPort || import_daemon_core4.DEFAULT_DAEMON_PORT;
|
|
28577
28766
|
const workingDir = options.workingDir || process.cwd();
|
|
28578
28767
|
if (isDaemonRunning()) {
|
|
28579
28768
|
console.log(import_chalk.default.yellow("\n\u26A0 ADHDev Daemon is already running."));
|
|
@@ -28582,14 +28771,14 @@ var init_adhdev_daemon = __esm({
|
|
|
28582
28771
|
return;
|
|
28583
28772
|
}
|
|
28584
28773
|
writeDaemonPid(process.pid);
|
|
28585
|
-
const config2 = (0,
|
|
28774
|
+
const config2 = (0, import_daemon_core4.loadConfig)();
|
|
28586
28775
|
if (!config2.connectionToken) {
|
|
28587
28776
|
console.log(import_chalk.default.red("\n\u2717 No connection token found."));
|
|
28588
28777
|
console.log(import_chalk.default.gray(" Run `adhdev setup` first.\n"));
|
|
28589
28778
|
process.exit(1);
|
|
28590
28779
|
}
|
|
28591
|
-
this.components = await (0,
|
|
28592
|
-
providerLogFn:
|
|
28780
|
+
this.components = await (0, import_daemon_core4.initDaemonComponents)({
|
|
28781
|
+
providerLogFn: import_daemon_core4.LOG.forComponent("Provider").asLogFn(),
|
|
28593
28782
|
cliManagerDeps: {
|
|
28594
28783
|
getServerConn: () => this.serverConn,
|
|
28595
28784
|
getP2p: () => this.p2p,
|
|
@@ -28602,7 +28791,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28602
28791
|
setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
|
|
28603
28792
|
setTimeout(() => this.statusReporter?.throttledReport(), 3e3);
|
|
28604
28793
|
},
|
|
28605
|
-
getCdpLogFn: (ideType) =>
|
|
28794
|
+
getCdpLogFn: (ideType) => import_daemon_core4.LOG.forComponent(`CDP:${ideType}`).asLogFn(),
|
|
28606
28795
|
onCdpManagerSetup: (ideType) => {
|
|
28607
28796
|
if (this.ideType === "unknown") this.ideType = ideType;
|
|
28608
28797
|
},
|
|
@@ -28610,11 +28799,11 @@ var init_adhdev_daemon = __esm({
|
|
|
28610
28799
|
this.statusReporter?.updateAgentStreams(ideType, streams);
|
|
28611
28800
|
}
|
|
28612
28801
|
});
|
|
28613
|
-
const versionArchive = new
|
|
28614
|
-
(0,
|
|
28802
|
+
const versionArchive = new import_daemon_core4.VersionArchive();
|
|
28803
|
+
(0, import_daemon_core4.detectAllVersions)(this.components.providerLoader, versionArchive).then((results) => {
|
|
28615
28804
|
this.components.providerLoader.setVersionArchive(versionArchive);
|
|
28616
28805
|
for (const info of results) {
|
|
28617
|
-
if (info.warning)
|
|
28806
|
+
if (info.warning) import_daemon_core4.LOG.warn("Provider", `\u26A0 [${info.name}] ${info.warning}`);
|
|
28618
28807
|
}
|
|
28619
28808
|
}).catch(() => {
|
|
28620
28809
|
});
|
|
@@ -28622,7 +28811,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28622
28811
|
if (updated) {
|
|
28623
28812
|
this.components.providerLoader.reload();
|
|
28624
28813
|
this.components.providerLoader.registerToDetector();
|
|
28625
|
-
|
|
28814
|
+
import_daemon_core4.LOG.info("Provider", "Providers auto-updated from upstream");
|
|
28626
28815
|
}
|
|
28627
28816
|
}).catch(() => {
|
|
28628
28817
|
});
|
|
@@ -28675,99 +28864,25 @@ var init_adhdev_daemon = __esm({
|
|
|
28675
28864
|
});
|
|
28676
28865
|
this.p2p.onStateChange((state) => {
|
|
28677
28866
|
if (state === "connected") {
|
|
28678
|
-
|
|
28679
|
-
this.statusReporter?.sendUnifiedStatusReport().catch((e) =>
|
|
28867
|
+
import_daemon_core4.LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
|
|
28868
|
+
this.statusReporter?.sendUnifiedStatusReport().catch((e) => import_daemon_core4.LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
|
|
28680
28869
|
setTimeout(() => {
|
|
28681
28870
|
this.statusReporter?.sendUnifiedStatusReport().catch(() => {
|
|
28682
28871
|
});
|
|
28683
28872
|
}, 2e3);
|
|
28684
28873
|
}
|
|
28685
28874
|
});
|
|
28686
|
-
let ssDebugCount = 0;
|
|
28687
|
-
let lastScreenshotSize = 0;
|
|
28688
|
-
let lastScreenshotHash = 0;
|
|
28689
|
-
let staticFrameCount = 0;
|
|
28690
28875
|
const planLimits = this.serverConn.getPlanLimits();
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
};
|
|
28702
|
-
let currentInterval = PROFILE_DIRECT.maxInterval;
|
|
28703
|
-
const STATIC_THRESHOLD = 3;
|
|
28704
|
-
if (planMinIntervalMs > 0) {
|
|
28705
|
-
import_daemon_core3.LOG.info("Screenshot", `Plan limit: min interval ${planMinIntervalMs}ms (${planLimits?.screenshotIntervalSeconds}s)`);
|
|
28706
|
-
}
|
|
28707
|
-
const fnvHash = (buf) => {
|
|
28708
|
-
let h = 2166136261;
|
|
28709
|
-
const sampleEnd = Math.min(1024, buf.length);
|
|
28710
|
-
for (let i = 0; i < sampleEnd; i++) {
|
|
28711
|
-
h ^= buf[i];
|
|
28712
|
-
h = h * 16777619 >>> 0;
|
|
28713
|
-
}
|
|
28714
|
-
if (buf.length > 1024) {
|
|
28715
|
-
const start = Math.max(0, buf.length - 1024);
|
|
28716
|
-
for (let i = start; i < buf.length; i++) {
|
|
28717
|
-
h ^= buf[i];
|
|
28718
|
-
h = h * 16777619 >>> 0;
|
|
28719
|
-
}
|
|
28720
|
-
}
|
|
28721
|
-
return h;
|
|
28722
|
-
};
|
|
28723
|
-
const screenshotTick = async () => {
|
|
28724
|
-
if (!this.running) return;
|
|
28725
|
-
const active = this.p2p?.screenshotActive;
|
|
28726
|
-
const ssIdeType = this.p2p?.screenshotIdeType;
|
|
28727
|
-
const cdp = (ssIdeType ? this.getCdpFor(ssIdeType) : null) || this.getAnyCdp();
|
|
28728
|
-
const isRelay = this.p2p?.isUsingRelay ?? false;
|
|
28729
|
-
const profile = isRelay ? PROFILE_RELAY : PROFILE_DIRECT;
|
|
28730
|
-
if (!active || !cdp) {
|
|
28731
|
-
staticFrameCount = 0;
|
|
28732
|
-
currentInterval = profile.maxInterval;
|
|
28733
|
-
this.screenshotTimer = setTimeout(screenshotTick, currentInterval);
|
|
28734
|
-
return;
|
|
28735
|
-
}
|
|
28736
|
-
ssDebugCount++;
|
|
28737
|
-
try {
|
|
28738
|
-
const buf = await cdp.captureScreenshot({ quality: profile.quality });
|
|
28739
|
-
if (buf) {
|
|
28740
|
-
const hash2 = fnvHash(buf);
|
|
28741
|
-
const sizeMatch = buf.length === lastScreenshotSize;
|
|
28742
|
-
const hashMatch = hash2 === lastScreenshotHash;
|
|
28743
|
-
const anyNeedsFirstFrame = this.p2p.hasAnyNeedingFirstFrame();
|
|
28744
|
-
if (sizeMatch && hashMatch && !anyNeedsFirstFrame) {
|
|
28745
|
-
staticFrameCount++;
|
|
28746
|
-
if (staticFrameCount >= STATIC_THRESHOLD) {
|
|
28747
|
-
currentInterval = Math.min(currentInterval + 200, profile.maxInterval);
|
|
28748
|
-
}
|
|
28749
|
-
if (ssDebugCount <= 5 || ssDebugCount % 50 === 0) {
|
|
28750
|
-
import_daemon_core3.LOG.debug("Screenshot", `skip (unchanged, static=${staticFrameCount}, interval=${currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"})`);
|
|
28751
|
-
}
|
|
28752
|
-
} else {
|
|
28753
|
-
lastScreenshotSize = buf.length;
|
|
28754
|
-
lastScreenshotHash = hash2;
|
|
28755
|
-
staticFrameCount = 0;
|
|
28756
|
-
currentInterval = profile.minInterval;
|
|
28757
|
-
const sent = this.p2p.sendScreenshotBuffer(buf);
|
|
28758
|
-
if (ssDebugCount <= 3 || anyNeedsFirstFrame) {
|
|
28759
|
-
import_daemon_core3.LOG.debug("Screenshot", `sent: ${buf.length} bytes, delivered=${sent}, interval=${currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"}${anyNeedsFirstFrame ? " (first-frame)" : ""}`);
|
|
28760
|
-
}
|
|
28761
|
-
}
|
|
28762
|
-
} else {
|
|
28763
|
-
if (ssDebugCount <= 5) import_daemon_core3.LOG.debug("Screenshot", "captureScreenshot returned null");
|
|
28764
|
-
}
|
|
28765
|
-
} catch (e) {
|
|
28766
|
-
if (ssDebugCount <= 5) import_daemon_core3.LOG.warn("Screenshot", `error: ${e?.message}`);
|
|
28767
|
-
}
|
|
28768
|
-
this.screenshotTimer = setTimeout(screenshotTick, currentInterval);
|
|
28769
|
-
};
|
|
28770
|
-
this.screenshotTimer = setTimeout(screenshotTick, 1e3);
|
|
28876
|
+
this.screenshotController = new ScreenshotController({
|
|
28877
|
+
isRunning: () => this.running,
|
|
28878
|
+
isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
|
|
28879
|
+
getScreenshotIdeType: () => this.p2p?.screenshotIdeType,
|
|
28880
|
+
isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
|
|
28881
|
+
hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
|
|
28882
|
+
getCdp: (ideType) => (ideType ? this.getCdpFor(ideType) : null) || this.getAnyCdp(),
|
|
28883
|
+
sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
|
|
28884
|
+
}, planLimits ?? void 0);
|
|
28885
|
+
this.screenshotController.start();
|
|
28771
28886
|
} else {
|
|
28772
28887
|
console.log(import_chalk.default.gray(" \u26A0 P2P unavailable \u2014 using server relay"));
|
|
28773
28888
|
}
|
|
@@ -28781,7 +28896,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28781
28896
|
}
|
|
28782
28897
|
});
|
|
28783
28898
|
await this.serverConn.connect();
|
|
28784
|
-
this.statusReporter = new
|
|
28899
|
+
this.statusReporter = new import_daemon_core4.DaemonStatusReporter({
|
|
28785
28900
|
serverConn: this.serverConn,
|
|
28786
28901
|
cdpManagers: this.components.cdpManagers,
|
|
28787
28902
|
p2p: this.p2p,
|
|
@@ -28799,7 +28914,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28799
28914
|
process.on("SIGINT", () => this.stop());
|
|
28800
28915
|
process.on("SIGTERM", () => this.stop());
|
|
28801
28916
|
if (options.dev) {
|
|
28802
|
-
const devServer = new
|
|
28917
|
+
const devServer = new import_daemon_core4.DevServer({ providerLoader: this.components.providerLoader, cdpManagers: this.components.cdpManagers });
|
|
28803
28918
|
await devServer.start();
|
|
28804
28919
|
}
|
|
28805
28920
|
this.printBanner(options, config2.serverUrl);
|
|
@@ -28912,7 +29027,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28912
29027
|
}
|
|
28913
29028
|
}
|
|
28914
29029
|
async handleCommand(msg, cmd, args) {
|
|
28915
|
-
|
|
29030
|
+
import_daemon_core4.LOG.info("Command", `${cmd}${args?._targetInstance ? ` \u2192 ${args._targetType}:${args._targetInstance.split("_")[0]}` : ""}`);
|
|
28916
29031
|
const cmdStart = Date.now();
|
|
28917
29032
|
const source = msg.ipcWs ? "ext" : "ws";
|
|
28918
29033
|
try {
|
|
@@ -28920,7 +29035,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28920
29035
|
const cmdStr = args?.command;
|
|
28921
29036
|
if (!cmdStr) throw new Error("Command string required");
|
|
28922
29037
|
if (DANGEROUS_PATTERNS.some((p) => p.test(cmdStr))) {
|
|
28923
|
-
(0,
|
|
29038
|
+
(0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: false, error: "Blocked", durationMs: Date.now() - cmdStart });
|
|
28924
29039
|
this.sendResult(msg, false, { error: `Blocked: "${cmdStr}"` });
|
|
28925
29040
|
return;
|
|
28926
29041
|
}
|
|
@@ -28934,7 +29049,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28934
29049
|
if (stderr) this.serverConn.sendMessage("log", { message: stderr.slice(0, 5e3), level: "warn" });
|
|
28935
29050
|
}
|
|
28936
29051
|
});
|
|
28937
|
-
(0,
|
|
29052
|
+
(0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: true, durationMs: Date.now() - cmdStart });
|
|
28938
29053
|
this.sendResult(msg, true, { started: true });
|
|
28939
29054
|
return;
|
|
28940
29055
|
}
|
|
@@ -28951,16 +29066,16 @@ var init_adhdev_daemon = __esm({
|
|
|
28951
29066
|
try {
|
|
28952
29067
|
switch (cmdType) {
|
|
28953
29068
|
case "get_cli_history": {
|
|
28954
|
-
const config2 = (0,
|
|
28955
|
-
(0,
|
|
29069
|
+
const config2 = (0, import_daemon_core4.loadConfig)();
|
|
29070
|
+
(0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: true, durationMs: Date.now() - cmdStart });
|
|
28956
29071
|
return { success: true, history: config2.cliHistory || [] };
|
|
28957
29072
|
}
|
|
28958
29073
|
case "set_machine_nickname": {
|
|
28959
29074
|
const nickname = data.nickname?.trim() || null;
|
|
28960
|
-
const config2 = (0,
|
|
29075
|
+
const config2 = (0, import_daemon_core4.loadConfig)();
|
|
28961
29076
|
config2.machineNickname = nickname;
|
|
28962
|
-
(0,
|
|
28963
|
-
(0,
|
|
29077
|
+
(0, import_daemon_core4.saveConfig)(config2);
|
|
29078
|
+
(0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", args: { nickname }, success: true, durationMs: Date.now() - cmdStart });
|
|
28964
29079
|
return { success: true, nickname };
|
|
28965
29080
|
}
|
|
28966
29081
|
case "get_command_history": {
|
|
@@ -28972,7 +29087,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28972
29087
|
}
|
|
28973
29088
|
return await this.components.router.execute(cmdType, data, "p2p");
|
|
28974
29089
|
} catch (e) {
|
|
28975
|
-
(0,
|
|
29090
|
+
(0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: false, error: e.message, durationMs: Date.now() - cmdStart });
|
|
28976
29091
|
return { success: false, error: e.message };
|
|
28977
29092
|
}
|
|
28978
29093
|
}
|
|
@@ -28997,16 +29112,16 @@ var init_adhdev_daemon = __esm({
|
|
|
28997
29112
|
if (!this.running) return;
|
|
28998
29113
|
this.running = false;
|
|
28999
29114
|
console.log(import_chalk.default.yellow("\n Shutting down ADHDev Daemon..."));
|
|
29000
|
-
if (this.
|
|
29001
|
-
|
|
29002
|
-
this.
|
|
29115
|
+
if (this.screenshotController) {
|
|
29116
|
+
this.screenshotController.stop();
|
|
29117
|
+
this.screenshotController = null;
|
|
29003
29118
|
}
|
|
29004
29119
|
if (this.statusReporter) {
|
|
29005
29120
|
this.statusReporter.stopReporting();
|
|
29006
29121
|
this.statusReporter = null;
|
|
29007
29122
|
}
|
|
29008
29123
|
if (this.components) {
|
|
29009
|
-
await (0,
|
|
29124
|
+
await (0, import_daemon_core4.shutdownDaemonComponents)(this.components);
|
|
29010
29125
|
}
|
|
29011
29126
|
try {
|
|
29012
29127
|
this.p2p?.disconnect();
|
|
@@ -29060,7 +29175,7 @@ var import_chalk2 = __toESM(require("chalk"));
|
|
|
29060
29175
|
var import_inquirer = __toESM(require("inquirer"));
|
|
29061
29176
|
var import_ora = __toESM(require("ora"));
|
|
29062
29177
|
var import_open = __toESM(require("open"));
|
|
29063
|
-
var
|
|
29178
|
+
var import_daemon_core5 = __toESM(require_dist());
|
|
29064
29179
|
var SERVER_URL = process.env.ADHDEV_SERVER_URL || "https://api.adhf.dev";
|
|
29065
29180
|
var LOGO = `
|
|
29066
29181
|
${import_chalk2.default.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
|
|
@@ -29070,13 +29185,13 @@ ${import_chalk2.default.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u
|
|
|
29070
29185
|
`;
|
|
29071
29186
|
var DIVIDER = import_chalk2.default.gray("\u2500".repeat(44));
|
|
29072
29187
|
async function runWizard(options = {}) {
|
|
29073
|
-
const loader = new
|
|
29188
|
+
const loader = new import_daemon_core5.ProviderLoader({ logFn: () => {
|
|
29074
29189
|
} });
|
|
29075
29190
|
loader.loadAll();
|
|
29076
29191
|
loader.registerToDetector();
|
|
29077
29192
|
console.log(LOGO);
|
|
29078
|
-
if ((0,
|
|
29079
|
-
const config2 = (0,
|
|
29193
|
+
if ((0, import_daemon_core5.isSetupComplete)() && !options.force) {
|
|
29194
|
+
const config2 = (0, import_daemon_core5.loadConfig)();
|
|
29080
29195
|
console.log(import_chalk2.default.green("\u2713") + " ADHDev is already set up!");
|
|
29081
29196
|
const ides = config2.configuredIdes?.length ? config2.configuredIdes.join(", ") : config2.selectedIde || "none";
|
|
29082
29197
|
console.log(import_chalk2.default.gray(` IDEs: ${ides}`));
|
|
@@ -29105,7 +29220,7 @@ async function runWizard(options = {}) {
|
|
|
29105
29220
|
if (action === "relogin") {
|
|
29106
29221
|
const loginResult = await loginFlow();
|
|
29107
29222
|
if (loginResult) {
|
|
29108
|
-
(0,
|
|
29223
|
+
(0, import_daemon_core5.updateConfig)({
|
|
29109
29224
|
connectionToken: loginResult.connectionToken,
|
|
29110
29225
|
userEmail: loginResult.email,
|
|
29111
29226
|
userName: loginResult.name
|
|
@@ -29142,7 +29257,7 @@ async function runWizard(options = {}) {
|
|
|
29142
29257
|
async function quickSetup() {
|
|
29143
29258
|
console.log(import_chalk2.default.bold("\n\u{1F680} Quick Setup\n"));
|
|
29144
29259
|
const spinner = (0, import_ora.default)("Detecting installed IDEs...").start();
|
|
29145
|
-
const ides = await (0,
|
|
29260
|
+
const ides = await (0, import_daemon_core5.detectIDEs)();
|
|
29146
29261
|
const installedIDEs = ides.filter((i) => i.installed && i.cliCommand);
|
|
29147
29262
|
spinner.stop();
|
|
29148
29263
|
if (installedIDEs.length === 0) {
|
|
@@ -29190,9 +29305,9 @@ async function quickSetup() {
|
|
|
29190
29305
|
}
|
|
29191
29306
|
}
|
|
29192
29307
|
const ideIds = selectedIDEs.map((i) => i.id);
|
|
29193
|
-
(0,
|
|
29308
|
+
(0, import_daemon_core5.markSetupComplete)(ideIds, ["adhdev"]);
|
|
29194
29309
|
if (loginResult) {
|
|
29195
|
-
(0,
|
|
29310
|
+
(0, import_daemon_core5.updateConfig)({
|
|
29196
29311
|
connectionToken: loginResult.connectionToken,
|
|
29197
29312
|
userEmail: loginResult.email,
|
|
29198
29313
|
userName: loginResult.name
|
|
@@ -29222,7 +29337,7 @@ async function quickSetup() {
|
|
|
29222
29337
|
async function customSetup() {
|
|
29223
29338
|
console.log(import_chalk2.default.bold("\n\u{1F4CD} Step 1/4 \u2014 Detecting installed IDEs...\n"));
|
|
29224
29339
|
const spinner = (0, import_ora.default)("Scanning your system...").start();
|
|
29225
|
-
const ides = await (0,
|
|
29340
|
+
const ides = await (0, import_daemon_core5.detectIDEs)();
|
|
29226
29341
|
const installedIDEs = ides.filter((i) => i.installed);
|
|
29227
29342
|
spinner.stop();
|
|
29228
29343
|
if (installedIDEs.length === 0) {
|
|
@@ -29253,7 +29368,7 @@ async function customSetup() {
|
|
|
29253
29368
|
const selectedIDE = installedIDEs.find((i) => i.id === selectedIdeId);
|
|
29254
29369
|
console.log(DIVIDER);
|
|
29255
29370
|
console.log(import_chalk2.default.bold("\n\u{1F4CD} Step 3/4 \u2014 Choose AI extensions\n"));
|
|
29256
|
-
const aiExtensions = (0,
|
|
29371
|
+
const aiExtensions = (0, import_daemon_core5.getAIExtensions)();
|
|
29257
29372
|
const { selectedExtIds } = await import_inquirer.default.prompt([
|
|
29258
29373
|
{
|
|
29259
29374
|
type: "checkbox",
|
|
@@ -29270,7 +29385,7 @@ async function customSetup() {
|
|
|
29270
29385
|
const allExtensions = selectedAIExts;
|
|
29271
29386
|
console.log(import_chalk2.default.bold("\n\u{1F4CD} Step 4/4 \u2014 Installing extensions\n"));
|
|
29272
29387
|
if (selectedIDE.cliCommand) {
|
|
29273
|
-
await (0,
|
|
29388
|
+
await (0, import_daemon_core5.installExtensions)(
|
|
29274
29389
|
selectedIDE,
|
|
29275
29390
|
allExtensions,
|
|
29276
29391
|
(current, total, ext, result) => {
|
|
@@ -29289,9 +29404,9 @@ async function customSetup() {
|
|
|
29289
29404
|
if (loginResult?.connectionToken) {
|
|
29290
29405
|
await injectTokenToIDE(selectedIDE, loginResult.connectionToken);
|
|
29291
29406
|
}
|
|
29292
|
-
(0,
|
|
29407
|
+
(0, import_daemon_core5.markSetupComplete)(selectedIdeId, allExtensions.map((e) => e.id));
|
|
29293
29408
|
if (loginResult) {
|
|
29294
|
-
(0,
|
|
29409
|
+
(0, import_daemon_core5.updateConfig)({
|
|
29295
29410
|
connectionToken: loginResult.connectionToken,
|
|
29296
29411
|
userEmail: loginResult.email,
|
|
29297
29412
|
userName: loginResult.name
|
|
@@ -29397,7 +29512,7 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
29397
29512
|
return path3.join(home, ".config", appName2, "User", "settings.json");
|
|
29398
29513
|
}
|
|
29399
29514
|
};
|
|
29400
|
-
const loader = new
|
|
29515
|
+
const loader = new import_daemon_core5.ProviderLoader({ logFn: () => {
|
|
29401
29516
|
} });
|
|
29402
29517
|
loader.loadAll();
|
|
29403
29518
|
const appNameMap = loader.getMacAppIdentifiers();
|