adhdev 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-entrypoint.js +685 -236
- package/dist/cli-entrypoint.js.map +1 -1
- package/dist/index.js +676 -226
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/providers/_builtin/COMPATIBILITY.md +0 -217
- package/providers/_builtin/CONTRIBUTING.md +0 -141
- package/providers/_builtin/README.md +0 -51
- package/providers/_builtin/_helpers/index.js +0 -188
- package/providers/_builtin/acp/agentpool/provider.json +0 -54
- package/providers/_builtin/acp/amp/provider.json +0 -52
- package/providers/_builtin/acp/auggie/provider.json +0 -57
- package/providers/_builtin/acp/autodev/provider.json +0 -54
- package/providers/_builtin/acp/autohand/provider.json +0 -52
- package/providers/_builtin/acp/blackbox-ai/provider.json +0 -54
- package/providers/_builtin/acp/claude-agent/provider.json +0 -57
- package/providers/_builtin/acp/cline-acp/provider.json +0 -54
- package/providers/_builtin/acp/codebuddy/provider.json +0 -54
- package/providers/_builtin/acp/codex-cli/provider.json +0 -57
- package/providers/_builtin/acp/corust-agent/provider.json +0 -52
- package/providers/_builtin/acp/crow-cli/provider.json +0 -54
- package/providers/_builtin/acp/cursor-acp/provider.json +0 -54
- package/providers/_builtin/acp/deepagents/provider.json +0 -52
- package/providers/_builtin/acp/dimcode/provider.json +0 -54
- package/providers/_builtin/acp/docker-cagent/provider.json +0 -57
- package/providers/_builtin/acp/factory-droid/provider.json +0 -60
- package/providers/_builtin/acp/fast-agent/provider.json +0 -52
- package/providers/_builtin/acp/gemini-cli/provider.json +0 -114
- package/providers/_builtin/acp/github-copilot/provider.json +0 -54
- package/providers/_builtin/acp/goose/provider.json +0 -57
- package/providers/_builtin/acp/junie/provider.json +0 -52
- package/providers/_builtin/acp/kilo/provider.json +0 -54
- package/providers/_builtin/acp/kimi-cli/provider.json +0 -57
- package/providers/_builtin/acp/minion-code/provider.json +0 -52
- package/providers/_builtin/acp/mistral-vibe/provider.json +0 -57
- package/providers/_builtin/acp/nova/provider.json +0 -54
- package/providers/_builtin/acp/openclaw/provider.json +0 -54
- package/providers/_builtin/acp/opencode/provider.json +0 -52
- package/providers/_builtin/acp/openhands/provider.json +0 -54
- package/providers/_builtin/acp/pi-acp/provider.json +0 -52
- package/providers/_builtin/acp/qoder/provider.json +0 -54
- package/providers/_builtin/acp/qwen-code/provider.json +0 -60
- package/providers/_builtin/acp/stakpak/provider.json +0 -54
- package/providers/_builtin/acp/vtcode/provider.json +0 -54
- package/providers/_builtin/cli/claude-cli/provider.json +0 -100
- package/providers/_builtin/cli/codex-cli/provider.json +0 -89
- package/providers/_builtin/cli/gemini-cli/provider.json +0 -93
- package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +0 -370
- package/providers/_builtin/docs/PROVIDER_GUIDE.md +0 -916
- package/providers/_builtin/extension/cline/provider.json +0 -35
- package/providers/_builtin/extension/cline/scripts/focus_editor.js +0 -48
- package/providers/_builtin/extension/cline/scripts/list_chats.js +0 -100
- package/providers/_builtin/extension/cline/scripts/list_models.js +0 -43
- package/providers/_builtin/extension/cline/scripts/list_modes.js +0 -35
- package/providers/_builtin/extension/cline/scripts/new_session.js +0 -85
- package/providers/_builtin/extension/cline/scripts/open_panel.js +0 -25
- package/providers/_builtin/extension/cline/scripts/read_chat.js +0 -257
- package/providers/_builtin/extension/cline/scripts/resolve_action.js +0 -83
- package/providers/_builtin/extension/cline/scripts/send_message.js +0 -95
- package/providers/_builtin/extension/cline/scripts/set_mode.js +0 -36
- package/providers/_builtin/extension/cline/scripts/set_model.js +0 -36
- package/providers/_builtin/extension/cline/scripts/switch_session.js +0 -206
- package/providers/_builtin/extension/cline/scripts.js +0 -73
- package/providers/_builtin/extension/roo-code/provider.json +0 -35
- package/providers/_builtin/extension/roo-code/scripts.js +0 -659
- package/providers/_builtin/ide/antigravity/provider.json +0 -63
- package/providers/_builtin/ide/antigravity/scripts/focus_editor.js +0 -20
- package/providers/_builtin/ide/antigravity/scripts/legacy/list_models.js +0 -38
- package/providers/_builtin/ide/antigravity/scripts/legacy/list_modes.js +0 -48
- package/providers/_builtin/ide/antigravity/scripts/legacy/scripts.js +0 -64
- package/providers/_builtin/ide/antigravity/scripts/legacy/set_mode.js +0 -34
- package/providers/_builtin/ide/antigravity/scripts/legacy/set_model.js +0 -47
- package/providers/_builtin/ide/antigravity/scripts/list_chats.js +0 -137
- package/providers/_builtin/ide/antigravity/scripts/list_models.js +0 -61
- package/providers/_builtin/ide/antigravity/scripts/list_modes.js +0 -72
- package/providers/_builtin/ide/antigravity/scripts/new_session.js +0 -75
- package/providers/_builtin/ide/antigravity/scripts/read_chat.js +0 -262
- package/providers/_builtin/ide/antigravity/scripts/resolve_action.js +0 -68
- package/providers/_builtin/ide/antigravity/scripts/send_message.js +0 -56
- package/providers/_builtin/ide/antigravity/scripts/set_mode.js +0 -67
- package/providers/_builtin/ide/antigravity/scripts/set_model.js +0 -72
- package/providers/_builtin/ide/antigravity/scripts/switch_session.js +0 -114
- package/providers/_builtin/ide/antigravity/scripts.js +0 -67
- package/providers/_builtin/ide/cursor/provider.json +0 -59
- package/providers/_builtin/ide/cursor/scripts.js +0 -458
- package/providers/_builtin/ide/kiro/provider.json +0 -60
- package/providers/_builtin/ide/kiro/scripts/focus_editor.js +0 -20
- package/providers/_builtin/ide/kiro/scripts/open_panel.js +0 -47
- package/providers/_builtin/ide/kiro/scripts/resolve_action.js +0 -54
- package/providers/_builtin/ide/kiro/scripts/send_message.js +0 -29
- package/providers/_builtin/ide/kiro/scripts/webview_list_models.js +0 -39
- package/providers/_builtin/ide/kiro/scripts/webview_list_modes.js +0 -39
- package/providers/_builtin/ide/kiro/scripts/webview_list_sessions.js +0 -21
- package/providers/_builtin/ide/kiro/scripts/webview_new_session.js +0 -34
- package/providers/_builtin/ide/kiro/scripts/webview_read_chat.js +0 -68
- package/providers/_builtin/ide/kiro/scripts/webview_send_message.js +0 -72
- package/providers/_builtin/ide/kiro/scripts/webview_set_mode.js +0 -15
- package/providers/_builtin/ide/kiro/scripts/webview_set_model.js +0 -15
- package/providers/_builtin/ide/kiro/scripts/webview_switch_session.js +0 -26
- package/providers/_builtin/ide/kiro/scripts.js +0 -62
- package/providers/_builtin/ide/pearai/provider.json +0 -60
- package/providers/_builtin/ide/pearai/scripts/focus_editor.js +0 -20
- package/providers/_builtin/ide/pearai/scripts/list_sessions.js +0 -38
- package/providers/_builtin/ide/pearai/scripts/new_session.js +0 -55
- package/providers/_builtin/ide/pearai/scripts/open_panel.js +0 -46
- package/providers/_builtin/ide/pearai/scripts/resolve_action.js +0 -54
- package/providers/_builtin/ide/pearai/scripts/send_message.js +0 -29
- package/providers/_builtin/ide/pearai/scripts/webview_list_models.js +0 -43
- package/providers/_builtin/ide/pearai/scripts/webview_list_modes.js +0 -35
- package/providers/_builtin/ide/pearai/scripts/webview_list_sessions.js +0 -62
- package/providers/_builtin/ide/pearai/scripts/webview_new_session.js +0 -49
- package/providers/_builtin/ide/pearai/scripts/webview_read_chat.js +0 -92
- package/providers/_builtin/ide/pearai/scripts/webview_resolve_action.js +0 -59
- package/providers/_builtin/ide/pearai/scripts/webview_send_message.js +0 -72
- package/providers/_builtin/ide/pearai/scripts/webview_set_mode.js +0 -36
- package/providers/_builtin/ide/pearai/scripts/webview_set_model.js +0 -36
- package/providers/_builtin/ide/pearai/scripts/webview_switch_session.js +0 -34
- package/providers/_builtin/ide/pearai/scripts.js +0 -74
- package/providers/_builtin/ide/trae/provider.json +0 -59
- package/providers/_builtin/ide/trae/scripts/focus_editor.js +0 -20
- package/providers/_builtin/ide/trae/scripts/list_chats.js +0 -24
- package/providers/_builtin/ide/trae/scripts/list_models.js +0 -39
- package/providers/_builtin/ide/trae/scripts/list_modes.js +0 -39
- package/providers/_builtin/ide/trae/scripts/new_session.js +0 -30
- package/providers/_builtin/ide/trae/scripts/open_panel.js +0 -44
- package/providers/_builtin/ide/trae/scripts/read_chat.js +0 -113
- package/providers/_builtin/ide/trae/scripts/resolve_action.js +0 -54
- package/providers/_builtin/ide/trae/scripts/send_message.js +0 -69
- package/providers/_builtin/ide/trae/scripts/set_mode.js +0 -15
- package/providers/_builtin/ide/trae/scripts/set_model.js +0 -15
- package/providers/_builtin/ide/trae/scripts/switch_session.js +0 -23
- package/providers/_builtin/ide/trae/scripts.js +0 -57
- package/providers/_builtin/ide/vscode/provider.json +0 -57
- package/providers/_builtin/ide/vscode-insiders/provider.json +0 -55
- package/providers/_builtin/ide/vscodium/provider.json +0 -56
- package/providers/_builtin/ide/windsurf/provider.json +0 -46
- package/providers/_builtin/ide/windsurf/scripts/focus_editor.js +0 -30
- package/providers/_builtin/ide/windsurf/scripts/list_chats.js +0 -117
- package/providers/_builtin/ide/windsurf/scripts/list_models.js +0 -39
- package/providers/_builtin/ide/windsurf/scripts/list_modes.js +0 -39
- package/providers/_builtin/ide/windsurf/scripts/new_session.js +0 -69
- package/providers/_builtin/ide/windsurf/scripts/open_panel.js +0 -58
- package/providers/_builtin/ide/windsurf/scripts/read_chat.js +0 -297
- package/providers/_builtin/ide/windsurf/scripts/resolve_action.js +0 -68
- package/providers/_builtin/ide/windsurf/scripts/send_message.js +0 -87
- package/providers/_builtin/ide/windsurf/scripts/set_mode.js +0 -15
- package/providers/_builtin/ide/windsurf/scripts/set_model.js +0 -15
- package/providers/_builtin/ide/windsurf/scripts/switch_session.js +0 -58
- package/providers/_builtin/ide/windsurf/scripts.js +0 -57
- package/providers/_builtin/validate.js +0 -156
package/dist/cli-entrypoint.js
CHANGED
|
@@ -16382,14 +16382,14 @@ var require_dist = __commonJS({
|
|
|
16382
16382
|
updateConfig: () => updateConfig2
|
|
16383
16383
|
});
|
|
16384
16384
|
function getConfigDir() {
|
|
16385
|
-
const dir = (0,
|
|
16385
|
+
const dir = (0, import_path2.join)((0, import_os.homedir)(), ".adhdev");
|
|
16386
16386
|
if (!(0, import_fs2.existsSync)(dir)) {
|
|
16387
16387
|
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
16388
16388
|
}
|
|
16389
16389
|
return dir;
|
|
16390
16390
|
}
|
|
16391
16391
|
function getConfigPath() {
|
|
16392
|
-
return (0,
|
|
16392
|
+
return (0, import_path2.join)(getConfigDir(), "config.json");
|
|
16393
16393
|
}
|
|
16394
16394
|
function loadConfig4() {
|
|
16395
16395
|
const configPath = getConfigPath();
|
|
@@ -16464,14 +16464,14 @@ var require_dist = __commonJS({
|
|
|
16464
16464
|
saveConfig2(config2);
|
|
16465
16465
|
}
|
|
16466
16466
|
var import_os;
|
|
16467
|
-
var
|
|
16467
|
+
var import_path2;
|
|
16468
16468
|
var import_fs2;
|
|
16469
16469
|
var DEFAULT_CONFIG;
|
|
16470
16470
|
var init_config = __esm2({
|
|
16471
16471
|
"src/config/config.ts"() {
|
|
16472
16472
|
"use strict";
|
|
16473
16473
|
import_os = require("os");
|
|
16474
|
-
|
|
16474
|
+
import_path2 = require("path");
|
|
16475
16475
|
import_fs2 = require("fs");
|
|
16476
16476
|
DEFAULT_CONFIG = {
|
|
16477
16477
|
serverUrl: "https://api.adhf.dev",
|
|
@@ -16915,13 +16915,44 @@ var require_dist = __commonJS({
|
|
|
16915
16915
|
// Connect to specific targetId (multi-window support)
|
|
16916
16916
|
_pageTitle = "";
|
|
16917
16917
|
// Connected page title
|
|
16918
|
-
|
|
16918
|
+
_targetFilter;
|
|
16919
|
+
// Provider-configurable target selection
|
|
16920
|
+
constructor(port = 9333, logFn, targetId, targetFilter) {
|
|
16919
16921
|
this.port = port;
|
|
16920
16922
|
this._targetId = targetId || null;
|
|
16923
|
+
this._targetFilter = targetFilter || {};
|
|
16921
16924
|
this.logFn = logFn || ((msg) => {
|
|
16922
16925
|
LOG4.info("CDP", msg);
|
|
16923
16926
|
});
|
|
16924
16927
|
}
|
|
16928
|
+
/** Set target filter (can be updated after construction) */
|
|
16929
|
+
setTargetFilter(filter) {
|
|
16930
|
+
this._targetFilter = filter;
|
|
16931
|
+
}
|
|
16932
|
+
/**
|
|
16933
|
+
* Check if a page title should be excluded (non-main page).
|
|
16934
|
+
* Uses provider-configured titleExcludes, falls back to default pattern.
|
|
16935
|
+
*/
|
|
16936
|
+
isNonMainTitle(title) {
|
|
16937
|
+
if (!title) return true;
|
|
16938
|
+
const pattern = this._targetFilter.titleExcludes || "extension-output|ADHDev CDP|Debug Console|Output\\s*$|Launchpad";
|
|
16939
|
+
return new RegExp(pattern, "i").test(title);
|
|
16940
|
+
}
|
|
16941
|
+
/**
|
|
16942
|
+
* Check if a page URL matches the main window criteria.
|
|
16943
|
+
* Uses provider-configured urlIncludes/urlExcludes.
|
|
16944
|
+
*/
|
|
16945
|
+
isMainPageUrl(url2) {
|
|
16946
|
+
if (!url2) return true;
|
|
16947
|
+
const { urlIncludes, urlExcludes } = this._targetFilter;
|
|
16948
|
+
if (urlIncludes && !url2.includes(urlIncludes)) return false;
|
|
16949
|
+
if (urlExcludes) {
|
|
16950
|
+
for (const exc of urlExcludes) {
|
|
16951
|
+
if (url2.includes(exc)) return false;
|
|
16952
|
+
}
|
|
16953
|
+
}
|
|
16954
|
+
return true;
|
|
16955
|
+
}
|
|
16925
16956
|
/** Connected page title (includes workspace name) */
|
|
16926
16957
|
get pageTitle() {
|
|
16927
16958
|
return this._pageTitle;
|
|
@@ -16941,7 +16972,8 @@ var require_dist = __commonJS({
|
|
|
16941
16972
|
const pages = targets.filter(
|
|
16942
16973
|
(t) => t.type === "page" && t.webSocketDebuggerUrl
|
|
16943
16974
|
);
|
|
16944
|
-
const
|
|
16975
|
+
const defaultExclude = /extension-output|ADHDev CDP|Debug Console|Output\s*$|Launchpad/i;
|
|
16976
|
+
const isNonMain = (title) => !title || defaultExclude.test(title);
|
|
16945
16977
|
const mainPages = pages.filter(
|
|
16946
16978
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
16947
16979
|
);
|
|
@@ -17009,8 +17041,7 @@ var require_dist = __commonJS({
|
|
|
17009
17041
|
resolve5(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
17010
17042
|
return;
|
|
17011
17043
|
}
|
|
17012
|
-
const
|
|
17013
|
-
const mainPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
17044
|
+
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
17014
17045
|
const list = mainPages.length > 0 ? mainPages : pages;
|
|
17015
17046
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
17016
17047
|
if (this._targetId) {
|
|
@@ -21577,7 +21608,7 @@ ${installInfo}`
|
|
|
21577
21608
|
var os9 = __toESM2(require("os"));
|
|
21578
21609
|
var ProviderLoader4 = class _ProviderLoader {
|
|
21579
21610
|
providers = /* @__PURE__ */ new Map();
|
|
21580
|
-
|
|
21611
|
+
builtinDirs;
|
|
21581
21612
|
userDir;
|
|
21582
21613
|
upstreamDir;
|
|
21583
21614
|
watchers = [];
|
|
@@ -21590,7 +21621,11 @@ ${installInfo}`
|
|
|
21590
21621
|
static GITHUB_TARBALL_URL = "https://github.com/vilmire/adhdev-providers/archive/refs/heads/main.tar.gz";
|
|
21591
21622
|
static META_FILE = ".meta.json";
|
|
21592
21623
|
constructor(options) {
|
|
21593
|
-
|
|
21624
|
+
if (options?.builtinDir) {
|
|
21625
|
+
this.builtinDirs = Array.isArray(options.builtinDir) ? options.builtinDir : [options.builtinDir];
|
|
21626
|
+
} else {
|
|
21627
|
+
this.builtinDirs = [path6.resolve(__dirname, "../providers/_builtin")];
|
|
21628
|
+
}
|
|
21594
21629
|
this.userDir = options?.userDir || path6.join(os9.homedir(), ".adhdev", "providers");
|
|
21595
21630
|
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
21596
21631
|
this.logFn = options?.logFn || LOG4.forComponent("Provider").asLogFn();
|
|
@@ -21601,14 +21636,19 @@ ${installInfo}`
|
|
|
21601
21636
|
// ─── Public API ────────────────────────────────
|
|
21602
21637
|
/**
|
|
21603
21638
|
* Load all providers (3-tier priority)
|
|
21604
|
-
* 1. _builtin/ (bundled fallback)
|
|
21639
|
+
* 1. _builtin/ (bundled fallback, or multiple array dirs)
|
|
21605
21640
|
* 2. .upstream/ (GitHub auto-download)
|
|
21606
21641
|
* 3. User custom (~/.adhdev/providers/ excluding _upstream)
|
|
21607
21642
|
* Later loads override earlier ones, so user custom always wins.
|
|
21608
21643
|
*/
|
|
21609
21644
|
loadAll() {
|
|
21610
21645
|
this.providers.clear();
|
|
21611
|
-
|
|
21646
|
+
let builtinCount = 0;
|
|
21647
|
+
for (const dir of this.builtinDirs) {
|
|
21648
|
+
if (fs5.existsSync(dir)) {
|
|
21649
|
+
builtinCount += this.loadDir(dir);
|
|
21650
|
+
}
|
|
21651
|
+
}
|
|
21612
21652
|
this.log(`Loaded ${builtinCount} builtin providers`);
|
|
21613
21653
|
let upstreamCount = 0;
|
|
21614
21654
|
if (fs5.existsSync(this.upstreamDir)) {
|
|
@@ -21628,7 +21668,7 @@ ${installInfo}`
|
|
|
21628
21668
|
this.log(`\u26A0 Using bundled providers only (upstream not available). Run 'adhdev daemon' with internet to auto-update.`);
|
|
21629
21669
|
}
|
|
21630
21670
|
if (this.providers.size === 0) {
|
|
21631
|
-
this.log(`\u274C No providers loaded! Check
|
|
21671
|
+
this.log(`\u274C No providers loaded! Check builtinDirs.`);
|
|
21632
21672
|
}
|
|
21633
21673
|
}
|
|
21634
21674
|
/**
|
|
@@ -21812,14 +21852,15 @@ ${installInfo}`
|
|
|
21812
21852
|
/**
|
|
21813
21853
|
* Return final provider with OS/version overrides applied.
|
|
21814
21854
|
*
|
|
21815
|
-
*
|
|
21816
|
-
* 1.
|
|
21817
|
-
*
|
|
21818
|
-
*
|
|
21855
|
+
* Script resolution order:
|
|
21856
|
+
* 1. compatibility array (new format — preferred)
|
|
21857
|
+
* Provider.json defines: "compatibility": [{ "ideVersion": ">=1.107.0", "scriptDir": "scripts/1.107" }]
|
|
21858
|
+
* First matching range wins. Fallback: defaultScriptDir.
|
|
21859
|
+
* 2. versions field (legacy format — backward compat)
|
|
21860
|
+
* "versions": { "< 1.107.0": { "__dir": "scripts/legacy" } }
|
|
21861
|
+
* 3. Root scripts.js (original format — no versioning)
|
|
21819
21862
|
*
|
|
21820
|
-
*
|
|
21821
|
-
* "versions": { "< 1.107.0": { "__dir": "scripts/legacy" } }
|
|
21822
|
-
* When __dir is set, the scripts.js is re-required from that subdirectory.
|
|
21863
|
+
* Version source: context.version → VersionArchive → undefined
|
|
21823
21864
|
*/
|
|
21824
21865
|
resolve(type, context) {
|
|
21825
21866
|
const base = this.providers.get(type);
|
|
@@ -21842,36 +21883,51 @@ ${installInfo}`
|
|
|
21842
21883
|
if (osOverride.inputSelector) resolved.inputSelector = osOverride.inputSelector;
|
|
21843
21884
|
resolved._resolvedOs = currentOs;
|
|
21844
21885
|
}
|
|
21845
|
-
if (currentVersion
|
|
21846
|
-
|
|
21847
|
-
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
21856
|
-
|
|
21857
|
-
resolved.scripts = require(altScriptsPath);
|
|
21858
|
-
this.log(` [version override] ${type} ${range} \u2192 scripts from ${dirOverride}/scripts.js`);
|
|
21859
|
-
} catch (e) {
|
|
21860
|
-
this.log(` \u26A0 version override scripts load failed: ${altScriptsPath}: ${e.message}`);
|
|
21861
|
-
}
|
|
21862
|
-
} else {
|
|
21863
|
-
const altDir = path6.join(providerDir, dirOverride);
|
|
21864
|
-
if (fs5.existsSync(altDir)) {
|
|
21865
|
-
const wrappers = this.buildScriptWrappersFromDir(altDir);
|
|
21866
|
-
resolved.scripts = { ...resolved.scripts, ...wrappers };
|
|
21867
|
-
this.log(` [version override] ${type} ${range} \u2192 individual scripts from ${dirOverride}/`);
|
|
21868
|
-
}
|
|
21886
|
+
if (currentVersion) {
|
|
21887
|
+
resolved._resolvedVersion = currentVersion;
|
|
21888
|
+
if (Array.isArray(base.compatibility)) {
|
|
21889
|
+
const compat = base.compatibility;
|
|
21890
|
+
let matched = false;
|
|
21891
|
+
for (const entry of compat) {
|
|
21892
|
+
if (this.matchesVersion(currentVersion, entry.ideVersion)) {
|
|
21893
|
+
const loaded = this.loadScriptsFromDir(type, entry.scriptDir);
|
|
21894
|
+
if (loaded) {
|
|
21895
|
+
resolved.scripts = loaded;
|
|
21896
|
+
this.log(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
|
|
21897
|
+
matched = true;
|
|
21869
21898
|
}
|
|
21899
|
+
break;
|
|
21900
|
+
}
|
|
21901
|
+
}
|
|
21902
|
+
if (!matched && base.defaultScriptDir) {
|
|
21903
|
+
const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
|
|
21904
|
+
if (loaded) {
|
|
21905
|
+
resolved.scripts = loaded;
|
|
21906
|
+
this.log(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
|
|
21907
|
+
}
|
|
21908
|
+
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
21909
|
+
}
|
|
21910
|
+
} else if (base.versions) {
|
|
21911
|
+
for (const [range, override] of Object.entries(base.versions)) {
|
|
21912
|
+
if (!this.matchesVersion(currentVersion, range)) continue;
|
|
21913
|
+
const dirOverride = override.__dir;
|
|
21914
|
+
if (dirOverride) {
|
|
21915
|
+
const loaded = this.loadScriptsFromDir(type, dirOverride);
|
|
21916
|
+
if (loaded) {
|
|
21917
|
+
resolved.scripts = loaded;
|
|
21918
|
+
this.log(` [version override] ${type} ${range} \u2192 ${dirOverride}`);
|
|
21919
|
+
}
|
|
21920
|
+
} else if (override.scripts) {
|
|
21921
|
+
resolved.scripts = { ...resolved.scripts, ...override.scripts };
|
|
21870
21922
|
}
|
|
21871
|
-
} else if (override.scripts) {
|
|
21872
|
-
resolved.scripts = { ...resolved.scripts, ...override.scripts };
|
|
21873
21923
|
}
|
|
21874
21924
|
}
|
|
21925
|
+
} else if (Array.isArray(base.compatibility) && base.defaultScriptDir) {
|
|
21926
|
+
const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
|
|
21927
|
+
if (loaded) {
|
|
21928
|
+
resolved.scripts = loaded;
|
|
21929
|
+
this.log(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
|
|
21930
|
+
}
|
|
21875
21931
|
}
|
|
21876
21932
|
if (base.overrides) {
|
|
21877
21933
|
for (const override of base.overrides) {
|
|
@@ -21884,6 +21940,36 @@ ${installInfo}`
|
|
|
21884
21940
|
}
|
|
21885
21941
|
return resolved;
|
|
21886
21942
|
}
|
|
21943
|
+
/**
|
|
21944
|
+
* Load scripts from a scriptDir within a provider directory.
|
|
21945
|
+
* Tries scripts.js first, then individual .js files.
|
|
21946
|
+
*/
|
|
21947
|
+
loadScriptsFromDir(type, scriptDir) {
|
|
21948
|
+
const providerDir = this.findProviderDir(type);
|
|
21949
|
+
if (!providerDir) {
|
|
21950
|
+
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
21951
|
+
return null;
|
|
21952
|
+
}
|
|
21953
|
+
const dir = path6.join(providerDir, scriptDir);
|
|
21954
|
+
if (!fs5.existsSync(dir)) {
|
|
21955
|
+
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
21956
|
+
return null;
|
|
21957
|
+
}
|
|
21958
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
21959
|
+
if (fs5.existsSync(scriptsJs)) {
|
|
21960
|
+
try {
|
|
21961
|
+
delete require.cache[require.resolve(scriptsJs)];
|
|
21962
|
+
const loaded = require(scriptsJs);
|
|
21963
|
+
this.log(` [loadScriptsFromDir] ${type}: loaded scripts.js from ${dir} (${Object.keys(loaded).length} exports)`);
|
|
21964
|
+
return loaded;
|
|
21965
|
+
} catch (e) {
|
|
21966
|
+
this.log(` \u26A0 scripts.js load failed: ${scriptsJs}: ${e.message}`);
|
|
21967
|
+
}
|
|
21968
|
+
}
|
|
21969
|
+
const result = this.buildScriptWrappersFromDir(dir);
|
|
21970
|
+
this.log(` [loadScriptsFromDir] ${type}: built wrappers from ${dir} (${Object.keys(result).length} scripts)`);
|
|
21971
|
+
return result;
|
|
21972
|
+
}
|
|
21887
21973
|
/**
|
|
21888
21974
|
* Hot-reload: start watching for file changes
|
|
21889
21975
|
*/
|
|
@@ -21909,7 +21995,7 @@ ${installInfo}`
|
|
|
21909
21995
|
this.log(`Watch failed for ${dir}: ${e.message}`);
|
|
21910
21996
|
}
|
|
21911
21997
|
};
|
|
21912
|
-
|
|
21998
|
+
this.builtinDirs.forEach((dir) => watchDir(dir));
|
|
21913
21999
|
watchDir(this.userDir);
|
|
21914
22000
|
}
|
|
21915
22001
|
/**
|
|
@@ -22217,7 +22303,7 @@ ${installInfo}`
|
|
|
22217
22303
|
const provider2 = this.providers.get(type);
|
|
22218
22304
|
if (!provider2) return null;
|
|
22219
22305
|
const cat = provider2.category;
|
|
22220
|
-
const searchRoots = [this.userDir, this.upstreamDir, this.
|
|
22306
|
+
const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
|
|
22221
22307
|
for (const root of searchRoots) {
|
|
22222
22308
|
if (!fs5.existsSync(root)) continue;
|
|
22223
22309
|
for (const candidate of [path6.join(root, type), path6.join(root, cat, type)]) {
|
|
@@ -22307,8 +22393,9 @@ ${installInfo}`
|
|
|
22307
22393
|
mod.extensionIdPattern = new RegExp(mod.extensionIdPattern, flags);
|
|
22308
22394
|
delete mod.extensionIdPattern_flags;
|
|
22309
22395
|
}
|
|
22396
|
+
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
22310
22397
|
const scriptsPath = path6.join(d, "scripts.js");
|
|
22311
|
-
if (fs5.existsSync(scriptsPath)) {
|
|
22398
|
+
if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
|
|
22312
22399
|
try {
|
|
22313
22400
|
delete require.cache[require.resolve(scriptsPath)];
|
|
22314
22401
|
const scripts = require(scriptsPath);
|
|
@@ -23811,7 +23898,7 @@ ${installInfo}`
|
|
|
23811
23898
|
var path9 = __toESM2(require("path"));
|
|
23812
23899
|
var os12 = __toESM2(require("os"));
|
|
23813
23900
|
function generateFiles(type, name, category, opts = {}) {
|
|
23814
|
-
const { cdpPorts, cli, processName, installPath, binary, extensionId } = opts;
|
|
23901
|
+
const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
|
|
23815
23902
|
if (category === "cli" || category === "acp") {
|
|
23816
23903
|
const bin = binary || type;
|
|
23817
23904
|
const meta22 = {
|
|
@@ -23835,6 +23922,7 @@ ${installInfo}`
|
|
|
23835
23922
|
return { "provider.json": JSON.stringify(meta22, null, 2) + "\n" };
|
|
23836
23923
|
}
|
|
23837
23924
|
const isExtension = category === "extension";
|
|
23925
|
+
const scriptDir = `scripts/${version2}`;
|
|
23838
23926
|
const meta3 = {
|
|
23839
23927
|
type,
|
|
23840
23928
|
name,
|
|
@@ -23853,159 +23941,284 @@ ${installInfo}`
|
|
|
23853
23941
|
} else {
|
|
23854
23942
|
meta3.inputMethod = "cdp-type-and-send";
|
|
23855
23943
|
meta3.inputSelector = '[contenteditable="true"][role="textbox"]';
|
|
23944
|
+
meta3.providerVersion = "1.0.0";
|
|
23945
|
+
meta3.compatibility = [
|
|
23946
|
+
{ ideVersion: `>=${version2}.0`, scriptDir }
|
|
23947
|
+
];
|
|
23948
|
+
meta3.defaultScriptDir = scriptDir;
|
|
23856
23949
|
}
|
|
23857
|
-
const
|
|
23858
|
-
|
|
23859
|
-
*
|
|
23860
|
-
* Each exported function receives a params object and returns
|
|
23861
|
-
* a JavaScript expression string to be evaluated in the IDE's DOM.
|
|
23950
|
+
const files = {};
|
|
23951
|
+
files[`${scriptDir}/scripts.js`] = `/**
|
|
23952
|
+
* ${name} CDP Scripts \u2014 Router
|
|
23862
23953
|
*
|
|
23863
|
-
*
|
|
23864
|
-
*
|
|
23954
|
+
* Loads individual .js files and invokes with params.
|
|
23955
|
+
* Pattern:
|
|
23956
|
+
* - No-params scripts: loaded as-is (IIFE)
|
|
23957
|
+
* - With-params scripts: \`(\${script})(\${JSON.stringify(params)})\`
|
|
23865
23958
|
*/
|
|
23866
23959
|
|
|
23867
|
-
|
|
23868
|
-
return \`(() => {
|
|
23869
|
-
try {
|
|
23870
|
-
const messages = [];
|
|
23871
|
-
let status = 'idle';
|
|
23872
|
-
let activeModal = null;
|
|
23960
|
+
'use strict';
|
|
23873
23961
|
|
|
23874
|
-
|
|
23875
|
-
|
|
23876
|
-
// document.querySelectorAll('.chat-message').forEach(el => {
|
|
23877
|
-
// const role = el.classList.contains('user') ? 'user' : 'assistant';
|
|
23878
|
-
// messages.push({ role, content: el.innerText.trim(), index: messages.length });
|
|
23879
|
-
// });
|
|
23962
|
+
const fs = require('fs');
|
|
23963
|
+
const path = require('path');
|
|
23880
23964
|
|
|
23881
|
-
|
|
23882
|
-
|
|
23883
|
-
|
|
23884
|
-
|
|
23885
|
-
// if (approvalBtns.length > 0) {
|
|
23886
|
-
// status = 'waiting_approval';
|
|
23887
|
-
// activeModal = { message: 'Action required', buttons: approvalBtns.map(b => b.textContent.trim()) };
|
|
23888
|
-
// }
|
|
23965
|
+
function load(name) {
|
|
23966
|
+
try { return fs.readFileSync(path.join(__dirname, name), 'utf-8'); }
|
|
23967
|
+
catch { return null; }
|
|
23968
|
+
}
|
|
23889
23969
|
|
|
23890
|
-
|
|
23891
|
-
|
|
23892
|
-
|
|
23893
|
-
|
|
23894
|
-
|
|
23895
|
-
}
|
|
23896
|
-
})()\`;
|
|
23897
|
-
};
|
|
23970
|
+
function withParams(name, params) {
|
|
23971
|
+
const script = load(name);
|
|
23972
|
+
if (!script) return null;
|
|
23973
|
+
return \`(\${script})(\${JSON.stringify(params)})\`;
|
|
23974
|
+
}
|
|
23898
23975
|
|
|
23899
|
-
|
|
23900
|
-
const text = typeof params === 'string' ? params : params?.text;
|
|
23901
|
-
return \`(() => {
|
|
23902
|
-
try {
|
|
23903
|
-
// Most VS Code-based IDEs use needsTypeAndSend for reliable input
|
|
23904
|
-
return JSON.stringify({
|
|
23905
|
-
sent: false,
|
|
23906
|
-
needsTypeAndSend: true,
|
|
23907
|
-
selector: '[contenteditable="true"]',
|
|
23908
|
-
});
|
|
23909
|
-
} catch(e) {
|
|
23910
|
-
return JSON.stringify({ sent: false, error: e.message });
|
|
23911
|
-
}
|
|
23912
|
-
})()\`;
|
|
23913
|
-
};
|
|
23976
|
+
// \u2500\u2500\u2500 Core (no params \u2014 IIFE) \u2500\u2500\u2500
|
|
23914
23977
|
|
|
23915
|
-
module.exports.
|
|
23916
|
-
|
|
23917
|
-
|
|
23918
|
-
|
|
23919
|
-
|
|
23920
|
-
|
|
23921
|
-
|
|
23922
|
-
|
|
23923
|
-
}
|
|
23924
|
-
})()\`;
|
|
23925
|
-
};
|
|
23978
|
+
module.exports.readChat = () => load('read_chat.js');
|
|
23979
|
+
module.exports.sendMessage = () => load('send_message.js');
|
|
23980
|
+
module.exports.listSessions = () => load('list_sessions.js');
|
|
23981
|
+
module.exports.newSession = () => load('new_session.js');
|
|
23982
|
+
module.exports.focusEditor = () => load('focus_editor.js');
|
|
23983
|
+
module.exports.openPanel = () => load('open_panel.js');
|
|
23984
|
+
module.exports.listModels = () => load('list_models.js');
|
|
23985
|
+
module.exports.listModes = () => load('list_modes.js');
|
|
23926
23986
|
|
|
23927
|
-
|
|
23928
|
-
return \`(() => {
|
|
23929
|
-
try {
|
|
23930
|
-
// TODO: Click "New Chat" button
|
|
23931
|
-
// const btn = document.querySelector('[aria-label*="New Chat"]');
|
|
23932
|
-
// if (btn) { btn.click(); return JSON.stringify({ created: true }); }
|
|
23933
|
-
return JSON.stringify({ created: false, error: 'New Chat button not found' });
|
|
23934
|
-
} catch(e) {
|
|
23935
|
-
return JSON.stringify({ created: false, error: e.message });
|
|
23936
|
-
}
|
|
23937
|
-
})()\`;
|
|
23938
|
-
};
|
|
23987
|
+
// \u2500\u2500\u2500 With params (function expression) \u2500\u2500\u2500
|
|
23939
23988
|
|
|
23940
|
-
module.exports.
|
|
23941
|
-
|
|
23942
|
-
|
|
23943
|
-
|
|
23944
|
-
return 'not_found';
|
|
23945
|
-
} catch(e) { return 'error'; }
|
|
23946
|
-
})()\`;
|
|
23989
|
+
module.exports.switchSession = (params) => {
|
|
23990
|
+
const index = typeof params === 'number' ? params : params?.index ?? 0;
|
|
23991
|
+
const title = typeof params === 'string' ? params : params?.title || null;
|
|
23992
|
+
return withParams('switch_session.js', { index, title });
|
|
23947
23993
|
};
|
|
23948
23994
|
|
|
23949
|
-
module.exports.
|
|
23950
|
-
|
|
23951
|
-
|
|
23952
|
-
|
|
23953
|
-
|
|
23954
|
-
return 'not_found';
|
|
23955
|
-
} catch(e) { return 'error'; }
|
|
23956
|
-
})()\`;
|
|
23995
|
+
module.exports.resolveAction = (params) => {
|
|
23996
|
+
const action = typeof params === 'string' ? params : params?.action || 'approve';
|
|
23997
|
+
const buttonText = params?.button || params?.buttonText
|
|
23998
|
+
|| (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : action);
|
|
23999
|
+
return withParams('resolve_action.js', { buttonText });
|
|
23957
24000
|
};
|
|
23958
24001
|
|
|
23959
|
-
module.exports.
|
|
23960
|
-
|
|
23961
|
-
|
|
23962
|
-
|| (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : action);
|
|
23963
|
-
return \`(() => {
|
|
23964
|
-
try {
|
|
23965
|
-
const btns = [...document.querySelectorAll('button, [role="button"]')].filter(b => b.offsetWidth > 0);
|
|
23966
|
-
const target = btns.find(b => (b.textContent||'').trim().toLowerCase().includes(\${JSON.stringify((buttonText||'').toLowerCase())}));
|
|
23967
|
-
if (target) { target.click(); return JSON.stringify({ resolved: true, clicked: target.textContent.trim() }); }
|
|
23968
|
-
return JSON.stringify({ resolved: false, available: btns.map(b => b.textContent.trim()).filter(Boolean).slice(0, 10) });
|
|
23969
|
-
} catch(e) { return JSON.stringify({ resolved: false, error: e.message }); }
|
|
23970
|
-
})()\`;
|
|
24002
|
+
module.exports.setModel = (params) => {
|
|
24003
|
+
const model = typeof params === 'string' ? params : params?.model;
|
|
24004
|
+
return withParams('set_model.js', { model });
|
|
23971
24005
|
};
|
|
23972
24006
|
|
|
23973
|
-
module.exports.
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
const toasts = [...document.querySelectorAll('.notifications-toasts .notification-toast, .notification-list-item')];
|
|
23977
|
-
return JSON.stringify(toasts.filter(t => t.offsetWidth > 0).map((t, i) => ({
|
|
23978
|
-
index: i,
|
|
23979
|
-
message: t.querySelector('.notification-list-item-message')?.textContent?.trim() || t.textContent?.trim().substring(0, 200),
|
|
23980
|
-
severity: t.querySelector('.codicon-error') ? 'error' : t.querySelector('.codicon-warning') ? 'warning' : 'info',
|
|
23981
|
-
buttons: [...t.querySelectorAll('.notification-list-item-buttons-container button')].map(b => b.textContent?.trim()).filter(Boolean),
|
|
23982
|
-
})));
|
|
23983
|
-
} catch(e) { return JSON.stringify([]); }
|
|
23984
|
-
})()\`;
|
|
24007
|
+
module.exports.setMode = (params) => {
|
|
24008
|
+
const mode = typeof params === 'string' ? params : params?.mode;
|
|
24009
|
+
return withParams('set_mode.js', { mode });
|
|
23985
24010
|
};
|
|
24011
|
+
`;
|
|
24012
|
+
files[`${scriptDir}/read_chat.js`] = `/**
|
|
24013
|
+
* ${name} \u2014 read_chat
|
|
24014
|
+
*
|
|
24015
|
+
* Extract chat messages, status, and approval state from DOM.
|
|
24016
|
+
*
|
|
24017
|
+
* TODO: Identify via CDP/DevConsole:
|
|
24018
|
+
* 1. Chat container selector
|
|
24019
|
+
* 2. User message selector + class pattern
|
|
24020
|
+
* 3. Assistant message selector + class pattern
|
|
24021
|
+
* 4. Status detection (generating/idle/waiting_approval)
|
|
24022
|
+
* 5. Approval dialog detection (buttons, modal)
|
|
24023
|
+
* 6. Input field selector
|
|
24024
|
+
*
|
|
24025
|
+
* \u2192 { id, status, title, messages[], inputContent, activeModal }
|
|
24026
|
+
*/
|
|
24027
|
+
(() => {
|
|
24028
|
+
try {
|
|
24029
|
+
const messages = [];
|
|
24030
|
+
let status = 'idle';
|
|
24031
|
+
let activeModal = null;
|
|
23986
24032
|
|
|
23987
|
-
|
|
23988
|
-
|
|
23989
|
-
|
|
23990
|
-
|
|
23991
|
-
|
|
23992
|
-
|
|
23993
|
-
|
|
23994
|
-
|
|
23995
|
-
|
|
23996
|
-
|
|
23997
|
-
|
|
23998
|
-
|
|
23999
|
-
|
|
24000
|
-
|
|
24001
|
-
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
|
|
24033
|
+
// TODO: Query chat container and extract messages
|
|
24034
|
+
// Example:
|
|
24035
|
+
// document.querySelectorAll('.chat-message').forEach(el => {
|
|
24036
|
+
// const role = el.classList.contains('user') ? 'user' : 'assistant';
|
|
24037
|
+
// messages.push({ role, content: el.innerText.trim(), index: messages.length });
|
|
24038
|
+
// });
|
|
24039
|
+
|
|
24040
|
+
// TODO: Detect generating state
|
|
24041
|
+
// TODO: Detect approval dialogs -> status = 'waiting_approval'
|
|
24042
|
+
|
|
24043
|
+
const inputEl = document.querySelector('[contenteditable="true"]');
|
|
24044
|
+
const inputContent = inputEl?.innerText?.trim() || '';
|
|
24045
|
+
|
|
24046
|
+
return JSON.stringify({
|
|
24047
|
+
id: 'active',
|
|
24048
|
+
status,
|
|
24049
|
+
title: document.title,
|
|
24050
|
+
messages,
|
|
24051
|
+
inputContent,
|
|
24052
|
+
activeModal,
|
|
24053
|
+
});
|
|
24054
|
+
} catch(e) {
|
|
24055
|
+
return JSON.stringify({ id: '', status: 'error', messages: [], error: e.message });
|
|
24056
|
+
}
|
|
24057
|
+
})()
|
|
24058
|
+
`;
|
|
24059
|
+
files[`${scriptDir}/send_message.js`] = `/**
|
|
24060
|
+
* ${name} \u2014 send_message
|
|
24061
|
+
*
|
|
24062
|
+
* For cdp-type-and-send IDEs: returns selector for daemon to type into.
|
|
24063
|
+
* \u2192 { sent: false, needsTypeAndSend: true, selector }
|
|
24064
|
+
*/
|
|
24065
|
+
(() => {
|
|
24066
|
+
try {
|
|
24067
|
+
const input = document.querySelector('${meta3.inputSelector || '[contenteditable="true"]'}');
|
|
24068
|
+
if (!input) return JSON.stringify({ sent: false, error: 'Input not found' });
|
|
24069
|
+
return JSON.stringify({
|
|
24070
|
+
sent: false,
|
|
24071
|
+
needsTypeAndSend: true,
|
|
24072
|
+
selector: '${meta3.inputSelector || '[contenteditable="true"]'}',
|
|
24073
|
+
});
|
|
24074
|
+
} catch(e) {
|
|
24075
|
+
return JSON.stringify({ sent: false, error: e.message });
|
|
24076
|
+
}
|
|
24077
|
+
})()
|
|
24078
|
+
`;
|
|
24079
|
+
files[`${scriptDir}/list_sessions.js`] = `/**
|
|
24080
|
+
* ${name} \u2014 list_sessions
|
|
24081
|
+
*
|
|
24082
|
+
* TODO: Query session/chat list from sidebar.
|
|
24083
|
+
* \u2192 { sessions: [{ id, title, active, index }] }
|
|
24084
|
+
*/
|
|
24085
|
+
(() => {
|
|
24086
|
+
try {
|
|
24087
|
+
const sessions = [];
|
|
24088
|
+
// TODO: Find session list container and parse items
|
|
24089
|
+
return JSON.stringify({ sessions });
|
|
24090
|
+
} catch(e) {
|
|
24091
|
+
return JSON.stringify({ sessions: [], error: e.message });
|
|
24092
|
+
}
|
|
24093
|
+
})()
|
|
24094
|
+
`;
|
|
24095
|
+
files[`${scriptDir}/switch_session.js`] = `/**
|
|
24096
|
+
* ${name} \u2014 switch_session
|
|
24097
|
+
*
|
|
24098
|
+
* params.index: number, params.title: string|null
|
|
24099
|
+
* TODO: Click on session in sidebar by title or index.
|
|
24100
|
+
* \u2192 { switched: true/false }
|
|
24101
|
+
*/
|
|
24102
|
+
(params) => {
|
|
24103
|
+
try {
|
|
24104
|
+
// TODO: Find session list and click target
|
|
24105
|
+
return JSON.stringify({ switched: false, error: 'Not implemented' });
|
|
24106
|
+
} catch(e) {
|
|
24107
|
+
return JSON.stringify({ switched: false, error: e.message });
|
|
24108
|
+
}
|
|
24109
|
+
}
|
|
24110
|
+
`;
|
|
24111
|
+
files[`${scriptDir}/new_session.js`] = `/**
|
|
24112
|
+
* ${name} \u2014 new_session
|
|
24113
|
+
*
|
|
24114
|
+
* TODO: Click "New Chat" button.
|
|
24115
|
+
* \u2192 { created: true/false }
|
|
24116
|
+
*/
|
|
24117
|
+
(() => {
|
|
24118
|
+
try {
|
|
24119
|
+
const btn = document.querySelector('[aria-label*="New Chat"], [aria-label*="New Composer"]');
|
|
24120
|
+
if (btn) { btn.click(); return JSON.stringify({ created: true }); }
|
|
24121
|
+
return JSON.stringify({ created: false, error: 'New Chat button not found' });
|
|
24122
|
+
} catch(e) {
|
|
24123
|
+
return JSON.stringify({ created: false, error: e.message });
|
|
24124
|
+
}
|
|
24125
|
+
})()
|
|
24126
|
+
`;
|
|
24127
|
+
files[`${scriptDir}/focus_editor.js`] = `/**
|
|
24128
|
+
* ${name} \u2014 focus_editor
|
|
24129
|
+
*/
|
|
24130
|
+
(() => {
|
|
24131
|
+
try {
|
|
24132
|
+
const input = document.querySelector('${meta3.inputSelector || '[contenteditable="true"]'}');
|
|
24133
|
+
if (input) { input.focus(); return 'focused'; }
|
|
24134
|
+
return 'not_found';
|
|
24135
|
+
} catch(e) { return 'error'; }
|
|
24136
|
+
})()
|
|
24137
|
+
`;
|
|
24138
|
+
files[`${scriptDir}/open_panel.js`] = `/**
|
|
24139
|
+
* ${name} \u2014 open_panel
|
|
24140
|
+
*
|
|
24141
|
+
* TODO: Open chat/AI panel if not visible.
|
|
24142
|
+
*/
|
|
24143
|
+
(() => {
|
|
24144
|
+
try {
|
|
24145
|
+
// TODO: Check if panel visible, if not find toggle button
|
|
24146
|
+
return 'not_found';
|
|
24147
|
+
} catch(e) { return 'error'; }
|
|
24148
|
+
})()
|
|
24149
|
+
`;
|
|
24150
|
+
files[`${scriptDir}/resolve_action.js`] = `/**
|
|
24151
|
+
* ${name} \u2014 resolve_action
|
|
24152
|
+
*
|
|
24153
|
+
* params.buttonText: string \u2014 button text to find and click.
|
|
24154
|
+
* \u2192 { resolved: true/false, clicked? }
|
|
24155
|
+
*/
|
|
24156
|
+
(params) => {
|
|
24157
|
+
try {
|
|
24158
|
+
const btns = [...document.querySelectorAll('button, [role="button"]')].filter(b => b.offsetWidth > 0);
|
|
24159
|
+
const searchText = (params.buttonText || '').toLowerCase();
|
|
24160
|
+
const target = btns.find(b => (b.textContent||'').trim().toLowerCase().includes(searchText));
|
|
24161
|
+
if (target) {
|
|
24162
|
+
target.click();
|
|
24163
|
+
return JSON.stringify({ resolved: true, clicked: target.textContent.trim() });
|
|
24164
|
+
}
|
|
24165
|
+
return JSON.stringify({ resolved: false, available: btns.map(b => b.textContent.trim()).filter(Boolean).slice(0, 10) });
|
|
24166
|
+
} catch(e) { return JSON.stringify({ resolved: false, error: e.message }); }
|
|
24167
|
+
}
|
|
24168
|
+
`;
|
|
24169
|
+
files[`${scriptDir}/list_models.js`] = `/**
|
|
24170
|
+
* ${name} \u2014 list_models
|
|
24171
|
+
*
|
|
24172
|
+
* TODO: Open model dropdown and extract model list.
|
|
24173
|
+
* \u2192 { models[], current }
|
|
24174
|
+
*/
|
|
24175
|
+
(() => {
|
|
24176
|
+
try {
|
|
24177
|
+
return JSON.stringify({ models: [], current: '' });
|
|
24178
|
+
} catch(e) { return JSON.stringify({ models: [], current: '', error: e.message }); }
|
|
24179
|
+
})()
|
|
24180
|
+
`;
|
|
24181
|
+
files[`${scriptDir}/list_modes.js`] = `/**
|
|
24182
|
+
* ${name} \u2014 list_modes
|
|
24183
|
+
*
|
|
24184
|
+
* TODO: Open mode dropdown and extract mode list.
|
|
24185
|
+
* \u2192 { modes[], current }
|
|
24186
|
+
*/
|
|
24187
|
+
(() => {
|
|
24188
|
+
try {
|
|
24189
|
+
return JSON.stringify({ modes: [], current: '' });
|
|
24190
|
+
} catch(e) { return JSON.stringify({ modes: [], current: '', error: e.message }); }
|
|
24191
|
+
})()
|
|
24192
|
+
`;
|
|
24193
|
+
files[`${scriptDir}/set_model.js`] = `/**
|
|
24194
|
+
* ${name} \u2014 set_model
|
|
24195
|
+
*
|
|
24196
|
+
* params.model: string
|
|
24197
|
+
* TODO: Open model dropdown and select target model.
|
|
24198
|
+
* \u2192 { success: true/false }
|
|
24199
|
+
*/
|
|
24200
|
+
async (params) => {
|
|
24201
|
+
try {
|
|
24202
|
+
return JSON.stringify({ success: false, error: 'Not implemented' });
|
|
24203
|
+
} catch(e) { return JSON.stringify({ success: false, error: e.message }); }
|
|
24204
|
+
}
|
|
24205
|
+
`;
|
|
24206
|
+
files[`${scriptDir}/set_mode.js`] = `/**
|
|
24207
|
+
* ${name} \u2014 set_mode
|
|
24208
|
+
*
|
|
24209
|
+
* params.mode: string
|
|
24210
|
+
* TODO: Open mode dropdown and select target mode.
|
|
24211
|
+
* \u2192 { success: true/false }
|
|
24212
|
+
*/
|
|
24213
|
+
async (params) => {
|
|
24214
|
+
try {
|
|
24215
|
+
return JSON.stringify({ success: false, error: 'Not implemented' });
|
|
24216
|
+
} catch(e) { return JSON.stringify({ success: false, error: e.message }); }
|
|
24217
|
+
}
|
|
24005
24218
|
`;
|
|
24006
24219
|
return {
|
|
24007
24220
|
"provider.json": JSON.stringify(meta3, null, 2) + "\n",
|
|
24008
|
-
|
|
24221
|
+
files
|
|
24009
24222
|
};
|
|
24010
24223
|
}
|
|
24011
24224
|
var DEV_SERVER_PORT = 19280;
|
|
@@ -24099,6 +24312,15 @@ module.exports.dismissNotification = function dismissNotification(params) {
|
|
|
24099
24312
|
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/spawn-test$/) && req.method === "POST") {
|
|
24100
24313
|
const type = pathname.match(/^\/api\/providers\/([^/]+)\/spawn-test$/)[1];
|
|
24101
24314
|
await this.handleSpawnTest(type, req, res);
|
|
24315
|
+
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/validate$/) && req.method === "POST") {
|
|
24316
|
+
const type = pathname.match(/^\/api\/providers\/([^/]+)\/validate$/)[1];
|
|
24317
|
+
await this.handleValidate(type, req, res);
|
|
24318
|
+
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/acp-chat$/) && req.method === "POST") {
|
|
24319
|
+
const type = pathname.match(/^\/api\/providers\/([^/]+)\/acp-chat$/)[1];
|
|
24320
|
+
await this.handleAcpChat(type, req, res);
|
|
24321
|
+
} else if (pathname.match(/^\/api\/providers\/([^/]+)\/script-hints$/) && req.method === "GET") {
|
|
24322
|
+
const type = pathname.match(/^\/api\/providers\/([^/]+)\/script-hints$/)[1];
|
|
24323
|
+
await this.handleScriptHints(type, req, res);
|
|
24102
24324
|
} else if (pathname.startsWith("/assets/") || pathname === "/favicon.ico") {
|
|
24103
24325
|
await this.serveStaticAsset(pathname, res);
|
|
24104
24326
|
} else if (pathname === "/" || pathname === "/console" || !pathname.startsWith("/api")) {
|
|
@@ -24179,7 +24401,7 @@ module.exports.dismissNotification = function dismissNotification(params) {
|
|
|
24179
24401
|
this.json(res, 200, { providers, count: providers.length });
|
|
24180
24402
|
}
|
|
24181
24403
|
async handleProviderConfig(type, _req, res) {
|
|
24182
|
-
const provider2 = this.providerLoader.
|
|
24404
|
+
const provider2 = this.providerLoader.resolve(type);
|
|
24183
24405
|
if (!provider2) {
|
|
24184
24406
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
24185
24407
|
return;
|
|
@@ -24192,7 +24414,7 @@ module.exports.dismissNotification = function dismissNotification(params) {
|
|
|
24192
24414
|
this.json(res, 200, { type, config: config2 });
|
|
24193
24415
|
}
|
|
24194
24416
|
async handleSpawnTest(type, req, res) {
|
|
24195
|
-
const provider2 = this.providerLoader.
|
|
24417
|
+
const provider2 = this.providerLoader.resolve(type);
|
|
24196
24418
|
if (!provider2) {
|
|
24197
24419
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
24198
24420
|
return;
|
|
@@ -24739,6 +24961,208 @@ module.exports.dismissNotification = function dismissNotification(params) {
|
|
|
24739
24961
|
this.json(res, 500, { error: `Save failed: ${e.message}` });
|
|
24740
24962
|
}
|
|
24741
24963
|
}
|
|
24964
|
+
async handleScriptHints(type, _req, res) {
|
|
24965
|
+
const dir = this.findProviderDir(type);
|
|
24966
|
+
if (!dir) {
|
|
24967
|
+
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
24968
|
+
return;
|
|
24969
|
+
}
|
|
24970
|
+
let scriptsPath = "";
|
|
24971
|
+
const directScripts = path9.join(dir, "scripts.js");
|
|
24972
|
+
if (fs7.existsSync(directScripts)) {
|
|
24973
|
+
scriptsPath = directScripts;
|
|
24974
|
+
} else {
|
|
24975
|
+
const scriptsDir = path9.join(dir, "scripts");
|
|
24976
|
+
if (fs7.existsSync(scriptsDir)) {
|
|
24977
|
+
const versions = fs7.readdirSync(scriptsDir).filter((d) => {
|
|
24978
|
+
return fs7.statSync(path9.join(scriptsDir, d)).isDirectory();
|
|
24979
|
+
}).sort().reverse();
|
|
24980
|
+
for (const ver of versions) {
|
|
24981
|
+
const p = path9.join(scriptsDir, ver, "scripts.js");
|
|
24982
|
+
if (fs7.existsSync(p)) {
|
|
24983
|
+
scriptsPath = p;
|
|
24984
|
+
break;
|
|
24985
|
+
}
|
|
24986
|
+
}
|
|
24987
|
+
}
|
|
24988
|
+
}
|
|
24989
|
+
if (!scriptsPath) {
|
|
24990
|
+
this.json(res, 200, { hints: {} });
|
|
24991
|
+
return;
|
|
24992
|
+
}
|
|
24993
|
+
try {
|
|
24994
|
+
const source = fs7.readFileSync(scriptsPath, "utf-8");
|
|
24995
|
+
const hints = {};
|
|
24996
|
+
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
24997
|
+
let match;
|
|
24998
|
+
while ((match = funcRegex.exec(source)) !== null) {
|
|
24999
|
+
const name = match[1];
|
|
25000
|
+
const startIdx = match.index;
|
|
25001
|
+
const nextFunc = source.indexOf("module.exports.", startIdx + 1);
|
|
25002
|
+
const funcBody = source.substring(startIdx, nextFunc > 0 ? nextFunc : source.length);
|
|
25003
|
+
const paramFields = {};
|
|
25004
|
+
const dotRegex = /params\?\.([a-zA-Z_]+)|params\.([a-zA-Z_]+)/g;
|
|
25005
|
+
let dm;
|
|
25006
|
+
while ((dm = dotRegex.exec(funcBody)) !== null) {
|
|
25007
|
+
const field = dm[1] || dm[2];
|
|
25008
|
+
if (field === "length") continue;
|
|
25009
|
+
if (!(field in paramFields)) {
|
|
25010
|
+
if (/index|count|port|timeout/i.test(field)) paramFields[field] = 0;
|
|
25011
|
+
else if (/action|text|title|message|model|mode|button|name|filter/i.test(field)) paramFields[field] = "";
|
|
25012
|
+
else paramFields[field] = "";
|
|
25013
|
+
}
|
|
25014
|
+
}
|
|
25015
|
+
const typeofRegex = /typeof params === 'string' \? params : params\?\.([a-zA-Z_]+)/g;
|
|
25016
|
+
let tm;
|
|
25017
|
+
while ((tm = typeofRegex.exec(funcBody)) !== null) {
|
|
25018
|
+
const field = tm[1];
|
|
25019
|
+
if (!(field in paramFields)) paramFields[field] = "";
|
|
25020
|
+
}
|
|
25021
|
+
const numRegex = /typeof params === 'number' \? params : params\?\.([a-zA-Z_]+)/g;
|
|
25022
|
+
let nm;
|
|
25023
|
+
while ((nm = numRegex.exec(funcBody)) !== null) {
|
|
25024
|
+
const field = nm[1];
|
|
25025
|
+
if (!(field in paramFields)) paramFields[field] = 0;
|
|
25026
|
+
}
|
|
25027
|
+
const descriptions = {
|
|
25028
|
+
readChat: "No params required",
|
|
25029
|
+
sendMessage: "Text to send to the chat",
|
|
25030
|
+
listSessions: "No params required",
|
|
25031
|
+
switchSession: "Switch by index or title",
|
|
25032
|
+
newSession: "No params required",
|
|
25033
|
+
focusEditor: "No params required",
|
|
25034
|
+
openPanel: "No params required",
|
|
25035
|
+
resolveAction: "Approve/reject action buttons",
|
|
25036
|
+
listNotifications: "Optional message filter",
|
|
25037
|
+
dismissNotification: "Dismiss by index, message, or button",
|
|
25038
|
+
listModels: "No params required",
|
|
25039
|
+
setModel: "Model name to select",
|
|
25040
|
+
listModes: "No params required",
|
|
25041
|
+
setMode: "Mode name to select"
|
|
25042
|
+
};
|
|
25043
|
+
hints[name] = {
|
|
25044
|
+
template: Object.keys(paramFields).length > 0 ? paramFields : {},
|
|
25045
|
+
description: descriptions[name] || (Object.keys(paramFields).length > 0 ? "Params: " + Object.keys(paramFields).join(", ") : "No params")
|
|
25046
|
+
};
|
|
25047
|
+
}
|
|
25048
|
+
this.json(res, 200, { hints });
|
|
25049
|
+
} catch (e) {
|
|
25050
|
+
this.json(res, 500, { error: e.message });
|
|
25051
|
+
}
|
|
25052
|
+
}
|
|
25053
|
+
// ─── Validate provider.json ───
|
|
25054
|
+
async handleValidate(type, req, res) {
|
|
25055
|
+
const body = await this.readBody(req);
|
|
25056
|
+
const { content } = body;
|
|
25057
|
+
const errors = [];
|
|
25058
|
+
const warnings = [];
|
|
25059
|
+
try {
|
|
25060
|
+
const config2 = typeof content === "string" ? JSON.parse(content) : content;
|
|
25061
|
+
if (!config2.type) errors.push("Missing required field: type");
|
|
25062
|
+
if (!config2.name) errors.push("Missing required field: name");
|
|
25063
|
+
if (!config2.category) errors.push("Missing required field: category");
|
|
25064
|
+
else if (!["ide", "extension", "cli", "acp"].includes(config2.category)) errors.push(`Invalid category: ${config2.category}`);
|
|
25065
|
+
if (config2.category === "ide" || config2.category === "extension") {
|
|
25066
|
+
if (!config2.cdpPorts || !Array.isArray(config2.cdpPorts) || config2.cdpPorts.length === 0)
|
|
25067
|
+
warnings.push("IDE/Extension providers should have cdpPorts");
|
|
25068
|
+
if (config2.category === "extension" && !config2.extensionId)
|
|
25069
|
+
warnings.push("Extension providers should have extensionId");
|
|
25070
|
+
}
|
|
25071
|
+
if (config2.category === "acp" || config2.category === "cli") {
|
|
25072
|
+
if (!config2.spawn) errors.push("ACP/CLI providers must have spawn config");
|
|
25073
|
+
else {
|
|
25074
|
+
if (!config2.spawn.command) errors.push("spawn.command is required");
|
|
25075
|
+
}
|
|
25076
|
+
}
|
|
25077
|
+
if (config2.settings) {
|
|
25078
|
+
for (const [key, val] of Object.entries(config2.settings)) {
|
|
25079
|
+
const s = val;
|
|
25080
|
+
if (!s.type) errors.push(`settings.${key}: missing type`);
|
|
25081
|
+
else if (!["boolean", "number", "string", "select"].includes(s.type))
|
|
25082
|
+
errors.push(`settings.${key}: invalid type '${s.type}'`);
|
|
25083
|
+
if (s.default === void 0) warnings.push(`settings.${key}: no default value`);
|
|
25084
|
+
if (s.type === "number" && s.min !== void 0 && s.max !== void 0 && s.min > s.max)
|
|
25085
|
+
errors.push(`settings.${key}: min (${s.min}) > max (${s.max})`);
|
|
25086
|
+
if (s.type === "select" && (!s.options || !Array.isArray(s.options) || s.options.length === 0))
|
|
25087
|
+
errors.push(`settings.${key}: select type requires options[]`);
|
|
25088
|
+
}
|
|
25089
|
+
}
|
|
25090
|
+
if (config2.cdpPorts && Array.isArray(config2.cdpPorts)) {
|
|
25091
|
+
const allProviders = this.providerLoader.getAll();
|
|
25092
|
+
for (const port of config2.cdpPorts) {
|
|
25093
|
+
const conflict = allProviders.find((p) => p.type !== type && p.cdpPorts?.includes(port));
|
|
25094
|
+
if (conflict) warnings.push(`CDP port ${port} conflicts with provider '${conflict.type}'`);
|
|
25095
|
+
}
|
|
25096
|
+
}
|
|
25097
|
+
this.json(res, 200, { valid: errors.length === 0, errors, warnings });
|
|
25098
|
+
} catch (e) {
|
|
25099
|
+
this.json(res, 200, { valid: false, errors: [`Invalid JSON: ${e.message}`], warnings: [] });
|
|
25100
|
+
}
|
|
25101
|
+
}
|
|
25102
|
+
// ─── ACP Chat Test ───
|
|
25103
|
+
async handleAcpChat(type, req, res) {
|
|
25104
|
+
const body = await this.readBody(req);
|
|
25105
|
+
const { message, timeout = 3e4 } = body;
|
|
25106
|
+
if (!message) {
|
|
25107
|
+
this.json(res, 400, { error: "message required" });
|
|
25108
|
+
return;
|
|
25109
|
+
}
|
|
25110
|
+
const provider2 = this.providerLoader.get(type);
|
|
25111
|
+
if (!provider2) {
|
|
25112
|
+
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
25113
|
+
return;
|
|
25114
|
+
}
|
|
25115
|
+
const spawn3 = provider2.spawn;
|
|
25116
|
+
if (!spawn3) {
|
|
25117
|
+
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
25118
|
+
return;
|
|
25119
|
+
}
|
|
25120
|
+
const { spawn: spawnFn } = await import("child_process");
|
|
25121
|
+
const start = Date.now();
|
|
25122
|
+
try {
|
|
25123
|
+
const args = [...spawn3.args || [], message];
|
|
25124
|
+
const child = spawnFn(spawn3.command, args, {
|
|
25125
|
+
shell: spawn3.shell ?? false,
|
|
25126
|
+
timeout,
|
|
25127
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
25128
|
+
env: { ...process.env, ...spawn3.env || {} }
|
|
25129
|
+
});
|
|
25130
|
+
let stdout = "";
|
|
25131
|
+
let stderr = "";
|
|
25132
|
+
child.stdout?.on("data", (d) => {
|
|
25133
|
+
stdout += d.toString();
|
|
25134
|
+
});
|
|
25135
|
+
child.stderr?.on("data", (d) => {
|
|
25136
|
+
stderr += d.toString();
|
|
25137
|
+
});
|
|
25138
|
+
await new Promise((resolve5) => {
|
|
25139
|
+
const timer = setTimeout(() => {
|
|
25140
|
+
child.kill();
|
|
25141
|
+
resolve5();
|
|
25142
|
+
}, timeout);
|
|
25143
|
+
child.on("exit", () => {
|
|
25144
|
+
clearTimeout(timer);
|
|
25145
|
+
resolve5();
|
|
25146
|
+
});
|
|
25147
|
+
});
|
|
25148
|
+
const elapsed = Date.now() - start;
|
|
25149
|
+
this.json(res, 200, {
|
|
25150
|
+
success: true,
|
|
25151
|
+
message,
|
|
25152
|
+
response: stdout.trim(),
|
|
25153
|
+
stderr: stderr.trim(),
|
|
25154
|
+
exitCode: child.exitCode,
|
|
25155
|
+
elapsed
|
|
25156
|
+
});
|
|
25157
|
+
} catch (e) {
|
|
25158
|
+
this.json(res, 200, {
|
|
25159
|
+
success: false,
|
|
25160
|
+
message,
|
|
25161
|
+
error: e.message,
|
|
25162
|
+
elapsed: Date.now() - start
|
|
25163
|
+
});
|
|
25164
|
+
}
|
|
25165
|
+
}
|
|
24742
25166
|
async handleCdpTargets(_req, res) {
|
|
24743
25167
|
const targets = [];
|
|
24744
25168
|
for (const [ide, cdp2] of this.cdpManagers.entries()) {
|
|
@@ -24759,7 +25183,8 @@ module.exports.dismissNotification = function dismissNotification(params) {
|
|
|
24759
25183
|
processName,
|
|
24760
25184
|
installPath,
|
|
24761
25185
|
binary,
|
|
24762
|
-
extensionId
|
|
25186
|
+
extensionId,
|
|
25187
|
+
version: version2
|
|
24763
25188
|
} = body;
|
|
24764
25189
|
if (!type || !name) {
|
|
24765
25190
|
this.json(res, 400, { error: "type and name required" });
|
|
@@ -24778,15 +25203,19 @@ module.exports.dismissNotification = function dismissNotification(params) {
|
|
|
24778
25203
|
return;
|
|
24779
25204
|
}
|
|
24780
25205
|
try {
|
|
24781
|
-
const
|
|
25206
|
+
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 });
|
|
24782
25207
|
fs7.mkdirSync(targetDir, { recursive: true });
|
|
24783
|
-
fs7.writeFileSync(jsonPath,
|
|
25208
|
+
fs7.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
24784
25209
|
const createdFiles = ["provider.json"];
|
|
24785
|
-
if (files
|
|
24786
|
-
|
|
24787
|
-
|
|
25210
|
+
if (result.files) {
|
|
25211
|
+
for (const [relPath, content] of Object.entries(result.files)) {
|
|
25212
|
+
const fullPath = path9.join(targetDir, relPath);
|
|
25213
|
+
fs7.mkdirSync(path9.dirname(fullPath), { recursive: true });
|
|
25214
|
+
fs7.writeFileSync(fullPath, content, "utf-8");
|
|
25215
|
+
createdFiles.push(relPath);
|
|
25216
|
+
}
|
|
24788
25217
|
}
|
|
24789
|
-
this.log(`Scaffolded provider: ${targetDir} (${createdFiles.
|
|
25218
|
+
this.log(`Scaffolded provider: ${targetDir} (${createdFiles.length} files)`);
|
|
24790
25219
|
this.json(res, 201, { created: true, path: targetDir, files: createdFiles, type, name, category });
|
|
24791
25220
|
} catch (e) {
|
|
24792
25221
|
this.json(res, 500, { error: e.message });
|
|
@@ -25980,7 +26409,7 @@ var init_daemon_p2p = __esm({
|
|
|
25980
26409
|
/** Fetch TURN credentials */
|
|
25981
26410
|
async fetchTurnCredentials() {
|
|
25982
26411
|
try {
|
|
25983
|
-
const serverUrl = "https://api.adhf.dev";
|
|
26412
|
+
const serverUrl = process.env.ADHDEV_SERVER_URL || "https://api.adhf.dev";
|
|
25984
26413
|
const configPath = path.join(os.homedir(), ".adhdev", "config.json");
|
|
25985
26414
|
let token = "";
|
|
25986
26415
|
try {
|
|
@@ -26612,7 +27041,7 @@ function stopDaemon() {
|
|
|
26612
27041
|
return false;
|
|
26613
27042
|
}
|
|
26614
27043
|
}
|
|
26615
|
-
var import_daemon_core3, os2, fs2, path2, crypto2, import_chalk, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
27044
|
+
var import_daemon_core3, os2, fs2, path2, crypto2, import_chalk, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
26616
27045
|
var init_adhdev_daemon = __esm({
|
|
26617
27046
|
"src/adhdev-daemon.ts"() {
|
|
26618
27047
|
"use strict";
|
|
@@ -26624,6 +27053,24 @@ var init_adhdev_daemon = __esm({
|
|
|
26624
27053
|
path2 = __toESM(require("path"));
|
|
26625
27054
|
crypto2 = __toESM(require("crypto"));
|
|
26626
27055
|
import_chalk = __toESM(require("chalk"));
|
|
27056
|
+
pkgVersion = "unknown";
|
|
27057
|
+
try {
|
|
27058
|
+
const possiblePaths = [
|
|
27059
|
+
path2.join(__dirname, "..", "package.json"),
|
|
27060
|
+
path2.join(__dirname, "package.json")
|
|
27061
|
+
];
|
|
27062
|
+
for (const p of possiblePaths) {
|
|
27063
|
+
try {
|
|
27064
|
+
const data = JSON.parse(fs2.readFileSync(p, "utf-8"));
|
|
27065
|
+
if (data.version) {
|
|
27066
|
+
pkgVersion = data.version;
|
|
27067
|
+
break;
|
|
27068
|
+
}
|
|
27069
|
+
} catch {
|
|
27070
|
+
}
|
|
27071
|
+
}
|
|
27072
|
+
} catch {
|
|
27073
|
+
}
|
|
26627
27074
|
DANGEROUS_PATTERNS = [
|
|
26628
27075
|
/\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/i,
|
|
26629
27076
|
/\bsudo\b/i,
|
|
@@ -26658,7 +27105,6 @@ var init_adhdev_daemon = __esm({
|
|
|
26658
27105
|
constructor() {
|
|
26659
27106
|
this.localPort = 19222;
|
|
26660
27107
|
this.providerLoader = new import_daemon_core3.ProviderLoader({
|
|
26661
|
-
builtinDir: path2.join(__dirname, "..", "providers", "_builtin"),
|
|
26662
27108
|
logFn: import_daemon_core3.LOG.forComponent("Provider").asLogFn()
|
|
26663
27109
|
});
|
|
26664
27110
|
this.providerLoader.loadAll();
|
|
@@ -26734,7 +27180,7 @@ var init_adhdev_daemon = __esm({
|
|
|
26734
27180
|
token: config2.connectionToken,
|
|
26735
27181
|
cliInfo: {
|
|
26736
27182
|
type: "adhdev-daemon",
|
|
26737
|
-
version:
|
|
27183
|
+
version: pkgVersion,
|
|
26738
27184
|
platform: os2.platform(),
|
|
26739
27185
|
instanceId
|
|
26740
27186
|
}
|
|
@@ -27080,29 +27526,6 @@ var init_adhdev_daemon = __esm({
|
|
|
27080
27526
|
const history = getRecentCommands(count);
|
|
27081
27527
|
return { success: true, history };
|
|
27082
27528
|
}
|
|
27083
|
-
// get_acp_auth / set_acp_auth removed — ADHDev does not manage API keys.
|
|
27084
|
-
// Each CLI/ACP tool handles its own auth. ADHDev focuses on install detection + error reporting.
|
|
27085
|
-
case "get_daemon_logs": {
|
|
27086
|
-
const count = parseInt(data.lines) || 100;
|
|
27087
|
-
const minLevel = data.minLevel || "info";
|
|
27088
|
-
try {
|
|
27089
|
-
const { getRecentLogs, LOG_PATH } = require("./logging/logger");
|
|
27090
|
-
const entries = getRecentLogs(count, minLevel);
|
|
27091
|
-
if (entries.length > 0) {
|
|
27092
|
-
return { success: true, entries, totalBuffered: entries.length };
|
|
27093
|
-
}
|
|
27094
|
-
const logFs = require("fs");
|
|
27095
|
-
if (logFs.existsSync(LOG_PATH)) {
|
|
27096
|
-
const content = logFs.readFileSync(LOG_PATH, "utf-8");
|
|
27097
|
-
const allLines = content.split("\n");
|
|
27098
|
-
const recent = allLines.slice(-count).join("\n");
|
|
27099
|
-
return { success: true, logs: recent, totalLines: allLines.length };
|
|
27100
|
-
}
|
|
27101
|
-
return { success: true, entries: [], totalBuffered: 0 };
|
|
27102
|
-
} catch (e) {
|
|
27103
|
-
return { success: false, error: e.message };
|
|
27104
|
-
}
|
|
27105
|
-
}
|
|
27106
27529
|
}
|
|
27107
27530
|
const result = await this.executeDaemonCommand(cmdType, data);
|
|
27108
27531
|
if (result) {
|
|
@@ -27134,6 +27557,31 @@ var init_adhdev_daemon = __esm({
|
|
|
27134
27557
|
case "agent_command": {
|
|
27135
27558
|
return this.cliManager.handleCliCommand(cmd, args);
|
|
27136
27559
|
}
|
|
27560
|
+
case "get_logs": {
|
|
27561
|
+
const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
|
|
27562
|
+
const minLevel = args?.minLevel || "info";
|
|
27563
|
+
const sinceTs = args?.since || 0;
|
|
27564
|
+
try {
|
|
27565
|
+
const { getRecentLogs, LOG_PATH } = require("./logging/logger");
|
|
27566
|
+
let logs = getRecentLogs(count, minLevel);
|
|
27567
|
+
if (sinceTs > 0) {
|
|
27568
|
+
logs = logs.filter((l) => l.ts > sinceTs);
|
|
27569
|
+
}
|
|
27570
|
+
if (logs.length > 0) {
|
|
27571
|
+
return { success: true, logs, totalBuffered: logs.length };
|
|
27572
|
+
}
|
|
27573
|
+
const logFs = require("fs");
|
|
27574
|
+
if (logFs.existsSync(LOG_PATH)) {
|
|
27575
|
+
const content = logFs.readFileSync(LOG_PATH, "utf-8");
|
|
27576
|
+
const allLines = content.split("\n");
|
|
27577
|
+
const recent = allLines.slice(-count).join("\n");
|
|
27578
|
+
return { success: true, logs: recent, totalLines: allLines.length };
|
|
27579
|
+
}
|
|
27580
|
+
return { success: true, logs: [], totalBuffered: 0 };
|
|
27581
|
+
} catch (e) {
|
|
27582
|
+
return { success: false, error: e.message };
|
|
27583
|
+
}
|
|
27584
|
+
}
|
|
27137
27585
|
// ─── restart_session: IDE / CLI / ACP unified ───
|
|
27138
27586
|
case "restart_session": {
|
|
27139
27587
|
const targetType = args?.cliType || args?.agentType || args?.ideType;
|
|
@@ -27169,7 +27617,8 @@ var init_adhdev_daemon = __esm({
|
|
|
27169
27617
|
if (result.success && result.port && result.ideId && !this.cdpManagers.has(result.ideId)) {
|
|
27170
27618
|
const cdpLog = import_daemon_core3.LOG.forComponent(`CDP:${result.ideId}`);
|
|
27171
27619
|
console.log(import_chalk.default.cyan(`[launch_ide] Connecting CDP for ${result.ideId} on port ${result.port}...`));
|
|
27172
|
-
const
|
|
27620
|
+
const provider2 = this.providerLoader.get(result.ideId);
|
|
27621
|
+
const manager = new import_daemon_core3.DaemonCdpManager(result.port, cdpLog.asLogFn(), void 0, provider2?.targetFilter);
|
|
27173
27622
|
const connected = await manager.connect();
|
|
27174
27623
|
if (connected) {
|
|
27175
27624
|
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(result.ideId).map((p) => ({
|
|
@@ -27442,7 +27891,8 @@ var init_adhdev_daemon = __esm({
|
|
|
27442
27891
|
for (const { port, ide } of filteredPorts) {
|
|
27443
27892
|
const allTargets = await import_daemon_core3.DaemonCdpManager.listAllTargets(port);
|
|
27444
27893
|
if (allTargets.length === 0) {
|
|
27445
|
-
const
|
|
27894
|
+
const provider2 = this.providerLoader.get(ide);
|
|
27895
|
+
const manager = new import_daemon_core3.DaemonCdpManager(port, import_daemon_core3.LOG.forComponent(`CDP:${ide}`).asLogFn(), void 0, provider2?.targetFilter);
|
|
27446
27896
|
const connected = await manager.connect();
|
|
27447
27897
|
if (connected) {
|
|
27448
27898
|
this.cdpManagers.set(ide, manager);
|
|
@@ -27461,7 +27911,8 @@ var init_adhdev_daemon = __esm({
|
|
|
27461
27911
|
managerKey = `${ide}_${workspaceName}`;
|
|
27462
27912
|
}
|
|
27463
27913
|
if (this.cdpManagers.has(managerKey)) continue;
|
|
27464
|
-
const
|
|
27914
|
+
const provider2 = this.providerLoader.get(ide);
|
|
27915
|
+
const manager = new import_daemon_core3.DaemonCdpManager(port, import_daemon_core3.LOG.forComponent(`CDP:${managerKey}`).asLogFn(), target.id, provider2?.targetFilter);
|
|
27465
27916
|
const connected = await manager.connect();
|
|
27466
27917
|
if (connected) {
|
|
27467
27918
|
this.cdpManagers.set(managerKey, manager);
|
|
@@ -27504,7 +27955,8 @@ var init_adhdev_daemon = __esm({
|
|
|
27504
27955
|
managerKey = `${ide}_${workspaceName}`;
|
|
27505
27956
|
}
|
|
27506
27957
|
if (this.cdpManagers.has(managerKey)) continue;
|
|
27507
|
-
const
|
|
27958
|
+
const provider2 = this.providerLoader.get(ide);
|
|
27959
|
+
const manager = new import_daemon_core3.DaemonCdpManager(primaryPort, import_daemon_core3.LOG.forComponent(`CDP:${managerKey}`).asLogFn(), target.id, provider2?.targetFilter);
|
|
27508
27960
|
const connected = await manager.connect();
|
|
27509
27961
|
if (connected) {
|
|
27510
27962
|
this.cdpManagers.set(managerKey, manager);
|
|
@@ -27530,9 +27982,7 @@ var import_inquirer = __toESM(require("inquirer"));
|
|
|
27530
27982
|
var import_ora = __toESM(require("ora"));
|
|
27531
27983
|
var import_open = __toESM(require("open"));
|
|
27532
27984
|
var import_daemon_core4 = __toESM(require_dist());
|
|
27533
|
-
var
|
|
27534
|
-
var BUILTIN_PROVIDERS_DIR = (0, import_path.join)(__dirname, "..", "providers", "_builtin");
|
|
27535
|
-
var SERVER_URL = "https://api.adhf.dev";
|
|
27985
|
+
var SERVER_URL = process.env.ADHDEV_SERVER_URL || "https://api.adhf.dev";
|
|
27536
27986
|
var LOGO = `
|
|
27537
27987
|
${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")}
|
|
27538
27988
|
${import_chalk2.default.cyan("\u2551")} ${import_chalk2.default.bold.white("\u{1F9A6} ADHDev Setup Wizard")} ${import_chalk2.default.cyan("\u2551")}
|
|
@@ -27541,7 +27991,7 @@ ${import_chalk2.default.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u
|
|
|
27541
27991
|
`;
|
|
27542
27992
|
var DIVIDER = import_chalk2.default.gray("\u2500".repeat(44));
|
|
27543
27993
|
async function runWizard(options = {}) {
|
|
27544
|
-
const loader = new import_daemon_core4.ProviderLoader({
|
|
27994
|
+
const loader = new import_daemon_core4.ProviderLoader({ logFn: () => {
|
|
27545
27995
|
} });
|
|
27546
27996
|
loader.loadAll();
|
|
27547
27997
|
loader.registerToDetector();
|
|
@@ -27868,7 +28318,7 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
27868
28318
|
return path3.join(home, ".config", appName2, "User", "settings.json");
|
|
27869
28319
|
}
|
|
27870
28320
|
};
|
|
27871
|
-
const loader = new import_daemon_core4.ProviderLoader({
|
|
28321
|
+
const loader = new import_daemon_core4.ProviderLoader({ logFn: () => {
|
|
27872
28322
|
} });
|
|
27873
28323
|
loader.loadAll();
|
|
27874
28324
|
const appNameMap = loader.getMacAppIdentifiers();
|
|
@@ -28033,18 +28483,18 @@ async function installCliOnly() {
|
|
|
28033
28483
|
// src/cli-entrypoint.ts
|
|
28034
28484
|
var import_daemon_core5 = __toESM(require_dist());
|
|
28035
28485
|
var import_fs = require("fs");
|
|
28036
|
-
var
|
|
28037
|
-
var
|
|
28486
|
+
var import_path = require("path");
|
|
28487
|
+
var pkgVersion2 = "unknown";
|
|
28038
28488
|
try {
|
|
28039
28489
|
const possiblePaths = [
|
|
28040
|
-
(0,
|
|
28041
|
-
(0,
|
|
28490
|
+
(0, import_path.join)(__dirname, "..", "package.json"),
|
|
28491
|
+
(0, import_path.join)(__dirname, "package.json")
|
|
28042
28492
|
];
|
|
28043
28493
|
for (const p of possiblePaths) {
|
|
28044
28494
|
try {
|
|
28045
28495
|
const data = JSON.parse((0, import_fs.readFileSync)(p, "utf-8"));
|
|
28046
28496
|
if (data.version) {
|
|
28047
|
-
|
|
28497
|
+
pkgVersion2 = data.version;
|
|
28048
28498
|
break;
|
|
28049
28499
|
}
|
|
28050
28500
|
} catch {
|
|
@@ -28052,13 +28502,12 @@ try {
|
|
|
28052
28502
|
}
|
|
28053
28503
|
} catch {
|
|
28054
28504
|
}
|
|
28055
|
-
var
|
|
28056
|
-
var _cliProviderLoader = new import_daemon_core5.ProviderLoader({ builtinDir: BUILTIN_PROVIDERS_DIR2, logFn: () => {
|
|
28505
|
+
var _cliProviderLoader = new import_daemon_core5.ProviderLoader({ logFn: () => {
|
|
28057
28506
|
} });
|
|
28058
28507
|
_cliProviderLoader.loadAll();
|
|
28059
28508
|
_cliProviderLoader.registerToDetector();
|
|
28060
28509
|
var program = new import_commander.Command();
|
|
28061
|
-
program.name("adhdev").description("\u{1F9A6} ADHDev \u2014 Agent Dashboard Hub for Dev").version(
|
|
28510
|
+
program.name("adhdev").description("\u{1F9A6} ADHDev \u2014 Agent Dashboard Hub for Dev").version(pkgVersion2);
|
|
28062
28511
|
program.command("setup").description("Run the interactive setup wizard (detect IDEs, login)").option("-f, --force", "Force re-run setup even if already configured").action(async (options) => {
|
|
28063
28512
|
await runWizard({ force: options.force });
|
|
28064
28513
|
});
|
|
@@ -28392,7 +28841,7 @@ program.command("daemon:upgrade").description("Upgrade ADHDev to latest version
|
|
|
28392
28841
|
const adhdevPath = process.argv[1];
|
|
28393
28842
|
const realPath = fsMod.realpathSync(adhdevPath);
|
|
28394
28843
|
const isLinked = realPath.includes(".openclaw") || realPath.includes("/src/");
|
|
28395
|
-
const currentVersion =
|
|
28844
|
+
const currentVersion = pkgVersion2;
|
|
28396
28845
|
console.log(` ${import_chalk3.default.bold("Current:")} v${currentVersion}`);
|
|
28397
28846
|
console.log(` ${import_chalk3.default.bold("Install:")} ${isLinked ? "npm link (dev)" : "npm global"}`);
|
|
28398
28847
|
if (isLinked) {
|
|
@@ -28571,7 +29020,7 @@ var provider = program.command("provider").description("\u{1F50C} Provider manag
|
|
|
28571
29020
|
provider.command("list").description("List all loaded providers").option("-j, --json", "Output raw JSON").action(async (options) => {
|
|
28572
29021
|
try {
|
|
28573
29022
|
const { ProviderLoader: ProviderLoader4 } = await Promise.resolve().then(() => __toESM(require_dist()));
|
|
28574
|
-
const loader = new ProviderLoader4(
|
|
29023
|
+
const loader = new ProviderLoader4();
|
|
28575
29024
|
loader.loadAll();
|
|
28576
29025
|
const providers = loader.getAll();
|
|
28577
29026
|
if (options.json) {
|