adhdev 0.5.3 → 0.5.6
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 +1275 -454
- package/dist/cli-entrypoint.js.map +1 -1
- package/dist/index.js +1274 -453
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli-entrypoint.js
CHANGED
|
@@ -16369,6 +16369,190 @@ var require_dist = __commonJS({
|
|
|
16369
16369
|
mod
|
|
16370
16370
|
));
|
|
16371
16371
|
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
16372
|
+
function expandPath(p) {
|
|
16373
|
+
const t = (p || "").trim();
|
|
16374
|
+
if (!t) return "";
|
|
16375
|
+
if (t.startsWith("~")) return path3.join(os3.homedir(), t.slice(1).replace(/^\//, ""));
|
|
16376
|
+
return path3.resolve(t);
|
|
16377
|
+
}
|
|
16378
|
+
function validateWorkspacePath(absPath) {
|
|
16379
|
+
try {
|
|
16380
|
+
if (!absPath) return { ok: false, error: "Path required" };
|
|
16381
|
+
if (!fs3.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
|
|
16382
|
+
const st = fs3.statSync(absPath);
|
|
16383
|
+
if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
|
|
16384
|
+
return { ok: true };
|
|
16385
|
+
} catch (e) {
|
|
16386
|
+
return { ok: false, error: e?.message || "Invalid path" };
|
|
16387
|
+
}
|
|
16388
|
+
}
|
|
16389
|
+
function defaultWorkspaceLabel(absPath) {
|
|
16390
|
+
const base = path3.basename(absPath) || absPath;
|
|
16391
|
+
return base;
|
|
16392
|
+
}
|
|
16393
|
+
function migrateWorkspacesFromRecent(config2) {
|
|
16394
|
+
if (!config2.workspaces) config2.workspaces = [];
|
|
16395
|
+
if (config2.workspaces.length > 0) return config2;
|
|
16396
|
+
const recent = config2.recentCliWorkspaces || [];
|
|
16397
|
+
const now = Date.now();
|
|
16398
|
+
for (const raw of recent) {
|
|
16399
|
+
const abs = expandPath(raw);
|
|
16400
|
+
if (!abs || validateWorkspacePath(abs).ok !== true) continue;
|
|
16401
|
+
if (config2.workspaces.some((w) => path3.resolve(w.path) === abs)) continue;
|
|
16402
|
+
config2.workspaces.push({
|
|
16403
|
+
id: (0, import_crypto.randomUUID)(),
|
|
16404
|
+
path: abs,
|
|
16405
|
+
label: defaultWorkspaceLabel(abs),
|
|
16406
|
+
addedAt: now
|
|
16407
|
+
});
|
|
16408
|
+
if (config2.workspaces.length >= MAX_WORKSPACES) break;
|
|
16409
|
+
}
|
|
16410
|
+
return config2;
|
|
16411
|
+
}
|
|
16412
|
+
function getDefaultWorkspacePath(config2) {
|
|
16413
|
+
const id = config2.defaultWorkspaceId;
|
|
16414
|
+
if (!id) return null;
|
|
16415
|
+
const w = (config2.workspaces || []).find((x) => x.id === id);
|
|
16416
|
+
if (!w) return null;
|
|
16417
|
+
const abs = expandPath(w.path);
|
|
16418
|
+
if (validateWorkspacePath(abs).ok !== true) return null;
|
|
16419
|
+
return abs;
|
|
16420
|
+
}
|
|
16421
|
+
function getWorkspaceState(config2) {
|
|
16422
|
+
const workspaces = [...config2.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
|
|
16423
|
+
const defaultWorkspacePath = getDefaultWorkspacePath(config2);
|
|
16424
|
+
return {
|
|
16425
|
+
workspaces,
|
|
16426
|
+
defaultWorkspaceId: config2.defaultWorkspaceId ?? null,
|
|
16427
|
+
defaultWorkspacePath
|
|
16428
|
+
};
|
|
16429
|
+
}
|
|
16430
|
+
function resolveLaunchDirectory(args, config2) {
|
|
16431
|
+
const a = args || {};
|
|
16432
|
+
if (a.dir != null && String(a.dir).trim()) {
|
|
16433
|
+
const abs = expandPath(String(a.dir).trim());
|
|
16434
|
+
if (abs && validateWorkspacePath(abs).ok === true) {
|
|
16435
|
+
return { ok: true, path: abs, source: "dir" };
|
|
16436
|
+
}
|
|
16437
|
+
return {
|
|
16438
|
+
ok: false,
|
|
16439
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
16440
|
+
message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
|
|
16441
|
+
};
|
|
16442
|
+
}
|
|
16443
|
+
if (a.workspaceId) {
|
|
16444
|
+
const w = (config2.workspaces || []).find((x) => x.id === a.workspaceId);
|
|
16445
|
+
if (w) {
|
|
16446
|
+
const abs = expandPath(w.path);
|
|
16447
|
+
if (validateWorkspacePath(abs).ok === true) {
|
|
16448
|
+
return { ok: true, path: abs, source: "workspaceId" };
|
|
16449
|
+
}
|
|
16450
|
+
}
|
|
16451
|
+
return {
|
|
16452
|
+
ok: false,
|
|
16453
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
16454
|
+
message: "Saved workspace not found or path is no longer valid"
|
|
16455
|
+
};
|
|
16456
|
+
}
|
|
16457
|
+
if (a.useDefaultWorkspace === true) {
|
|
16458
|
+
const d = getDefaultWorkspacePath(config2);
|
|
16459
|
+
if (d) return { ok: true, path: d, source: "defaultWorkspace" };
|
|
16460
|
+
return {
|
|
16461
|
+
ok: false,
|
|
16462
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
16463
|
+
message: "No default workspace is set"
|
|
16464
|
+
};
|
|
16465
|
+
}
|
|
16466
|
+
if (a.useHome === true) {
|
|
16467
|
+
return { ok: true, path: os3.homedir(), source: "home" };
|
|
16468
|
+
}
|
|
16469
|
+
return {
|
|
16470
|
+
ok: false,
|
|
16471
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
16472
|
+
message: "Choose a directory, saved workspace, default workspace, or home before launching."
|
|
16473
|
+
};
|
|
16474
|
+
}
|
|
16475
|
+
function resolveIdeWorkspaceFromArgs(args, config2) {
|
|
16476
|
+
const ar = args || {};
|
|
16477
|
+
if (ar.workspace) {
|
|
16478
|
+
const abs = expandPath(ar.workspace);
|
|
16479
|
+
if (abs && validateWorkspacePath(abs).ok === true) return abs;
|
|
16480
|
+
}
|
|
16481
|
+
if (ar.workspaceId) {
|
|
16482
|
+
const w = (config2.workspaces || []).find((x) => x.id === ar.workspaceId);
|
|
16483
|
+
if (w) {
|
|
16484
|
+
const abs = expandPath(w.path);
|
|
16485
|
+
if (validateWorkspacePath(abs).ok === true) return abs;
|
|
16486
|
+
}
|
|
16487
|
+
}
|
|
16488
|
+
if (ar.useDefaultWorkspace === true) {
|
|
16489
|
+
return getDefaultWorkspacePath(config2) || void 0;
|
|
16490
|
+
}
|
|
16491
|
+
return void 0;
|
|
16492
|
+
}
|
|
16493
|
+
function resolveIdeLaunchWorkspace(args, config2) {
|
|
16494
|
+
const direct = resolveIdeWorkspaceFromArgs(args, config2);
|
|
16495
|
+
if (direct) return direct;
|
|
16496
|
+
if (args?.useDefaultWorkspace === false) return void 0;
|
|
16497
|
+
return getDefaultWorkspacePath(config2) || void 0;
|
|
16498
|
+
}
|
|
16499
|
+
function findWorkspaceByPath(config2, rawPath) {
|
|
16500
|
+
const abs = path3.resolve(expandPath(rawPath));
|
|
16501
|
+
if (!abs) return void 0;
|
|
16502
|
+
return (config2.workspaces || []).find((w) => path3.resolve(expandPath(w.path)) === abs);
|
|
16503
|
+
}
|
|
16504
|
+
function addWorkspaceEntry(config2, rawPath, label) {
|
|
16505
|
+
const abs = expandPath(rawPath);
|
|
16506
|
+
const v = validateWorkspacePath(abs);
|
|
16507
|
+
if (!v.ok) return { error: v.error };
|
|
16508
|
+
const list = [...config2.workspaces || []];
|
|
16509
|
+
if (list.some((w) => path3.resolve(w.path) === abs)) {
|
|
16510
|
+
return { error: "Workspace already in list" };
|
|
16511
|
+
}
|
|
16512
|
+
if (list.length >= MAX_WORKSPACES) {
|
|
16513
|
+
return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
|
|
16514
|
+
}
|
|
16515
|
+
const entry = {
|
|
16516
|
+
id: (0, import_crypto.randomUUID)(),
|
|
16517
|
+
path: abs,
|
|
16518
|
+
label: (label || "").trim() || defaultWorkspaceLabel(abs),
|
|
16519
|
+
addedAt: Date.now()
|
|
16520
|
+
};
|
|
16521
|
+
list.push(entry);
|
|
16522
|
+
return { config: { ...config2, workspaces: list }, entry };
|
|
16523
|
+
}
|
|
16524
|
+
function removeWorkspaceEntry(config2, id) {
|
|
16525
|
+
const list = (config2.workspaces || []).filter((w) => w.id !== id);
|
|
16526
|
+
if (list.length === (config2.workspaces || []).length) return { error: "Workspace not found" };
|
|
16527
|
+
let defaultWorkspaceId = config2.defaultWorkspaceId;
|
|
16528
|
+
if (defaultWorkspaceId === id) defaultWorkspaceId = null;
|
|
16529
|
+
return { config: { ...config2, workspaces: list, defaultWorkspaceId } };
|
|
16530
|
+
}
|
|
16531
|
+
function setDefaultWorkspaceId(config2, id) {
|
|
16532
|
+
if (id === null) {
|
|
16533
|
+
return { config: { ...config2, defaultWorkspaceId: null } };
|
|
16534
|
+
}
|
|
16535
|
+
const w = (config2.workspaces || []).find((x) => x.id === id);
|
|
16536
|
+
if (!w) return { error: "Workspace not found" };
|
|
16537
|
+
const abs = expandPath(w.path);
|
|
16538
|
+
if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
|
|
16539
|
+
return { config: { ...config2, defaultWorkspaceId: id } };
|
|
16540
|
+
}
|
|
16541
|
+
var fs3;
|
|
16542
|
+
var os3;
|
|
16543
|
+
var path3;
|
|
16544
|
+
var import_crypto;
|
|
16545
|
+
var MAX_WORKSPACES;
|
|
16546
|
+
var init_workspaces = __esm2({
|
|
16547
|
+
"src/config/workspaces.ts"() {
|
|
16548
|
+
"use strict";
|
|
16549
|
+
fs3 = __toESM2(require("fs"));
|
|
16550
|
+
os3 = __toESM2(require("os"));
|
|
16551
|
+
path3 = __toESM2(require("path"));
|
|
16552
|
+
import_crypto = require("crypto");
|
|
16553
|
+
MAX_WORKSPACES = 50;
|
|
16554
|
+
}
|
|
16555
|
+
});
|
|
16372
16556
|
var config_exports = {};
|
|
16373
16557
|
__export2(config_exports, {
|
|
16374
16558
|
addCliHistory: () => addCliHistory,
|
|
@@ -16399,7 +16583,20 @@ var require_dist = __commonJS({
|
|
|
16399
16583
|
try {
|
|
16400
16584
|
const raw = (0, import_fs2.readFileSync)(configPath, "utf-8");
|
|
16401
16585
|
const parsed = JSON.parse(raw);
|
|
16402
|
-
|
|
16586
|
+
const merged = { ...DEFAULT_CONFIG, ...parsed };
|
|
16587
|
+
if (merged.defaultWorkspaceId == null && merged.activeWorkspaceId != null) {
|
|
16588
|
+
merged.defaultWorkspaceId = merged.activeWorkspaceId;
|
|
16589
|
+
}
|
|
16590
|
+
delete merged.activeWorkspaceId;
|
|
16591
|
+
const hadStoredWorkspaces = Array.isArray(parsed.workspaces) && parsed.workspaces.length > 0;
|
|
16592
|
+
migrateWorkspacesFromRecent(merged);
|
|
16593
|
+
if (!hadStoredWorkspaces && (merged.workspaces?.length || 0) > 0) {
|
|
16594
|
+
try {
|
|
16595
|
+
saveConfig2(merged);
|
|
16596
|
+
} catch {
|
|
16597
|
+
}
|
|
16598
|
+
}
|
|
16599
|
+
return merged;
|
|
16403
16600
|
} catch {
|
|
16404
16601
|
return { ...DEFAULT_CONFIG };
|
|
16405
16602
|
}
|
|
@@ -16473,6 +16670,7 @@ var require_dist = __commonJS({
|
|
|
16473
16670
|
import_os = require("os");
|
|
16474
16671
|
import_path2 = require("path");
|
|
16475
16672
|
import_fs2 = require("fs");
|
|
16673
|
+
init_workspaces();
|
|
16476
16674
|
DEFAULT_CONFIG = {
|
|
16477
16675
|
serverUrl: "https://api.adhf.dev",
|
|
16478
16676
|
apiToken: null,
|
|
@@ -16489,6 +16687,9 @@ var require_dist = __commonJS({
|
|
|
16489
16687
|
configuredCLIs: [],
|
|
16490
16688
|
enabledIdes: [],
|
|
16491
16689
|
recentCliWorkspaces: [],
|
|
16690
|
+
workspaces: [],
|
|
16691
|
+
defaultWorkspaceId: null,
|
|
16692
|
+
recentWorkspaceActivity: [],
|
|
16492
16693
|
machineNickname: null,
|
|
16493
16694
|
cliHistory: [],
|
|
16494
16695
|
providerSettings: {},
|
|
@@ -16526,9 +16727,12 @@ var require_dist = __commonJS({
|
|
|
16526
16727
|
detectIDEs: () => detectIDEs3,
|
|
16527
16728
|
getAIExtensions: () => getAIExtensions2,
|
|
16528
16729
|
getAvailableIdeIds: () => getAvailableIdeIds2,
|
|
16730
|
+
getHostMemorySnapshot: () => getHostMemorySnapshot,
|
|
16529
16731
|
getLogLevel: () => getLogLevel,
|
|
16530
16732
|
getRecentCommands: () => getRecentCommands,
|
|
16531
16733
|
getRecentLogs: () => getRecentLogs,
|
|
16734
|
+
getWorkspaceActivity: () => getWorkspaceActivity,
|
|
16735
|
+
getWorkspaceState: () => getWorkspaceState,
|
|
16532
16736
|
initDaemonComponents: () => initDaemonComponents2,
|
|
16533
16737
|
installExtensions: () => installExtensions2,
|
|
16534
16738
|
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
@@ -16551,6 +16755,45 @@ var require_dist = __commonJS({
|
|
|
16551
16755
|
});
|
|
16552
16756
|
module2.exports = __toCommonJS2(index_exports);
|
|
16553
16757
|
init_config();
|
|
16758
|
+
init_workspaces();
|
|
16759
|
+
var path22 = __toESM2(require("path"));
|
|
16760
|
+
init_workspaces();
|
|
16761
|
+
var MAX_ACTIVITY = 30;
|
|
16762
|
+
function normWorkspacePath(p) {
|
|
16763
|
+
try {
|
|
16764
|
+
return path22.resolve(expandPath(p));
|
|
16765
|
+
} catch {
|
|
16766
|
+
return path22.resolve(p);
|
|
16767
|
+
}
|
|
16768
|
+
}
|
|
16769
|
+
function appendWorkspaceActivity(config2, rawPath, meta3) {
|
|
16770
|
+
const abs = normWorkspacePath(rawPath);
|
|
16771
|
+
if (!abs) return config2;
|
|
16772
|
+
const prev = config2.recentWorkspaceActivity || [];
|
|
16773
|
+
const filtered = prev.filter((e) => normWorkspacePath(e.path) !== abs);
|
|
16774
|
+
const entry = {
|
|
16775
|
+
path: abs,
|
|
16776
|
+
lastUsedAt: Date.now(),
|
|
16777
|
+
kind: meta3?.kind,
|
|
16778
|
+
agentType: meta3?.agentType
|
|
16779
|
+
};
|
|
16780
|
+
const recentWorkspaceActivity = [entry, ...filtered].slice(0, MAX_ACTIVITY);
|
|
16781
|
+
return { ...config2, recentWorkspaceActivity };
|
|
16782
|
+
}
|
|
16783
|
+
function getWorkspaceActivity(config2, limit = 20) {
|
|
16784
|
+
const list = [...config2.recentWorkspaceActivity || []];
|
|
16785
|
+
list.sort((a, b) => b.lastUsedAt - a.lastUsedAt);
|
|
16786
|
+
return list.slice(0, limit);
|
|
16787
|
+
}
|
|
16788
|
+
function removeActivityForPath(config2, rawPath) {
|
|
16789
|
+
const n = normWorkspacePath(rawPath);
|
|
16790
|
+
return {
|
|
16791
|
+
...config2,
|
|
16792
|
+
recentWorkspaceActivity: (config2.recentWorkspaceActivity || []).filter(
|
|
16793
|
+
(e) => normWorkspacePath(e.path) !== n
|
|
16794
|
+
)
|
|
16795
|
+
};
|
|
16796
|
+
}
|
|
16554
16797
|
var import_child_process = require("child_process");
|
|
16555
16798
|
var import_fs22 = require("fs");
|
|
16556
16799
|
var import_os2 = require("os");
|
|
@@ -16608,20 +16851,20 @@ var require_dist = __commonJS({
|
|
|
16608
16851
|
return null;
|
|
16609
16852
|
}
|
|
16610
16853
|
async function detectIDEs3() {
|
|
16611
|
-
const
|
|
16854
|
+
const os15 = (0, import_os2.platform)();
|
|
16612
16855
|
const results = [];
|
|
16613
16856
|
for (const def of getMergedDefinitions()) {
|
|
16614
16857
|
const cliPath = findCliCommand(def.cli);
|
|
16615
|
-
const appPath = checkPathExists(def.paths[
|
|
16858
|
+
const appPath = checkPathExists(def.paths[os15] || []);
|
|
16616
16859
|
const installed = !!(cliPath || appPath);
|
|
16617
16860
|
let resolvedCli = cliPath;
|
|
16618
|
-
if (!resolvedCli && appPath &&
|
|
16861
|
+
if (!resolvedCli && appPath && os15 === "darwin") {
|
|
16619
16862
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
16620
16863
|
if ((0, import_fs22.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
16621
16864
|
}
|
|
16622
|
-
if (!resolvedCli && appPath &&
|
|
16623
|
-
const { dirname:
|
|
16624
|
-
const appDir =
|
|
16865
|
+
if (!resolvedCli && appPath && os15 === "win32") {
|
|
16866
|
+
const { dirname: dirname6 } = await import("path");
|
|
16867
|
+
const appDir = dirname6(appPath);
|
|
16625
16868
|
const candidates = [
|
|
16626
16869
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
16627
16870
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -16652,22 +16895,22 @@ var require_dist = __commonJS({
|
|
|
16652
16895
|
return results;
|
|
16653
16896
|
}
|
|
16654
16897
|
var import_child_process2 = require("child_process");
|
|
16655
|
-
var
|
|
16898
|
+
var os22 = __toESM2(require("os"));
|
|
16656
16899
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
16657
|
-
return new Promise((
|
|
16900
|
+
return new Promise((resolve7) => {
|
|
16658
16901
|
const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
16659
16902
|
if (err || !stdout?.trim()) {
|
|
16660
|
-
|
|
16903
|
+
resolve7(null);
|
|
16661
16904
|
} else {
|
|
16662
|
-
|
|
16905
|
+
resolve7(stdout.trim());
|
|
16663
16906
|
}
|
|
16664
16907
|
});
|
|
16665
|
-
child.on("error", () =>
|
|
16908
|
+
child.on("error", () => resolve7(null));
|
|
16666
16909
|
});
|
|
16667
16910
|
}
|
|
16668
16911
|
async function detectCLIs2(providerLoader) {
|
|
16669
|
-
const
|
|
16670
|
-
const whichCmd =
|
|
16912
|
+
const platform8 = os22.platform();
|
|
16913
|
+
const whichCmd = platform8 === "win32" ? "where" : "which";
|
|
16671
16914
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
16672
16915
|
const results = await Promise.all(
|
|
16673
16916
|
cliList.map(async (cli) => {
|
|
@@ -16697,11 +16940,51 @@ var require_dist = __commonJS({
|
|
|
16697
16940
|
const all = await detectCLIs2(providerLoader);
|
|
16698
16941
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
16699
16942
|
}
|
|
16943
|
+
var os32 = __toESM2(require("os"));
|
|
16944
|
+
var import_child_process3 = require("child_process");
|
|
16945
|
+
function parseDarwinAvailableBytes(totalMem) {
|
|
16946
|
+
if (os32.platform() !== "darwin") return null;
|
|
16947
|
+
try {
|
|
16948
|
+
const out = (0, import_child_process3.execSync)("vm_stat", {
|
|
16949
|
+
encoding: "utf-8",
|
|
16950
|
+
timeout: 4e3,
|
|
16951
|
+
maxBuffer: 256 * 1024
|
|
16952
|
+
});
|
|
16953
|
+
const pageSizeMatch = out.match(/page size of (\d+)\s*bytes/i);
|
|
16954
|
+
const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 4096;
|
|
16955
|
+
const counts = {};
|
|
16956
|
+
for (const line of out.split("\n")) {
|
|
16957
|
+
const m = line.match(/^\s*Pages\s+([^:]+):\s+([\d,]+)\s*\.?/);
|
|
16958
|
+
if (!m) continue;
|
|
16959
|
+
const key = m[1].trim().toLowerCase().replace(/\s+/g, "_");
|
|
16960
|
+
const n = parseInt(m[2].replace(/,/g, ""), 10);
|
|
16961
|
+
if (!Number.isNaN(n)) counts[key] = n;
|
|
16962
|
+
}
|
|
16963
|
+
const free = counts["free"] ?? 0;
|
|
16964
|
+
const inactive = counts["inactive"] ?? 0;
|
|
16965
|
+
const speculative = counts["speculative"] ?? 0;
|
|
16966
|
+
const purgeable = counts["purgeable"] ?? 0;
|
|
16967
|
+
const fileBacked = counts["file_backed"] ?? 0;
|
|
16968
|
+
const availPages = free + inactive + speculative + purgeable + fileBacked;
|
|
16969
|
+
const bytes = availPages * pageSize;
|
|
16970
|
+
if (!Number.isFinite(bytes) || bytes < 0) return null;
|
|
16971
|
+
return Math.min(bytes, totalMem);
|
|
16972
|
+
} catch {
|
|
16973
|
+
return null;
|
|
16974
|
+
}
|
|
16975
|
+
}
|
|
16976
|
+
function getHostMemorySnapshot() {
|
|
16977
|
+
const totalMem = os32.totalmem();
|
|
16978
|
+
const freeMem = os32.freemem();
|
|
16979
|
+
const darwinAvail = parseDarwinAvailableBytes(totalMem);
|
|
16980
|
+
const availableMem = darwinAvail != null ? darwinAvail : freeMem;
|
|
16981
|
+
return { totalMem, freeMem, availableMem };
|
|
16982
|
+
}
|
|
16700
16983
|
var import_ws2 = __toESM2(require("ws"));
|
|
16701
16984
|
var http = __toESM2(require("http"));
|
|
16702
|
-
var
|
|
16703
|
-
var
|
|
16704
|
-
var
|
|
16985
|
+
var fs22 = __toESM2(require("fs"));
|
|
16986
|
+
var path32 = __toESM2(require("path"));
|
|
16987
|
+
var os4 = __toESM2(require("os"));
|
|
16705
16988
|
var LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
16706
16989
|
var LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
16707
16990
|
var currentLevel = "info";
|
|
@@ -16712,29 +16995,29 @@ var require_dist = __commonJS({
|
|
|
16712
16995
|
function getLogLevel() {
|
|
16713
16996
|
return currentLevel;
|
|
16714
16997
|
}
|
|
16715
|
-
var LOG_DIR = process.platform === "darwin" ?
|
|
16998
|
+
var LOG_DIR = process.platform === "darwin" ? path32.join(os4.homedir(), "Library", "Logs", "adhdev") : path32.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
16716
16999
|
var MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
16717
17000
|
var MAX_LOG_DAYS = 7;
|
|
16718
17001
|
try {
|
|
16719
|
-
|
|
17002
|
+
fs22.mkdirSync(LOG_DIR, { recursive: true });
|
|
16720
17003
|
} catch {
|
|
16721
17004
|
}
|
|
16722
17005
|
function getDateStr() {
|
|
16723
17006
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
16724
17007
|
}
|
|
16725
17008
|
var currentDate = getDateStr();
|
|
16726
|
-
var currentLogFile =
|
|
17009
|
+
var currentLogFile = path32.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
16727
17010
|
function checkDateRotation() {
|
|
16728
17011
|
const today = getDateStr();
|
|
16729
17012
|
if (today !== currentDate) {
|
|
16730
17013
|
currentDate = today;
|
|
16731
|
-
currentLogFile =
|
|
17014
|
+
currentLogFile = path32.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
16732
17015
|
cleanOldLogs();
|
|
16733
17016
|
}
|
|
16734
17017
|
}
|
|
16735
17018
|
function cleanOldLogs() {
|
|
16736
17019
|
try {
|
|
16737
|
-
const files =
|
|
17020
|
+
const files = fs22.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
16738
17021
|
const cutoff = /* @__PURE__ */ new Date();
|
|
16739
17022
|
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
16740
17023
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -16742,7 +17025,7 @@ var require_dist = __commonJS({
|
|
|
16742
17025
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
16743
17026
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
16744
17027
|
try {
|
|
16745
|
-
|
|
17028
|
+
fs22.unlinkSync(path32.join(LOG_DIR, file2));
|
|
16746
17029
|
} catch {
|
|
16747
17030
|
}
|
|
16748
17031
|
}
|
|
@@ -16752,29 +17035,29 @@ var require_dist = __commonJS({
|
|
|
16752
17035
|
}
|
|
16753
17036
|
function rotateSizeIfNeeded() {
|
|
16754
17037
|
try {
|
|
16755
|
-
const stat =
|
|
17038
|
+
const stat = fs22.statSync(currentLogFile);
|
|
16756
17039
|
if (stat.size > MAX_LOG_SIZE) {
|
|
16757
17040
|
const backup = currentLogFile.replace(".log", ".1.log");
|
|
16758
17041
|
try {
|
|
16759
|
-
|
|
17042
|
+
fs22.unlinkSync(backup);
|
|
16760
17043
|
} catch {
|
|
16761
17044
|
}
|
|
16762
|
-
|
|
17045
|
+
fs22.renameSync(currentLogFile, backup);
|
|
16763
17046
|
}
|
|
16764
17047
|
} catch {
|
|
16765
17048
|
}
|
|
16766
17049
|
}
|
|
16767
17050
|
cleanOldLogs();
|
|
16768
17051
|
try {
|
|
16769
|
-
const oldLog =
|
|
16770
|
-
if (
|
|
16771
|
-
const stat =
|
|
17052
|
+
const oldLog = path32.join(LOG_DIR, "daemon.log");
|
|
17053
|
+
if (fs22.existsSync(oldLog)) {
|
|
17054
|
+
const stat = fs22.statSync(oldLog);
|
|
16772
17055
|
const oldDate = stat.mtime.toISOString().slice(0, 10);
|
|
16773
|
-
|
|
17056
|
+
fs22.renameSync(oldLog, path32.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
16774
17057
|
}
|
|
16775
|
-
const oldLogBackup =
|
|
16776
|
-
if (
|
|
16777
|
-
|
|
17058
|
+
const oldLogBackup = path32.join(LOG_DIR, "daemon.log.old");
|
|
17059
|
+
if (fs22.existsSync(oldLogBackup)) {
|
|
17060
|
+
fs22.unlinkSync(oldLogBackup);
|
|
16778
17061
|
}
|
|
16779
17062
|
} catch {
|
|
16780
17063
|
}
|
|
@@ -16785,7 +17068,7 @@ var require_dist = __commonJS({
|
|
|
16785
17068
|
checkDateRotation();
|
|
16786
17069
|
rotateSizeIfNeeded();
|
|
16787
17070
|
}
|
|
16788
|
-
|
|
17071
|
+
fs22.appendFileSync(currentLogFile, line + "\n");
|
|
16789
17072
|
} catch {
|
|
16790
17073
|
}
|
|
16791
17074
|
}
|
|
@@ -16899,7 +17182,7 @@ var require_dist = __commonJS({
|
|
|
16899
17182
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
16900
17183
|
writeToFile(`Log level: ${currentLevel}`);
|
|
16901
17184
|
}
|
|
16902
|
-
var LOG_PATH =
|
|
17185
|
+
var LOG_PATH = path32.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
16903
17186
|
var DaemonCdpManager2 = class {
|
|
16904
17187
|
ws = null;
|
|
16905
17188
|
browserWs = null;
|
|
@@ -16972,7 +17255,7 @@ var require_dist = __commonJS({
|
|
|
16972
17255
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
16973
17256
|
*/
|
|
16974
17257
|
static listAllTargets(port) {
|
|
16975
|
-
return new Promise((
|
|
17258
|
+
return new Promise((resolve7) => {
|
|
16976
17259
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
16977
17260
|
let data = "";
|
|
16978
17261
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -16988,16 +17271,16 @@ var require_dist = __commonJS({
|
|
|
16988
17271
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
16989
17272
|
);
|
|
16990
17273
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
16991
|
-
|
|
17274
|
+
resolve7(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
16992
17275
|
} catch {
|
|
16993
|
-
|
|
17276
|
+
resolve7([]);
|
|
16994
17277
|
}
|
|
16995
17278
|
});
|
|
16996
17279
|
});
|
|
16997
|
-
req.on("error", () =>
|
|
17280
|
+
req.on("error", () => resolve7([]));
|
|
16998
17281
|
req.setTimeout(2e3, () => {
|
|
16999
17282
|
req.destroy();
|
|
17000
|
-
|
|
17283
|
+
resolve7([]);
|
|
17001
17284
|
});
|
|
17002
17285
|
});
|
|
17003
17286
|
}
|
|
@@ -17037,7 +17320,7 @@ var require_dist = __commonJS({
|
|
|
17037
17320
|
}
|
|
17038
17321
|
}
|
|
17039
17322
|
findTargetOnPort(port) {
|
|
17040
|
-
return new Promise((
|
|
17323
|
+
return new Promise((resolve7) => {
|
|
17041
17324
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
17042
17325
|
let data = "";
|
|
17043
17326
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -17048,7 +17331,7 @@ var require_dist = __commonJS({
|
|
|
17048
17331
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
17049
17332
|
);
|
|
17050
17333
|
if (pages.length === 0) {
|
|
17051
|
-
|
|
17334
|
+
resolve7(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
17052
17335
|
return;
|
|
17053
17336
|
}
|
|
17054
17337
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -17058,24 +17341,24 @@ var require_dist = __commonJS({
|
|
|
17058
17341
|
const specific = list.find((t) => t.id === this._targetId);
|
|
17059
17342
|
if (specific) {
|
|
17060
17343
|
this._pageTitle = specific.title || "";
|
|
17061
|
-
|
|
17344
|
+
resolve7(specific);
|
|
17062
17345
|
} else {
|
|
17063
17346
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
17064
|
-
|
|
17347
|
+
resolve7(null);
|
|
17065
17348
|
}
|
|
17066
17349
|
return;
|
|
17067
17350
|
}
|
|
17068
17351
|
this._pageTitle = list[0]?.title || "";
|
|
17069
|
-
|
|
17352
|
+
resolve7(list[0]);
|
|
17070
17353
|
} catch {
|
|
17071
|
-
|
|
17354
|
+
resolve7(null);
|
|
17072
17355
|
}
|
|
17073
17356
|
});
|
|
17074
17357
|
});
|
|
17075
|
-
req.on("error", () =>
|
|
17358
|
+
req.on("error", () => resolve7(null));
|
|
17076
17359
|
req.setTimeout(2e3, () => {
|
|
17077
17360
|
req.destroy();
|
|
17078
|
-
|
|
17361
|
+
resolve7(null);
|
|
17079
17362
|
});
|
|
17080
17363
|
});
|
|
17081
17364
|
}
|
|
@@ -17086,7 +17369,7 @@ var require_dist = __commonJS({
|
|
|
17086
17369
|
this.extensionProviders = providers;
|
|
17087
17370
|
}
|
|
17088
17371
|
connectToTarget(wsUrl) {
|
|
17089
|
-
return new Promise((
|
|
17372
|
+
return new Promise((resolve7) => {
|
|
17090
17373
|
this.ws = new import_ws2.default(wsUrl);
|
|
17091
17374
|
this.ws.on("open", async () => {
|
|
17092
17375
|
this._connected = true;
|
|
@@ -17096,17 +17379,17 @@ var require_dist = __commonJS({
|
|
|
17096
17379
|
}
|
|
17097
17380
|
this.connectBrowserWs().catch(() => {
|
|
17098
17381
|
});
|
|
17099
|
-
|
|
17382
|
+
resolve7(true);
|
|
17100
17383
|
});
|
|
17101
17384
|
this.ws.on("message", (data) => {
|
|
17102
17385
|
try {
|
|
17103
17386
|
const msg = JSON.parse(data.toString());
|
|
17104
17387
|
if (msg.id && this.pending.has(msg.id)) {
|
|
17105
|
-
const { resolve:
|
|
17388
|
+
const { resolve: resolve8, reject } = this.pending.get(msg.id);
|
|
17106
17389
|
this.pending.delete(msg.id);
|
|
17107
17390
|
this.failureCount = 0;
|
|
17108
17391
|
if (msg.error) reject(new Error(msg.error.message));
|
|
17109
|
-
else
|
|
17392
|
+
else resolve8(msg.result);
|
|
17110
17393
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
17111
17394
|
this.contexts.add(msg.params.context.id);
|
|
17112
17395
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -17129,7 +17412,7 @@ var require_dist = __commonJS({
|
|
|
17129
17412
|
this.ws.on("error", (err) => {
|
|
17130
17413
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
17131
17414
|
this._connected = false;
|
|
17132
|
-
|
|
17415
|
+
resolve7(false);
|
|
17133
17416
|
});
|
|
17134
17417
|
});
|
|
17135
17418
|
}
|
|
@@ -17143,7 +17426,7 @@ var require_dist = __commonJS({
|
|
|
17143
17426
|
return;
|
|
17144
17427
|
}
|
|
17145
17428
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
17146
|
-
await new Promise((
|
|
17429
|
+
await new Promise((resolve7, reject) => {
|
|
17147
17430
|
this.browserWs = new import_ws2.default(browserWsUrl);
|
|
17148
17431
|
this.browserWs.on("open", async () => {
|
|
17149
17432
|
this._browserConnected = true;
|
|
@@ -17153,16 +17436,16 @@ var require_dist = __commonJS({
|
|
|
17153
17436
|
} catch (e) {
|
|
17154
17437
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
17155
17438
|
}
|
|
17156
|
-
|
|
17439
|
+
resolve7();
|
|
17157
17440
|
});
|
|
17158
17441
|
this.browserWs.on("message", (data) => {
|
|
17159
17442
|
try {
|
|
17160
17443
|
const msg = JSON.parse(data.toString());
|
|
17161
17444
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
17162
|
-
const { resolve:
|
|
17445
|
+
const { resolve: resolve8, reject: reject2 } = this.browserPending.get(msg.id);
|
|
17163
17446
|
this.browserPending.delete(msg.id);
|
|
17164
17447
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
17165
|
-
else
|
|
17448
|
+
else resolve8(msg.result);
|
|
17166
17449
|
}
|
|
17167
17450
|
} catch {
|
|
17168
17451
|
}
|
|
@@ -17182,31 +17465,31 @@ var require_dist = __commonJS({
|
|
|
17182
17465
|
}
|
|
17183
17466
|
}
|
|
17184
17467
|
getBrowserWsUrl() {
|
|
17185
|
-
return new Promise((
|
|
17468
|
+
return new Promise((resolve7) => {
|
|
17186
17469
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
17187
17470
|
let data = "";
|
|
17188
17471
|
res.on("data", (chunk) => data += chunk.toString());
|
|
17189
17472
|
res.on("end", () => {
|
|
17190
17473
|
try {
|
|
17191
17474
|
const info = JSON.parse(data);
|
|
17192
|
-
|
|
17475
|
+
resolve7(info.webSocketDebuggerUrl || null);
|
|
17193
17476
|
} catch {
|
|
17194
|
-
|
|
17477
|
+
resolve7(null);
|
|
17195
17478
|
}
|
|
17196
17479
|
});
|
|
17197
17480
|
});
|
|
17198
|
-
req.on("error", () =>
|
|
17481
|
+
req.on("error", () => resolve7(null));
|
|
17199
17482
|
req.setTimeout(3e3, () => {
|
|
17200
17483
|
req.destroy();
|
|
17201
|
-
|
|
17484
|
+
resolve7(null);
|
|
17202
17485
|
});
|
|
17203
17486
|
});
|
|
17204
17487
|
}
|
|
17205
17488
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
17206
|
-
return new Promise((
|
|
17489
|
+
return new Promise((resolve7, reject) => {
|
|
17207
17490
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
17208
17491
|
const id = this.browserMsgId++;
|
|
17209
|
-
this.browserPending.set(id, { resolve:
|
|
17492
|
+
this.browserPending.set(id, { resolve: resolve7, reject });
|
|
17210
17493
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
17211
17494
|
setTimeout(() => {
|
|
17212
17495
|
if (this.browserPending.has(id)) {
|
|
@@ -17246,11 +17529,11 @@ var require_dist = __commonJS({
|
|
|
17246
17529
|
}
|
|
17247
17530
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
17248
17531
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
17249
|
-
return new Promise((
|
|
17532
|
+
return new Promise((resolve7, reject) => {
|
|
17250
17533
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
17251
17534
|
if (this.ws.readyState !== import_ws2.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
17252
17535
|
const id = this.msgId++;
|
|
17253
|
-
this.pending.set(id, { resolve:
|
|
17536
|
+
this.pending.set(id, { resolve: resolve7, reject });
|
|
17254
17537
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
17255
17538
|
setTimeout(() => {
|
|
17256
17539
|
if (this.pending.has(id)) {
|
|
@@ -17459,7 +17742,7 @@ var require_dist = __commonJS({
|
|
|
17459
17742
|
const browserWs = this.browserWs;
|
|
17460
17743
|
let msgId = this.browserMsgId;
|
|
17461
17744
|
const sendWs = (method, params = {}, sessionId) => {
|
|
17462
|
-
return new Promise((
|
|
17745
|
+
return new Promise((resolve7, reject) => {
|
|
17463
17746
|
const mid = msgId++;
|
|
17464
17747
|
this.browserMsgId = msgId;
|
|
17465
17748
|
const handler = (raw) => {
|
|
@@ -17468,7 +17751,7 @@ var require_dist = __commonJS({
|
|
|
17468
17751
|
if (msg.id === mid) {
|
|
17469
17752
|
browserWs.removeListener("message", handler);
|
|
17470
17753
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
17471
|
-
else
|
|
17754
|
+
else resolve7(msg.result);
|
|
17472
17755
|
}
|
|
17473
17756
|
} catch {
|
|
17474
17757
|
}
|
|
@@ -17642,14 +17925,14 @@ var require_dist = __commonJS({
|
|
|
17642
17925
|
if (!ws || ws.readyState !== import_ws2.default.OPEN) {
|
|
17643
17926
|
throw new Error("CDP not connected");
|
|
17644
17927
|
}
|
|
17645
|
-
return new Promise((
|
|
17928
|
+
return new Promise((resolve7, reject) => {
|
|
17646
17929
|
const id = getNextId();
|
|
17647
17930
|
pendingMap.set(id, {
|
|
17648
17931
|
resolve: (result) => {
|
|
17649
17932
|
if (result?.result?.subtype === "error") {
|
|
17650
17933
|
reject(new Error(result.result.description));
|
|
17651
17934
|
} else {
|
|
17652
|
-
|
|
17935
|
+
resolve7(result?.result?.value);
|
|
17653
17936
|
}
|
|
17654
17937
|
},
|
|
17655
17938
|
reject
|
|
@@ -18220,10 +18503,10 @@ var require_dist = __commonJS({
|
|
|
18220
18503
|
return events;
|
|
18221
18504
|
}
|
|
18222
18505
|
};
|
|
18223
|
-
var
|
|
18224
|
-
var
|
|
18225
|
-
var
|
|
18226
|
-
var HISTORY_DIR =
|
|
18506
|
+
var fs32 = __toESM2(require("fs"));
|
|
18507
|
+
var path4 = __toESM2(require("path"));
|
|
18508
|
+
var os5 = __toESM2(require("os"));
|
|
18509
|
+
var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
|
|
18227
18510
|
var RETAIN_DAYS = 30;
|
|
18228
18511
|
var ChatHistoryWriter = class {
|
|
18229
18512
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -18264,13 +18547,13 @@ var require_dist = __commonJS({
|
|
|
18264
18547
|
});
|
|
18265
18548
|
}
|
|
18266
18549
|
if (newMessages.length === 0) return;
|
|
18267
|
-
const dir =
|
|
18268
|
-
|
|
18550
|
+
const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
|
|
18551
|
+
fs32.mkdirSync(dir, { recursive: true });
|
|
18269
18552
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
18270
18553
|
const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
|
|
18271
|
-
const filePath =
|
|
18554
|
+
const filePath = path4.join(dir, `${filePrefix}${date5}.jsonl`);
|
|
18272
18555
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
18273
|
-
|
|
18556
|
+
fs32.appendFileSync(filePath, lines, "utf-8");
|
|
18274
18557
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
18275
18558
|
if (messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
18276
18559
|
seenHashes.clear();
|
|
@@ -18295,17 +18578,17 @@ var require_dist = __commonJS({
|
|
|
18295
18578
|
/** Delete history files older than 30 days */
|
|
18296
18579
|
async rotateOldFiles() {
|
|
18297
18580
|
try {
|
|
18298
|
-
if (!
|
|
18581
|
+
if (!fs32.existsSync(HISTORY_DIR)) return;
|
|
18299
18582
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
18300
|
-
const agentDirs =
|
|
18583
|
+
const agentDirs = fs32.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
18301
18584
|
for (const dir of agentDirs) {
|
|
18302
|
-
const dirPath =
|
|
18303
|
-
const files =
|
|
18585
|
+
const dirPath = path4.join(HISTORY_DIR, dir.name);
|
|
18586
|
+
const files = fs32.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
18304
18587
|
for (const file2 of files) {
|
|
18305
|
-
const filePath =
|
|
18306
|
-
const stat =
|
|
18588
|
+
const filePath = path4.join(dirPath, file2);
|
|
18589
|
+
const stat = fs32.statSync(filePath);
|
|
18307
18590
|
if (stat.mtimeMs < cutoff) {
|
|
18308
|
-
|
|
18591
|
+
fs32.unlinkSync(filePath);
|
|
18309
18592
|
}
|
|
18310
18593
|
}
|
|
18311
18594
|
}
|
|
@@ -18320,10 +18603,10 @@ var require_dist = __commonJS({
|
|
|
18320
18603
|
function readChatHistory2(agentType, offset = 0, limit = 30, instanceId) {
|
|
18321
18604
|
try {
|
|
18322
18605
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
18323
|
-
const dir =
|
|
18324
|
-
if (!
|
|
18606
|
+
const dir = path4.join(HISTORY_DIR, sanitized);
|
|
18607
|
+
if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
|
|
18325
18608
|
const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
18326
|
-
const files =
|
|
18609
|
+
const files = fs32.readdirSync(dir).filter((f) => {
|
|
18327
18610
|
if (!f.endsWith(".jsonl")) return false;
|
|
18328
18611
|
if (sanitizedInstance) {
|
|
18329
18612
|
return f.startsWith(`${sanitizedInstance}_`);
|
|
@@ -18334,8 +18617,8 @@ var require_dist = __commonJS({
|
|
|
18334
18617
|
const needed = offset + limit + 1;
|
|
18335
18618
|
for (const file2 of files) {
|
|
18336
18619
|
if (allMessages.length >= needed) break;
|
|
18337
|
-
const filePath =
|
|
18338
|
-
const content =
|
|
18620
|
+
const filePath = path4.join(dir, file2);
|
|
18621
|
+
const content = fs32.readFileSync(filePath, "utf-8");
|
|
18339
18622
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
18340
18623
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
18341
18624
|
if (allMessages.length >= needed) break;
|
|
@@ -18573,6 +18856,15 @@ var require_dist = __commonJS({
|
|
|
18573
18856
|
const h = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
|
|
18574
18857
|
msg.receivedAt = prevByHash.get(h) || now;
|
|
18575
18858
|
}
|
|
18859
|
+
if (raw.messages?.length > 0) {
|
|
18860
|
+
const hiddenKinds = /* @__PURE__ */ new Set();
|
|
18861
|
+
if (this.settings.showThinking === false) hiddenKinds.add("thought");
|
|
18862
|
+
if (this.settings.showToolCalls === false) hiddenKinds.add("tool");
|
|
18863
|
+
if (this.settings.showTerminal === false) hiddenKinds.add("terminal");
|
|
18864
|
+
if (hiddenKinds.size > 0) {
|
|
18865
|
+
raw.messages = raw.messages.filter((m) => !hiddenKinds.has(m.kind));
|
|
18866
|
+
}
|
|
18867
|
+
}
|
|
18576
18868
|
this.cachedChat = { ...raw, activeModal };
|
|
18577
18869
|
this.detectAgentTransitions(raw, now);
|
|
18578
18870
|
if (raw.messages?.length > 0) {
|
|
@@ -19581,6 +19873,39 @@ var require_dist = __commonJS({
|
|
|
19581
19873
|
const action = args?.action || "approve";
|
|
19582
19874
|
const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
|
|
19583
19875
|
LOG5.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider2?.type}`);
|
|
19876
|
+
if (provider2?.category === "cli") {
|
|
19877
|
+
const adapter = h.getCliAdapter(provider2.type);
|
|
19878
|
+
if (!adapter) return { success: false, error: "CLI adapter not running" };
|
|
19879
|
+
const status = adapter.getStatus?.();
|
|
19880
|
+
if (status?.status !== "waiting_approval") {
|
|
19881
|
+
return { success: false, error: "Not in approval state" };
|
|
19882
|
+
}
|
|
19883
|
+
const buttons = status.activeModal?.buttons || ["Allow once", "Always allow", "Deny"];
|
|
19884
|
+
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
19885
|
+
if (buttonIndex < 0) {
|
|
19886
|
+
const btnLower = button.toLowerCase();
|
|
19887
|
+
buttonIndex = buttons.findIndex((b) => b.toLowerCase().includes(btnLower));
|
|
19888
|
+
}
|
|
19889
|
+
if (buttonIndex < 0) {
|
|
19890
|
+
if (action === "reject" || action === "deny") {
|
|
19891
|
+
buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
|
|
19892
|
+
if (buttonIndex < 0) buttonIndex = buttons.length - 1;
|
|
19893
|
+
} else if (action === "always" || /always/i.test(button)) {
|
|
19894
|
+
buttonIndex = buttons.findIndex((b) => /always/i.test(b));
|
|
19895
|
+
if (buttonIndex < 0) buttonIndex = 1;
|
|
19896
|
+
} else {
|
|
19897
|
+
buttonIndex = 0;
|
|
19898
|
+
}
|
|
19899
|
+
}
|
|
19900
|
+
if (typeof adapter.resolveModal === "function") {
|
|
19901
|
+
adapter.resolveModal(buttonIndex);
|
|
19902
|
+
} else {
|
|
19903
|
+
const keys = "\x1B[B".repeat(Math.max(0, buttonIndex)) + "\r";
|
|
19904
|
+
adapter.writeRaw?.(keys);
|
|
19905
|
+
}
|
|
19906
|
+
LOG5.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
19907
|
+
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
19908
|
+
}
|
|
19584
19909
|
if (provider2?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
19585
19910
|
const ok = await h.agentStream.resolveAgentAction(
|
|
19586
19911
|
h.getCdp(),
|
|
@@ -19665,9 +19990,9 @@ var require_dist = __commonJS({
|
|
|
19665
19990
|
}
|
|
19666
19991
|
return { success: false, error: "resolveAction script not available for this provider" };
|
|
19667
19992
|
}
|
|
19668
|
-
var
|
|
19669
|
-
var
|
|
19670
|
-
var
|
|
19993
|
+
var fs4 = __toESM2(require("fs"));
|
|
19994
|
+
var path5 = __toESM2(require("path"));
|
|
19995
|
+
var os6 = __toESM2(require("os"));
|
|
19671
19996
|
async function handleCdpEval(h, args) {
|
|
19672
19997
|
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
19673
19998
|
const expression = args?.expression || args?.script;
|
|
@@ -19819,21 +20144,21 @@ var require_dist = __commonJS({
|
|
|
19819
20144
|
return { success: true, agents };
|
|
19820
20145
|
}
|
|
19821
20146
|
function resolveSafePath(requestedPath) {
|
|
19822
|
-
const home =
|
|
20147
|
+
const home = os6.homedir();
|
|
19823
20148
|
let resolved;
|
|
19824
20149
|
if (requestedPath.startsWith("~")) {
|
|
19825
|
-
resolved =
|
|
19826
|
-
} else if (
|
|
20150
|
+
resolved = path5.join(home, requestedPath.slice(1));
|
|
20151
|
+
} else if (path5.isAbsolute(requestedPath)) {
|
|
19827
20152
|
resolved = requestedPath;
|
|
19828
20153
|
} else {
|
|
19829
|
-
resolved =
|
|
20154
|
+
resolved = path5.resolve(requestedPath);
|
|
19830
20155
|
}
|
|
19831
20156
|
return resolved;
|
|
19832
20157
|
}
|
|
19833
20158
|
async function handleFileRead(h, args) {
|
|
19834
20159
|
try {
|
|
19835
20160
|
const filePath = resolveSafePath(args?.path);
|
|
19836
|
-
const content =
|
|
20161
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
19837
20162
|
return { success: true, content, path: filePath };
|
|
19838
20163
|
} catch (e) {
|
|
19839
20164
|
return { success: false, error: e.message };
|
|
@@ -19842,8 +20167,8 @@ var require_dist = __commonJS({
|
|
|
19842
20167
|
async function handleFileWrite(h, args) {
|
|
19843
20168
|
try {
|
|
19844
20169
|
const filePath = resolveSafePath(args?.path);
|
|
19845
|
-
|
|
19846
|
-
|
|
20170
|
+
fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
20171
|
+
fs4.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
19847
20172
|
return { success: true, path: filePath };
|
|
19848
20173
|
} catch (e) {
|
|
19849
20174
|
return { success: false, error: e.message };
|
|
@@ -19852,11 +20177,11 @@ var require_dist = __commonJS({
|
|
|
19852
20177
|
async function handleFileList(h, args) {
|
|
19853
20178
|
try {
|
|
19854
20179
|
const dirPath = resolveSafePath(args?.path || ".");
|
|
19855
|
-
const entries =
|
|
20180
|
+
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
19856
20181
|
const files = entries.map((e) => ({
|
|
19857
20182
|
name: e.name,
|
|
19858
20183
|
type: e.isDirectory() ? "directory" : "file",
|
|
19859
|
-
size: e.isFile() ?
|
|
20184
|
+
size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
|
|
19860
20185
|
}));
|
|
19861
20186
|
return { success: true, files, path: dirPath };
|
|
19862
20187
|
} catch (e) {
|
|
@@ -20143,6 +20468,92 @@ var require_dist = __commonJS({
|
|
|
20143
20468
|
}
|
|
20144
20469
|
return { success: false, error: "Failed to save setting" };
|
|
20145
20470
|
}
|
|
20471
|
+
init_config();
|
|
20472
|
+
init_workspaces();
|
|
20473
|
+
function handleWorkspaceList() {
|
|
20474
|
+
const config2 = loadConfig4();
|
|
20475
|
+
const state = getWorkspaceState(config2);
|
|
20476
|
+
return {
|
|
20477
|
+
success: true,
|
|
20478
|
+
workspaces: state.workspaces,
|
|
20479
|
+
defaultWorkspaceId: state.defaultWorkspaceId,
|
|
20480
|
+
defaultWorkspacePath: state.defaultWorkspacePath,
|
|
20481
|
+
legacyRecentPaths: config2.recentCliWorkspaces || [],
|
|
20482
|
+
activity: getWorkspaceActivity(config2, 25)
|
|
20483
|
+
};
|
|
20484
|
+
}
|
|
20485
|
+
function handleWorkspaceAdd(args) {
|
|
20486
|
+
const rawPath = (args?.path || args?.dir || "").trim();
|
|
20487
|
+
const label = (args?.label || "").trim() || void 0;
|
|
20488
|
+
if (!rawPath) return { success: false, error: "path required" };
|
|
20489
|
+
const config2 = loadConfig4();
|
|
20490
|
+
const result = addWorkspaceEntry(config2, rawPath, label);
|
|
20491
|
+
if ("error" in result) return { success: false, error: result.error };
|
|
20492
|
+
let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
|
|
20493
|
+
saveConfig2(cfg);
|
|
20494
|
+
const state = getWorkspaceState(cfg);
|
|
20495
|
+
return { success: true, entry: result.entry, ...state, activity: getWorkspaceActivity(cfg, 25) };
|
|
20496
|
+
}
|
|
20497
|
+
function handleWorkspaceRemove(args) {
|
|
20498
|
+
const id = (args?.id || "").trim();
|
|
20499
|
+
if (!id) return { success: false, error: "id required" };
|
|
20500
|
+
const config2 = loadConfig4();
|
|
20501
|
+
const removed = (config2.workspaces || []).find((w) => w.id === id);
|
|
20502
|
+
const result = removeWorkspaceEntry(config2, id);
|
|
20503
|
+
if ("error" in result) return { success: false, error: result.error };
|
|
20504
|
+
let cfg = result.config;
|
|
20505
|
+
if (removed) {
|
|
20506
|
+
cfg = removeActivityForPath(cfg, removed.path);
|
|
20507
|
+
}
|
|
20508
|
+
saveConfig2(cfg);
|
|
20509
|
+
const state = getWorkspaceState(cfg);
|
|
20510
|
+
return { success: true, removedId: id, ...state, activity: getWorkspaceActivity(cfg, 25) };
|
|
20511
|
+
}
|
|
20512
|
+
function handleWorkspaceSetDefault(args) {
|
|
20513
|
+
const clear = args?.clear === true || args?.id === null || args?.id === "";
|
|
20514
|
+
if (clear) {
|
|
20515
|
+
const config22 = loadConfig4();
|
|
20516
|
+
const result2 = setDefaultWorkspaceId(config22, null);
|
|
20517
|
+
if ("error" in result2) return { success: false, error: result2.error };
|
|
20518
|
+
saveConfig2(result2.config);
|
|
20519
|
+
const state2 = getWorkspaceState(result2.config);
|
|
20520
|
+
return {
|
|
20521
|
+
success: true,
|
|
20522
|
+
...state2,
|
|
20523
|
+
activity: getWorkspaceActivity(result2.config, 25)
|
|
20524
|
+
};
|
|
20525
|
+
}
|
|
20526
|
+
const pathArg = args?.path != null && String(args.path).trim() ? String(args.path).trim() : "";
|
|
20527
|
+
const idArg = args?.id !== void 0 && args?.id !== null && String(args.id).trim() ? String(args.id).trim() : "";
|
|
20528
|
+
if (!pathArg && !idArg) {
|
|
20529
|
+
return { success: false, error: "id or path required (or clear: true)" };
|
|
20530
|
+
}
|
|
20531
|
+
let config2 = loadConfig4();
|
|
20532
|
+
let nextId;
|
|
20533
|
+
if (pathArg) {
|
|
20534
|
+
let w = findWorkspaceByPath(config2, pathArg);
|
|
20535
|
+
if (!w) {
|
|
20536
|
+
const add = addWorkspaceEntry(config2, pathArg);
|
|
20537
|
+
if ("error" in add) return { success: false, error: add.error };
|
|
20538
|
+
config2 = add.config;
|
|
20539
|
+
w = add.entry;
|
|
20540
|
+
}
|
|
20541
|
+
nextId = w.id;
|
|
20542
|
+
} else {
|
|
20543
|
+
nextId = idArg;
|
|
20544
|
+
}
|
|
20545
|
+
const result = setDefaultWorkspaceId(config2, nextId);
|
|
20546
|
+
if ("error" in result) return { success: false, error: result.error };
|
|
20547
|
+
let out = result.config;
|
|
20548
|
+
const ap = getDefaultWorkspacePath(out);
|
|
20549
|
+
if (ap) {
|
|
20550
|
+
out = appendWorkspaceActivity(out, ap, { kind: "default" });
|
|
20551
|
+
}
|
|
20552
|
+
saveConfig2(out);
|
|
20553
|
+
const state = getWorkspaceState(out);
|
|
20554
|
+
return { success: true, ...state, activity: getWorkspaceActivity(out, 25) };
|
|
20555
|
+
}
|
|
20556
|
+
init_workspaces();
|
|
20146
20557
|
var DaemonCommandHandler = class {
|
|
20147
20558
|
_ctx;
|
|
20148
20559
|
_agentStream = null;
|
|
@@ -20251,6 +20662,9 @@ var require_dist = __commonJS({
|
|
|
20251
20662
|
}
|
|
20252
20663
|
/** Extract ideType from _targetInstance */
|
|
20253
20664
|
extractIdeType(args) {
|
|
20665
|
+
if (args?.ideType && this._ctx.cdpManagers.has(args.ideType)) {
|
|
20666
|
+
return args.ideType;
|
|
20667
|
+
}
|
|
20254
20668
|
if (args?._targetInstance) {
|
|
20255
20669
|
let raw = args._targetInstance;
|
|
20256
20670
|
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
@@ -20262,8 +20676,19 @@ var require_dist = __commonJS({
|
|
|
20262
20676
|
if (this._ctx.instanceIdMap?.has(raw)) {
|
|
20263
20677
|
return this._ctx.instanceIdMap.get(raw);
|
|
20264
20678
|
}
|
|
20679
|
+
if (this._ctx.cdpManagers.has(raw)) {
|
|
20680
|
+
return raw;
|
|
20681
|
+
}
|
|
20682
|
+
if (!ideMatch && !cliMatch && !acpMatch) {
|
|
20683
|
+
for (const [key, mgr] of this._ctx.cdpManagers.entries()) {
|
|
20684
|
+
if (mgr.isConnected) return key;
|
|
20685
|
+
}
|
|
20686
|
+
}
|
|
20265
20687
|
const lastUnderscore = raw.lastIndexOf("_");
|
|
20266
|
-
if (lastUnderscore > 0)
|
|
20688
|
+
if (lastUnderscore > 0) {
|
|
20689
|
+
const stripped = raw.substring(0, lastUnderscore);
|
|
20690
|
+
if (this._ctx.cdpManagers.has(stripped)) return stripped;
|
|
20691
|
+
}
|
|
20267
20692
|
return raw;
|
|
20268
20693
|
}
|
|
20269
20694
|
return void 0;
|
|
@@ -20359,6 +20784,19 @@ var require_dist = __commonJS({
|
|
|
20359
20784
|
return { success: false, error: `${cmd} requires bridge-extension (removed)` };
|
|
20360
20785
|
case "get_recent_workspaces":
|
|
20361
20786
|
return this.handleGetRecentWorkspaces(args);
|
|
20787
|
+
case "get_cli_history": {
|
|
20788
|
+
const config2 = loadConfig4();
|
|
20789
|
+
return { success: true, history: config2.cliHistory || [] };
|
|
20790
|
+
}
|
|
20791
|
+
case "workspace_list":
|
|
20792
|
+
return handleWorkspaceList();
|
|
20793
|
+
case "workspace_add":
|
|
20794
|
+
return handleWorkspaceAdd(args);
|
|
20795
|
+
case "workspace_remove":
|
|
20796
|
+
return handleWorkspaceRemove(args);
|
|
20797
|
+
case "workspace_set_default":
|
|
20798
|
+
case "workspace_set_active":
|
|
20799
|
+
return handleWorkspaceSetDefault(args);
|
|
20362
20800
|
// ─── Script manage ───────────────────
|
|
20363
20801
|
case "refresh_scripts":
|
|
20364
20802
|
return this.handleRefreshScripts(args);
|
|
@@ -20408,10 +20846,18 @@ var require_dist = __commonJS({
|
|
|
20408
20846
|
}
|
|
20409
20847
|
}
|
|
20410
20848
|
// ─── Misc (kept in handler — too small to extract) ───────
|
|
20411
|
-
async handleGetRecentWorkspaces(
|
|
20849
|
+
async handleGetRecentWorkspaces(_args) {
|
|
20412
20850
|
const config2 = loadConfig4();
|
|
20413
20851
|
const cliRecent = config2.recentCliWorkspaces || [];
|
|
20414
|
-
|
|
20852
|
+
const ws = getWorkspaceState(config2);
|
|
20853
|
+
return {
|
|
20854
|
+
success: true,
|
|
20855
|
+
result: cliRecent,
|
|
20856
|
+
workspaces: ws.workspaces,
|
|
20857
|
+
defaultWorkspaceId: ws.defaultWorkspaceId,
|
|
20858
|
+
defaultWorkspacePath: ws.defaultWorkspacePath,
|
|
20859
|
+
activity: getWorkspaceActivity(config2, 25)
|
|
20860
|
+
};
|
|
20415
20861
|
}
|
|
20416
20862
|
async handleRefreshScripts(_args) {
|
|
20417
20863
|
if (this._ctx.providerLoader) {
|
|
@@ -20421,13 +20867,13 @@ var require_dist = __commonJS({
|
|
|
20421
20867
|
return { success: false, error: "ProviderLoader not initialized" };
|
|
20422
20868
|
}
|
|
20423
20869
|
};
|
|
20424
|
-
var
|
|
20870
|
+
var import_child_process4 = require("child_process");
|
|
20425
20871
|
var net = __toESM2(require("net"));
|
|
20426
|
-
var
|
|
20427
|
-
var
|
|
20428
|
-
var
|
|
20429
|
-
var
|
|
20430
|
-
var
|
|
20872
|
+
var os8 = __toESM2(require("os"));
|
|
20873
|
+
var path7 = __toESM2(require("path"));
|
|
20874
|
+
var fs5 = __toESM2(require("fs"));
|
|
20875
|
+
var path6 = __toESM2(require("path"));
|
|
20876
|
+
var os7 = __toESM2(require("os"));
|
|
20431
20877
|
var ProviderLoader3 = class _ProviderLoader {
|
|
20432
20878
|
providers = /* @__PURE__ */ new Map();
|
|
20433
20879
|
builtinDirs;
|
|
@@ -20447,10 +20893,10 @@ var require_dist = __commonJS({
|
|
|
20447
20893
|
if (options?.builtinDir) {
|
|
20448
20894
|
this.builtinDirs = Array.isArray(options.builtinDir) ? options.builtinDir : [options.builtinDir];
|
|
20449
20895
|
} else {
|
|
20450
|
-
this.builtinDirs = [
|
|
20896
|
+
this.builtinDirs = [path6.resolve(__dirname, "../providers/_builtin")];
|
|
20451
20897
|
}
|
|
20452
|
-
this.userDir = options?.userDir ||
|
|
20453
|
-
this.upstreamDir =
|
|
20898
|
+
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
20899
|
+
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
20454
20900
|
this.logFn = options?.logFn || LOG5.forComponent("Provider").asLogFn();
|
|
20455
20901
|
}
|
|
20456
20902
|
log(msg) {
|
|
@@ -20468,19 +20914,19 @@ var require_dist = __commonJS({
|
|
|
20468
20914
|
this.providers.clear();
|
|
20469
20915
|
let builtinCount = 0;
|
|
20470
20916
|
for (const dir of this.builtinDirs) {
|
|
20471
|
-
if (
|
|
20917
|
+
if (fs5.existsSync(dir)) {
|
|
20472
20918
|
builtinCount += this.loadDir(dir);
|
|
20473
20919
|
}
|
|
20474
20920
|
}
|
|
20475
20921
|
this.log(`Loaded ${builtinCount} builtin providers`);
|
|
20476
20922
|
let upstreamCount = 0;
|
|
20477
|
-
if (
|
|
20923
|
+
if (fs5.existsSync(this.upstreamDir)) {
|
|
20478
20924
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
20479
20925
|
if (upstreamCount > 0) {
|
|
20480
20926
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
20481
20927
|
}
|
|
20482
20928
|
}
|
|
20483
|
-
if (
|
|
20929
|
+
if (fs5.existsSync(this.userDir)) {
|
|
20484
20930
|
const userCount = this.loadDir(this.userDir, [".upstream"]);
|
|
20485
20931
|
if (userCount > 0) {
|
|
20486
20932
|
this.log(`Loaded ${userCount} user custom providers (never auto-updated)`);
|
|
@@ -20784,15 +21230,15 @@ var require_dist = __commonJS({
|
|
|
20784
21230
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
20785
21231
|
return null;
|
|
20786
21232
|
}
|
|
20787
|
-
const dir =
|
|
20788
|
-
if (!
|
|
21233
|
+
const dir = path6.join(providerDir, scriptDir);
|
|
21234
|
+
if (!fs5.existsSync(dir)) {
|
|
20789
21235
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
20790
21236
|
return null;
|
|
20791
21237
|
}
|
|
20792
21238
|
const cached2 = this.scriptsCache.get(dir);
|
|
20793
21239
|
if (cached2) return cached2;
|
|
20794
|
-
const scriptsJs =
|
|
20795
|
-
if (
|
|
21240
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
21241
|
+
if (fs5.existsSync(scriptsJs)) {
|
|
20796
21242
|
try {
|
|
20797
21243
|
delete require.cache[require.resolve(scriptsJs)];
|
|
20798
21244
|
const loaded = require(scriptsJs);
|
|
@@ -20814,15 +21260,15 @@ var require_dist = __commonJS({
|
|
|
20814
21260
|
watch() {
|
|
20815
21261
|
this.stopWatch();
|
|
20816
21262
|
const watchDir = (dir) => {
|
|
20817
|
-
if (!
|
|
21263
|
+
if (!fs5.existsSync(dir)) {
|
|
20818
21264
|
try {
|
|
20819
|
-
|
|
21265
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
20820
21266
|
} catch {
|
|
20821
21267
|
return;
|
|
20822
21268
|
}
|
|
20823
21269
|
}
|
|
20824
21270
|
try {
|
|
20825
|
-
const watcher =
|
|
21271
|
+
const watcher = fs5.watch(dir, { recursive: true }, (event, filename) => {
|
|
20826
21272
|
if (filename?.endsWith(".js") || filename?.endsWith(".json")) {
|
|
20827
21273
|
this.log(`File changed: ${filename}, reloading...`);
|
|
20828
21274
|
this.loadAll();
|
|
@@ -20872,13 +21318,13 @@ var require_dist = __commonJS({
|
|
|
20872
21318
|
*/
|
|
20873
21319
|
async fetchLatest() {
|
|
20874
21320
|
const https = require("https");
|
|
20875
|
-
const { execSync:
|
|
20876
|
-
const metaPath =
|
|
21321
|
+
const { execSync: execSync7 } = require("child_process");
|
|
21322
|
+
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
20877
21323
|
let prevEtag = "";
|
|
20878
21324
|
let prevTimestamp = 0;
|
|
20879
21325
|
try {
|
|
20880
|
-
if (
|
|
20881
|
-
const meta3 = JSON.parse(
|
|
21326
|
+
if (fs5.existsSync(metaPath)) {
|
|
21327
|
+
const meta3 = JSON.parse(fs5.readFileSync(metaPath, "utf-8"));
|
|
20882
21328
|
prevEtag = meta3.etag || "";
|
|
20883
21329
|
prevTimestamp = meta3.timestamp || 0;
|
|
20884
21330
|
}
|
|
@@ -20890,7 +21336,7 @@ var require_dist = __commonJS({
|
|
|
20890
21336
|
return { updated: false };
|
|
20891
21337
|
}
|
|
20892
21338
|
try {
|
|
20893
|
-
const etag = await new Promise((
|
|
21339
|
+
const etag = await new Promise((resolve7, reject) => {
|
|
20894
21340
|
const options = {
|
|
20895
21341
|
method: "HEAD",
|
|
20896
21342
|
hostname: "github.com",
|
|
@@ -20908,7 +21354,7 @@ var require_dist = __commonJS({
|
|
|
20908
21354
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
20909
21355
|
timeout: 1e4
|
|
20910
21356
|
}, (res2) => {
|
|
20911
|
-
|
|
21357
|
+
resolve7(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
20912
21358
|
});
|
|
20913
21359
|
req2.on("error", reject);
|
|
20914
21360
|
req2.on("timeout", () => {
|
|
@@ -20917,7 +21363,7 @@ var require_dist = __commonJS({
|
|
|
20917
21363
|
});
|
|
20918
21364
|
req2.end();
|
|
20919
21365
|
} else {
|
|
20920
|
-
|
|
21366
|
+
resolve7(res.headers.etag || res.headers["last-modified"] || "");
|
|
20921
21367
|
}
|
|
20922
21368
|
});
|
|
20923
21369
|
req.on("error", reject);
|
|
@@ -20933,39 +21379,39 @@ var require_dist = __commonJS({
|
|
|
20933
21379
|
return { updated: false };
|
|
20934
21380
|
}
|
|
20935
21381
|
this.log("Downloading latest providers from GitHub...");
|
|
20936
|
-
const tmpTar =
|
|
20937
|
-
const tmpExtract =
|
|
21382
|
+
const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
21383
|
+
const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
20938
21384
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
20939
|
-
|
|
20940
|
-
|
|
20941
|
-
const extracted =
|
|
21385
|
+
fs5.mkdirSync(tmpExtract, { recursive: true });
|
|
21386
|
+
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
21387
|
+
const extracted = fs5.readdirSync(tmpExtract);
|
|
20942
21388
|
const rootDir = extracted.find(
|
|
20943
|
-
(d) =>
|
|
21389
|
+
(d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
20944
21390
|
);
|
|
20945
21391
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
20946
|
-
const sourceDir =
|
|
21392
|
+
const sourceDir = path6.join(tmpExtract, rootDir);
|
|
20947
21393
|
const backupDir = this.upstreamDir + ".bak";
|
|
20948
|
-
if (
|
|
20949
|
-
if (
|
|
20950
|
-
|
|
21394
|
+
if (fs5.existsSync(this.upstreamDir)) {
|
|
21395
|
+
if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
|
|
21396
|
+
fs5.renameSync(this.upstreamDir, backupDir);
|
|
20951
21397
|
}
|
|
20952
21398
|
try {
|
|
20953
21399
|
this.copyDirRecursive(sourceDir, this.upstreamDir);
|
|
20954
21400
|
this.writeMeta(metaPath, etag || `ts-${Date.now()}`, Date.now());
|
|
20955
|
-
if (
|
|
21401
|
+
if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
|
|
20956
21402
|
} catch (e) {
|
|
20957
|
-
if (
|
|
20958
|
-
if (
|
|
20959
|
-
|
|
21403
|
+
if (fs5.existsSync(backupDir)) {
|
|
21404
|
+
if (fs5.existsSync(this.upstreamDir)) fs5.rmSync(this.upstreamDir, { recursive: true, force: true });
|
|
21405
|
+
fs5.renameSync(backupDir, this.upstreamDir);
|
|
20960
21406
|
}
|
|
20961
21407
|
throw e;
|
|
20962
21408
|
}
|
|
20963
21409
|
try {
|
|
20964
|
-
|
|
21410
|
+
fs5.rmSync(tmpTar, { force: true });
|
|
20965
21411
|
} catch {
|
|
20966
21412
|
}
|
|
20967
21413
|
try {
|
|
20968
|
-
|
|
21414
|
+
fs5.rmSync(tmpExtract, { recursive: true, force: true });
|
|
20969
21415
|
} catch {
|
|
20970
21416
|
}
|
|
20971
21417
|
const upstreamCount = this.countProviders(this.upstreamDir);
|
|
@@ -20981,7 +21427,7 @@ var require_dist = __commonJS({
|
|
|
20981
21427
|
downloadFile(url2, destPath) {
|
|
20982
21428
|
const https = require("https");
|
|
20983
21429
|
const http3 = require("http");
|
|
20984
|
-
return new Promise((
|
|
21430
|
+
return new Promise((resolve7, reject) => {
|
|
20985
21431
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
20986
21432
|
if (redirectCount > 5) {
|
|
20987
21433
|
reject(new Error("Too many redirects"));
|
|
@@ -20997,11 +21443,11 @@ var require_dist = __commonJS({
|
|
|
20997
21443
|
reject(new Error(`HTTP ${res.statusCode}`));
|
|
20998
21444
|
return;
|
|
20999
21445
|
}
|
|
21000
|
-
const ws =
|
|
21446
|
+
const ws = fs5.createWriteStream(destPath);
|
|
21001
21447
|
res.pipe(ws);
|
|
21002
21448
|
ws.on("finish", () => {
|
|
21003
21449
|
ws.close();
|
|
21004
|
-
|
|
21450
|
+
resolve7();
|
|
21005
21451
|
});
|
|
21006
21452
|
ws.on("error", reject);
|
|
21007
21453
|
});
|
|
@@ -21016,22 +21462,22 @@ var require_dist = __commonJS({
|
|
|
21016
21462
|
}
|
|
21017
21463
|
/** Recursive directory copy */
|
|
21018
21464
|
copyDirRecursive(src, dest) {
|
|
21019
|
-
|
|
21020
|
-
for (const entry of
|
|
21021
|
-
const srcPath =
|
|
21022
|
-
const destPath =
|
|
21465
|
+
fs5.mkdirSync(dest, { recursive: true });
|
|
21466
|
+
for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
|
|
21467
|
+
const srcPath = path6.join(src, entry.name);
|
|
21468
|
+
const destPath = path6.join(dest, entry.name);
|
|
21023
21469
|
if (entry.isDirectory()) {
|
|
21024
21470
|
this.copyDirRecursive(srcPath, destPath);
|
|
21025
21471
|
} else {
|
|
21026
|
-
|
|
21472
|
+
fs5.copyFileSync(srcPath, destPath);
|
|
21027
21473
|
}
|
|
21028
21474
|
}
|
|
21029
21475
|
}
|
|
21030
21476
|
/** .meta.json save */
|
|
21031
21477
|
writeMeta(metaPath, etag, timestamp) {
|
|
21032
21478
|
try {
|
|
21033
|
-
|
|
21034
|
-
|
|
21479
|
+
fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
|
|
21480
|
+
fs5.writeFileSync(metaPath, JSON.stringify({
|
|
21035
21481
|
etag,
|
|
21036
21482
|
timestamp,
|
|
21037
21483
|
lastCheck: new Date(timestamp).toISOString(),
|
|
@@ -21042,12 +21488,12 @@ var require_dist = __commonJS({
|
|
|
21042
21488
|
}
|
|
21043
21489
|
/** Count provider files (provider.js or provider.json) */
|
|
21044
21490
|
countProviders(dir) {
|
|
21045
|
-
if (!
|
|
21491
|
+
if (!fs5.existsSync(dir)) return 0;
|
|
21046
21492
|
let count = 0;
|
|
21047
21493
|
const scan = (d) => {
|
|
21048
21494
|
try {
|
|
21049
|
-
for (const entry of
|
|
21050
|
-
if (entry.isDirectory()) scan(
|
|
21495
|
+
for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
|
|
21496
|
+
if (entry.isDirectory()) scan(path6.join(d, entry.name));
|
|
21051
21497
|
else if (entry.name === "provider.json") count++;
|
|
21052
21498
|
}
|
|
21053
21499
|
} catch {
|
|
@@ -21144,20 +21590,20 @@ var require_dist = __commonJS({
|
|
|
21144
21590
|
const cat = provider2.category;
|
|
21145
21591
|
const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
|
|
21146
21592
|
for (const root of searchRoots) {
|
|
21147
|
-
if (!
|
|
21148
|
-
for (const candidate of [
|
|
21149
|
-
if (
|
|
21593
|
+
if (!fs5.existsSync(root)) continue;
|
|
21594
|
+
for (const candidate of [path6.join(root, type), path6.join(root, cat, type)]) {
|
|
21595
|
+
if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
|
|
21150
21596
|
}
|
|
21151
|
-
const catDir =
|
|
21152
|
-
if (
|
|
21597
|
+
const catDir = path6.join(root, cat);
|
|
21598
|
+
if (fs5.existsSync(catDir)) {
|
|
21153
21599
|
try {
|
|
21154
|
-
for (const entry of
|
|
21600
|
+
for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
|
|
21155
21601
|
if (!entry.isDirectory()) continue;
|
|
21156
|
-
const jsonPath =
|
|
21157
|
-
if (
|
|
21602
|
+
const jsonPath = path6.join(catDir, entry.name, "provider.json");
|
|
21603
|
+
if (fs5.existsSync(jsonPath)) {
|
|
21158
21604
|
try {
|
|
21159
|
-
const data = JSON.parse(
|
|
21160
|
-
if (data.type === type) return
|
|
21605
|
+
const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
|
|
21606
|
+
if (data.type === type) return path6.join(catDir, entry.name);
|
|
21161
21607
|
} catch {
|
|
21162
21608
|
}
|
|
21163
21609
|
}
|
|
@@ -21174,8 +21620,8 @@ var require_dist = __commonJS({
|
|
|
21174
21620
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
21175
21621
|
*/
|
|
21176
21622
|
buildScriptWrappersFromDir(dir) {
|
|
21177
|
-
const scriptsJs =
|
|
21178
|
-
if (
|
|
21623
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
21624
|
+
if (fs5.existsSync(scriptsJs)) {
|
|
21179
21625
|
try {
|
|
21180
21626
|
delete require.cache[require.resolve(scriptsJs)];
|
|
21181
21627
|
return require(scriptsJs);
|
|
@@ -21185,13 +21631,13 @@ var require_dist = __commonJS({
|
|
|
21185
21631
|
const toCamel = (name) => name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
21186
21632
|
const result = {};
|
|
21187
21633
|
try {
|
|
21188
|
-
for (const file2 of
|
|
21634
|
+
for (const file2 of fs5.readdirSync(dir)) {
|
|
21189
21635
|
if (!file2.endsWith(".js")) continue;
|
|
21190
21636
|
const scriptName = toCamel(file2.replace(".js", ""));
|
|
21191
|
-
const filePath =
|
|
21637
|
+
const filePath = path6.join(dir, file2);
|
|
21192
21638
|
result[scriptName] = (..._args) => {
|
|
21193
21639
|
try {
|
|
21194
|
-
return
|
|
21640
|
+
return fs5.readFileSync(filePath, "utf-8");
|
|
21195
21641
|
} catch {
|
|
21196
21642
|
return "";
|
|
21197
21643
|
}
|
|
@@ -21209,20 +21655,20 @@ var require_dist = __commonJS({
|
|
|
21209
21655
|
* Structure: dir/category/agent-name/provider.{json,js}
|
|
21210
21656
|
*/
|
|
21211
21657
|
loadDir(dir, excludeDirs) {
|
|
21212
|
-
if (!
|
|
21658
|
+
if (!fs5.existsSync(dir)) return 0;
|
|
21213
21659
|
let count = 0;
|
|
21214
21660
|
const scan = (d) => {
|
|
21215
21661
|
let entries;
|
|
21216
21662
|
try {
|
|
21217
|
-
entries =
|
|
21663
|
+
entries = fs5.readdirSync(d, { withFileTypes: true });
|
|
21218
21664
|
} catch {
|
|
21219
21665
|
return;
|
|
21220
21666
|
}
|
|
21221
21667
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
21222
21668
|
if (hasJson) {
|
|
21223
|
-
const jsonPath =
|
|
21669
|
+
const jsonPath = path6.join(d, "provider.json");
|
|
21224
21670
|
try {
|
|
21225
|
-
const raw =
|
|
21671
|
+
const raw = fs5.readFileSync(jsonPath, "utf-8");
|
|
21226
21672
|
const mod = JSON.parse(raw);
|
|
21227
21673
|
if (!mod.type || !mod.name || !mod.category) {
|
|
21228
21674
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: missing type/name/category`);
|
|
@@ -21233,8 +21679,8 @@ var require_dist = __commonJS({
|
|
|
21233
21679
|
delete mod.extensionIdPattern_flags;
|
|
21234
21680
|
}
|
|
21235
21681
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
21236
|
-
const scriptsPath =
|
|
21237
|
-
if (!hasCompatibility &&
|
|
21682
|
+
const scriptsPath = path6.join(d, "scripts.js");
|
|
21683
|
+
if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
|
|
21238
21684
|
try {
|
|
21239
21685
|
delete require.cache[require.resolve(scriptsPath)];
|
|
21240
21686
|
const scripts = require(scriptsPath);
|
|
@@ -21259,7 +21705,7 @@ var require_dist = __commonJS({
|
|
|
21259
21705
|
if (!entry.isDirectory()) continue;
|
|
21260
21706
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
21261
21707
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
21262
|
-
scan(
|
|
21708
|
+
scan(path6.join(d, entry.name));
|
|
21263
21709
|
}
|
|
21264
21710
|
}
|
|
21265
21711
|
};
|
|
@@ -21336,17 +21782,17 @@ var require_dist = __commonJS({
|
|
|
21336
21782
|
throw new Error("No free port found");
|
|
21337
21783
|
}
|
|
21338
21784
|
function checkPortFree(port) {
|
|
21339
|
-
return new Promise((
|
|
21785
|
+
return new Promise((resolve7) => {
|
|
21340
21786
|
const server = net.createServer();
|
|
21341
21787
|
server.unref();
|
|
21342
|
-
server.on("error", () =>
|
|
21788
|
+
server.on("error", () => resolve7(false));
|
|
21343
21789
|
server.listen(port, "127.0.0.1", () => {
|
|
21344
|
-
server.close(() =>
|
|
21790
|
+
server.close(() => resolve7(true));
|
|
21345
21791
|
});
|
|
21346
21792
|
});
|
|
21347
21793
|
}
|
|
21348
21794
|
async function isCdpActive(port) {
|
|
21349
|
-
return new Promise((
|
|
21795
|
+
return new Promise((resolve7) => {
|
|
21350
21796
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
21351
21797
|
timeout: 2e3
|
|
21352
21798
|
}, (res) => {
|
|
@@ -21355,52 +21801,52 @@ var require_dist = __commonJS({
|
|
|
21355
21801
|
res.on("end", () => {
|
|
21356
21802
|
try {
|
|
21357
21803
|
const info = JSON.parse(data);
|
|
21358
|
-
|
|
21804
|
+
resolve7(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
21359
21805
|
} catch {
|
|
21360
|
-
|
|
21806
|
+
resolve7(false);
|
|
21361
21807
|
}
|
|
21362
21808
|
});
|
|
21363
21809
|
});
|
|
21364
|
-
req.on("error", () =>
|
|
21810
|
+
req.on("error", () => resolve7(false));
|
|
21365
21811
|
req.on("timeout", () => {
|
|
21366
21812
|
req.destroy();
|
|
21367
|
-
|
|
21813
|
+
resolve7(false);
|
|
21368
21814
|
});
|
|
21369
21815
|
});
|
|
21370
21816
|
}
|
|
21371
21817
|
async function killIdeProcess(ideId) {
|
|
21372
|
-
const plat =
|
|
21818
|
+
const plat = os8.platform();
|
|
21373
21819
|
const appName = getMacAppIdentifiers()[ideId];
|
|
21374
21820
|
const winProcesses = getWinProcessNames()[ideId];
|
|
21375
21821
|
try {
|
|
21376
21822
|
if (plat === "darwin" && appName) {
|
|
21377
21823
|
try {
|
|
21378
|
-
(0,
|
|
21824
|
+
(0, import_child_process4.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
|
|
21379
21825
|
timeout: 5e3
|
|
21380
21826
|
});
|
|
21381
21827
|
} catch {
|
|
21382
21828
|
try {
|
|
21383
|
-
(0,
|
|
21829
|
+
(0, import_child_process4.execSync)(`pkill -f "${appName}" 2>/dev/null`);
|
|
21384
21830
|
} catch {
|
|
21385
21831
|
}
|
|
21386
21832
|
}
|
|
21387
21833
|
} else if (plat === "win32" && winProcesses) {
|
|
21388
21834
|
for (const proc of winProcesses) {
|
|
21389
21835
|
try {
|
|
21390
|
-
(0,
|
|
21836
|
+
(0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`, { timeout: 5e3 });
|
|
21391
21837
|
} catch {
|
|
21392
21838
|
}
|
|
21393
21839
|
}
|
|
21394
21840
|
try {
|
|
21395
21841
|
const exeName = winProcesses[0].replace(".exe", "");
|
|
21396
|
-
(0,
|
|
21842
|
+
(0, import_child_process4.execSync)(`powershell -Command "Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue | Stop-Process -Force"`, {
|
|
21397
21843
|
timeout: 1e4
|
|
21398
21844
|
});
|
|
21399
21845
|
} catch {
|
|
21400
21846
|
}
|
|
21401
21847
|
} else {
|
|
21402
21848
|
try {
|
|
21403
|
-
(0,
|
|
21849
|
+
(0, import_child_process4.execSync)(`pkill -f "${ideId}" 2>/dev/null`);
|
|
21404
21850
|
} catch {
|
|
21405
21851
|
}
|
|
21406
21852
|
}
|
|
@@ -21410,13 +21856,13 @@ var require_dist = __commonJS({
|
|
|
21410
21856
|
}
|
|
21411
21857
|
if (plat === "darwin" && appName) {
|
|
21412
21858
|
try {
|
|
21413
|
-
(0,
|
|
21859
|
+
(0, import_child_process4.execSync)(`pkill -9 -f "${appName}" 2>/dev/null`);
|
|
21414
21860
|
} catch {
|
|
21415
21861
|
}
|
|
21416
21862
|
} else if (plat === "win32" && winProcesses) {
|
|
21417
21863
|
for (const proc of winProcesses) {
|
|
21418
21864
|
try {
|
|
21419
|
-
(0,
|
|
21865
|
+
(0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`);
|
|
21420
21866
|
} catch {
|
|
21421
21867
|
}
|
|
21422
21868
|
}
|
|
@@ -21428,26 +21874,26 @@ var require_dist = __commonJS({
|
|
|
21428
21874
|
}
|
|
21429
21875
|
}
|
|
21430
21876
|
function isIdeRunning(ideId) {
|
|
21431
|
-
const plat =
|
|
21877
|
+
const plat = os8.platform();
|
|
21432
21878
|
try {
|
|
21433
21879
|
if (plat === "darwin") {
|
|
21434
21880
|
const appName = getMacAppIdentifiers()[ideId];
|
|
21435
21881
|
if (!appName) return false;
|
|
21436
|
-
const result = (0,
|
|
21882
|
+
const result = (0, import_child_process4.execSync)(`pgrep -f "${appName}" 2>/dev/null`, { encoding: "utf-8" });
|
|
21437
21883
|
return result.trim().length > 0;
|
|
21438
21884
|
} else if (plat === "win32") {
|
|
21439
21885
|
const winProcesses = getWinProcessNames()[ideId];
|
|
21440
21886
|
if (!winProcesses) return false;
|
|
21441
21887
|
for (const proc of winProcesses) {
|
|
21442
21888
|
try {
|
|
21443
|
-
const result = (0,
|
|
21889
|
+
const result = (0, import_child_process4.execSync)(`tasklist /FI "IMAGENAME eq ${proc}" /NH 2>nul`, { encoding: "utf-8" });
|
|
21444
21890
|
if (result.includes(proc)) return true;
|
|
21445
21891
|
} catch {
|
|
21446
21892
|
}
|
|
21447
21893
|
}
|
|
21448
21894
|
try {
|
|
21449
21895
|
const exeName = winProcesses[0].replace(".exe", "");
|
|
21450
|
-
const result = (0,
|
|
21896
|
+
const result = (0, import_child_process4.execSync)(
|
|
21451
21897
|
`powershell -Command "(Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue).Count"`,
|
|
21452
21898
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
21453
21899
|
);
|
|
@@ -21456,7 +21902,7 @@ var require_dist = __commonJS({
|
|
|
21456
21902
|
}
|
|
21457
21903
|
return false;
|
|
21458
21904
|
} else {
|
|
21459
|
-
const result = (0,
|
|
21905
|
+
const result = (0, import_child_process4.execSync)(`pgrep -f "${ideId}" 2>/dev/null`, { encoding: "utf-8" });
|
|
21460
21906
|
return result.trim().length > 0;
|
|
21461
21907
|
}
|
|
21462
21908
|
} catch {
|
|
@@ -21464,12 +21910,12 @@ var require_dist = __commonJS({
|
|
|
21464
21910
|
}
|
|
21465
21911
|
}
|
|
21466
21912
|
function detectCurrentWorkspace(ideId) {
|
|
21467
|
-
const plat =
|
|
21913
|
+
const plat = os8.platform();
|
|
21468
21914
|
if (plat === "darwin") {
|
|
21469
21915
|
try {
|
|
21470
21916
|
const appName = getMacAppIdentifiers()[ideId];
|
|
21471
21917
|
if (!appName) return void 0;
|
|
21472
|
-
const result = (0,
|
|
21918
|
+
const result = (0, import_child_process4.execSync)(
|
|
21473
21919
|
`lsof -c "${appName}" 2>/dev/null | grep cwd | head -1 | awk '{print $NF}'`,
|
|
21474
21920
|
{ encoding: "utf-8", timeout: 3e3 }
|
|
21475
21921
|
);
|
|
@@ -21479,17 +21925,17 @@ var require_dist = __commonJS({
|
|
|
21479
21925
|
}
|
|
21480
21926
|
} else if (plat === "win32") {
|
|
21481
21927
|
try {
|
|
21482
|
-
const
|
|
21928
|
+
const fs10 = require("fs");
|
|
21483
21929
|
const appNameMap = getMacAppIdentifiers();
|
|
21484
21930
|
const appName = appNameMap[ideId];
|
|
21485
21931
|
if (appName) {
|
|
21486
|
-
const storagePath =
|
|
21487
|
-
process.env.APPDATA ||
|
|
21932
|
+
const storagePath = path7.join(
|
|
21933
|
+
process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
|
|
21488
21934
|
appName,
|
|
21489
21935
|
"storage.json"
|
|
21490
21936
|
);
|
|
21491
|
-
if (
|
|
21492
|
-
const data = JSON.parse(
|
|
21937
|
+
if (fs10.existsSync(storagePath)) {
|
|
21938
|
+
const data = JSON.parse(fs10.readFileSync(storagePath, "utf-8"));
|
|
21493
21939
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
21494
21940
|
if (workspaces.length > 0) {
|
|
21495
21941
|
const recent = workspaces[0];
|
|
@@ -21506,7 +21952,7 @@ var require_dist = __commonJS({
|
|
|
21506
21952
|
return void 0;
|
|
21507
21953
|
}
|
|
21508
21954
|
async function launchWithCdp2(options = {}) {
|
|
21509
|
-
const
|
|
21955
|
+
const platform8 = os8.platform();
|
|
21510
21956
|
let targetIde;
|
|
21511
21957
|
const ides = await detectIDEs3();
|
|
21512
21958
|
if (options.ideId) {
|
|
@@ -21575,9 +22021,9 @@ var require_dist = __commonJS({
|
|
|
21575
22021
|
}
|
|
21576
22022
|
const port = await findFreePort(portPair);
|
|
21577
22023
|
try {
|
|
21578
|
-
if (
|
|
22024
|
+
if (platform8 === "darwin") {
|
|
21579
22025
|
await launchMacOS(targetIde, port, workspace, options.newWindow);
|
|
21580
|
-
} else if (
|
|
22026
|
+
} else if (platform8 === "win32") {
|
|
21581
22027
|
await launchWindows(targetIde, port, workspace, options.newWindow);
|
|
21582
22028
|
} else {
|
|
21583
22029
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
@@ -21617,9 +22063,9 @@ var require_dist = __commonJS({
|
|
|
21617
22063
|
if (workspace) args.push(workspace);
|
|
21618
22064
|
if (appName) {
|
|
21619
22065
|
const openArgs = ["-a", appName, "--args", ...args];
|
|
21620
|
-
(0,
|
|
22066
|
+
(0, import_child_process4.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
|
|
21621
22067
|
} else if (ide.cliCommand) {
|
|
21622
|
-
(0,
|
|
22068
|
+
(0, import_child_process4.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
21623
22069
|
} else {
|
|
21624
22070
|
throw new Error(`No app identifier or CLI for ${ide.displayName}`);
|
|
21625
22071
|
}
|
|
@@ -21645,19 +22091,21 @@ var require_dist = __commonJS({
|
|
|
21645
22091
|
const args = ["--remote-debugging-port=" + port];
|
|
21646
22092
|
if (newWindow) args.push("--new-window");
|
|
21647
22093
|
if (workspace) args.push(workspace);
|
|
21648
|
-
(0,
|
|
22094
|
+
(0, import_child_process4.spawn)(cli, args, { detached: true, stdio: "ignore" }).unref();
|
|
21649
22095
|
}
|
|
21650
22096
|
function getAvailableIdeIds2() {
|
|
21651
22097
|
return getProviderLoader().getAvailableIdeTypes();
|
|
21652
22098
|
}
|
|
21653
|
-
|
|
21654
|
-
|
|
21655
|
-
var
|
|
21656
|
-
var
|
|
22099
|
+
init_config();
|
|
22100
|
+
init_workspaces();
|
|
22101
|
+
var fs6 = __toESM2(require("fs"));
|
|
22102
|
+
var path8 = __toESM2(require("path"));
|
|
22103
|
+
var os9 = __toESM2(require("os"));
|
|
22104
|
+
var LOG_DIR2 = process.platform === "darwin" ? path8.join(os9.homedir(), "Library", "Logs", "adhdev") : path8.join(os9.homedir(), ".local", "share", "adhdev", "logs");
|
|
21657
22105
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
21658
22106
|
var MAX_DAYS = 7;
|
|
21659
22107
|
try {
|
|
21660
|
-
|
|
22108
|
+
fs6.mkdirSync(LOG_DIR2, { recursive: true });
|
|
21661
22109
|
} catch {
|
|
21662
22110
|
}
|
|
21663
22111
|
var SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -21691,19 +22139,19 @@ var require_dist = __commonJS({
|
|
|
21691
22139
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
21692
22140
|
}
|
|
21693
22141
|
var currentDate2 = getDateStr2();
|
|
21694
|
-
var currentFile =
|
|
22142
|
+
var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
21695
22143
|
var writeCount2 = 0;
|
|
21696
22144
|
function checkRotation() {
|
|
21697
22145
|
const today = getDateStr2();
|
|
21698
22146
|
if (today !== currentDate2) {
|
|
21699
22147
|
currentDate2 = today;
|
|
21700
|
-
currentFile =
|
|
22148
|
+
currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
21701
22149
|
cleanOldFiles();
|
|
21702
22150
|
}
|
|
21703
22151
|
}
|
|
21704
22152
|
function cleanOldFiles() {
|
|
21705
22153
|
try {
|
|
21706
|
-
const files =
|
|
22154
|
+
const files = fs6.readdirSync(LOG_DIR2).filter((f) => f.startsWith("commands-") && f.endsWith(".jsonl"));
|
|
21707
22155
|
const cutoff = /* @__PURE__ */ new Date();
|
|
21708
22156
|
cutoff.setDate(cutoff.getDate() - MAX_DAYS);
|
|
21709
22157
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -21711,7 +22159,7 @@ var require_dist = __commonJS({
|
|
|
21711
22159
|
const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
21712
22160
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
21713
22161
|
try {
|
|
21714
|
-
|
|
22162
|
+
fs6.unlinkSync(path8.join(LOG_DIR2, file2));
|
|
21715
22163
|
} catch {
|
|
21716
22164
|
}
|
|
21717
22165
|
}
|
|
@@ -21721,14 +22169,14 @@ var require_dist = __commonJS({
|
|
|
21721
22169
|
}
|
|
21722
22170
|
function checkSize() {
|
|
21723
22171
|
try {
|
|
21724
|
-
const stat =
|
|
22172
|
+
const stat = fs6.statSync(currentFile);
|
|
21725
22173
|
if (stat.size > MAX_FILE_SIZE) {
|
|
21726
22174
|
const backup = currentFile.replace(".jsonl", ".1.jsonl");
|
|
21727
22175
|
try {
|
|
21728
|
-
|
|
22176
|
+
fs6.unlinkSync(backup);
|
|
21729
22177
|
} catch {
|
|
21730
22178
|
}
|
|
21731
|
-
|
|
22179
|
+
fs6.renameSync(currentFile, backup);
|
|
21732
22180
|
}
|
|
21733
22181
|
} catch {
|
|
21734
22182
|
}
|
|
@@ -21753,14 +22201,14 @@ var require_dist = __commonJS({
|
|
|
21753
22201
|
...entry.error ? { err: entry.error } : {},
|
|
21754
22202
|
...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
|
|
21755
22203
|
});
|
|
21756
|
-
|
|
22204
|
+
fs6.appendFileSync(currentFile, line + "\n");
|
|
21757
22205
|
} catch {
|
|
21758
22206
|
}
|
|
21759
22207
|
}
|
|
21760
22208
|
function getRecentCommands(count = 50) {
|
|
21761
22209
|
try {
|
|
21762
|
-
if (!
|
|
21763
|
-
const content =
|
|
22210
|
+
if (!fs6.existsSync(currentFile)) return [];
|
|
22211
|
+
const content = fs6.readFileSync(currentFile, "utf-8");
|
|
21764
22212
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
21765
22213
|
return lines.slice(-count).map((line) => {
|
|
21766
22214
|
try {
|
|
@@ -21783,7 +22231,7 @@ var require_dist = __commonJS({
|
|
|
21783
22231
|
}
|
|
21784
22232
|
}
|
|
21785
22233
|
cleanOldFiles();
|
|
21786
|
-
var
|
|
22234
|
+
var fs7 = __toESM2(require("fs"));
|
|
21787
22235
|
var CHAT_COMMANDS = [
|
|
21788
22236
|
"send_chat",
|
|
21789
22237
|
"new_chat",
|
|
@@ -21853,8 +22301,8 @@ var require_dist = __commonJS({
|
|
|
21853
22301
|
if (logs.length > 0) {
|
|
21854
22302
|
return { success: true, logs, totalBuffered: logs.length };
|
|
21855
22303
|
}
|
|
21856
|
-
if (
|
|
21857
|
-
const content =
|
|
22304
|
+
if (fs7.existsSync(LOG_PATH)) {
|
|
22305
|
+
const content = fs7.readFileSync(LOG_PATH, "utf-8");
|
|
21858
22306
|
const allLines = content.split("\n");
|
|
21859
22307
|
const recent = allLines.slice(-count).join("\n");
|
|
21860
22308
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
@@ -21893,8 +22341,20 @@ var require_dist = __commonJS({
|
|
|
21893
22341
|
}
|
|
21894
22342
|
// ─── IDE launch + CDP connect ───
|
|
21895
22343
|
case "launch_ide": {
|
|
21896
|
-
const
|
|
21897
|
-
const
|
|
22344
|
+
const ideKey = args?.ideId || args?.ideType;
|
|
22345
|
+
const resolvedWorkspace = resolveIdeLaunchWorkspace(
|
|
22346
|
+
{
|
|
22347
|
+
workspace: args?.workspace,
|
|
22348
|
+
workspaceId: args?.workspaceId,
|
|
22349
|
+
useDefaultWorkspace: args?.useDefaultWorkspace
|
|
22350
|
+
},
|
|
22351
|
+
loadConfig4()
|
|
22352
|
+
);
|
|
22353
|
+
const launchArgs = {
|
|
22354
|
+
ideId: ideKey,
|
|
22355
|
+
workspace: resolvedWorkspace,
|
|
22356
|
+
newWindow: args?.newWindow
|
|
22357
|
+
};
|
|
21898
22358
|
LOG5.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
21899
22359
|
const result = await launchWithCdp2(launchArgs);
|
|
21900
22360
|
if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
|
|
@@ -21911,6 +22371,15 @@ var require_dist = __commonJS({
|
|
|
21911
22371
|
}
|
|
21912
22372
|
}
|
|
21913
22373
|
this.deps.onIdeConnected?.();
|
|
22374
|
+
if (result.success && resolvedWorkspace) {
|
|
22375
|
+
try {
|
|
22376
|
+
saveConfig2(appendWorkspaceActivity(loadConfig4(), resolvedWorkspace, {
|
|
22377
|
+
kind: "ide",
|
|
22378
|
+
agentType: result.ideId
|
|
22379
|
+
}));
|
|
22380
|
+
} catch {
|
|
22381
|
+
}
|
|
22382
|
+
}
|
|
21914
22383
|
return { success: result.success, ...result };
|
|
21915
22384
|
}
|
|
21916
22385
|
// ─── IDE detection ───
|
|
@@ -21918,6 +22387,12 @@ var require_dist = __commonJS({
|
|
|
21918
22387
|
this.deps.detectedIdes.value = await detectIDEs3();
|
|
21919
22388
|
return { success: true, ides: this.deps.detectedIdes.value };
|
|
21920
22389
|
}
|
|
22390
|
+
// ─── Machine Settings ───
|
|
22391
|
+
case "set_machine_nickname": {
|
|
22392
|
+
const nickname = args?.nickname;
|
|
22393
|
+
updateConfig2({ machineNickname: nickname || null });
|
|
22394
|
+
return { success: true };
|
|
22395
|
+
}
|
|
21921
22396
|
}
|
|
21922
22397
|
return null;
|
|
21923
22398
|
}
|
|
@@ -21952,8 +22427,9 @@ var require_dist = __commonJS({
|
|
|
21952
22427
|
LOG5.info("StopIDE", `IDE stopped: ${ideType}`);
|
|
21953
22428
|
}
|
|
21954
22429
|
};
|
|
21955
|
-
var
|
|
22430
|
+
var os10 = __toESM2(require("os"));
|
|
21956
22431
|
init_config();
|
|
22432
|
+
init_workspaces();
|
|
21957
22433
|
var DaemonStatusReporter2 = class {
|
|
21958
22434
|
deps;
|
|
21959
22435
|
log;
|
|
@@ -22020,6 +22496,10 @@ var require_dist = __commonJS({
|
|
|
22020
22496
|
// (agent-stream polling backward compat)
|
|
22021
22497
|
updateAgentStreams(_ideType, _streams) {
|
|
22022
22498
|
}
|
|
22499
|
+
/** Reset P2P dedup hash — forces next send to transmit even if content unchanged */
|
|
22500
|
+
resetP2PHash() {
|
|
22501
|
+
this.lastP2PStatusHash = "";
|
|
22502
|
+
}
|
|
22023
22503
|
// ─── Core ────────────────────────────────────────
|
|
22024
22504
|
ts() {
|
|
22025
22505
|
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
@@ -22099,18 +22579,26 @@ var require_dist = __commonJS({
|
|
|
22099
22579
|
acpConfigOptions: s.acpConfigOptions,
|
|
22100
22580
|
acpModes: s.acpModes
|
|
22101
22581
|
}));
|
|
22582
|
+
const cfg = loadConfig4();
|
|
22583
|
+
const wsState = getWorkspaceState(cfg);
|
|
22584
|
+
const memSnap = getHostMemorySnapshot();
|
|
22102
22585
|
const payload = {
|
|
22103
22586
|
daemonMode: true,
|
|
22104
|
-
machineNickname:
|
|
22587
|
+
machineNickname: cfg.machineNickname || null,
|
|
22588
|
+
workspaces: wsState.workspaces,
|
|
22589
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
22590
|
+
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
22591
|
+
workspaceActivity: getWorkspaceActivity(cfg, 15),
|
|
22105
22592
|
machine: {
|
|
22106
|
-
hostname:
|
|
22107
|
-
platform:
|
|
22108
|
-
arch:
|
|
22109
|
-
cpus:
|
|
22110
|
-
totalMem:
|
|
22111
|
-
freeMem:
|
|
22112
|
-
|
|
22113
|
-
|
|
22593
|
+
hostname: os10.hostname(),
|
|
22594
|
+
platform: os10.platform(),
|
|
22595
|
+
arch: os10.arch(),
|
|
22596
|
+
cpus: os10.cpus().length,
|
|
22597
|
+
totalMem: memSnap.totalMem,
|
|
22598
|
+
freeMem: memSnap.freeMem,
|
|
22599
|
+
availableMem: memSnap.availableMem,
|
|
22600
|
+
loadavg: os10.loadavg(),
|
|
22601
|
+
uptime: os10.uptime()
|
|
22114
22602
|
},
|
|
22115
22603
|
managedIdes,
|
|
22116
22604
|
managedClis,
|
|
@@ -22142,6 +22630,8 @@ var require_dist = __commonJS({
|
|
|
22142
22630
|
const wsPayload = {
|
|
22143
22631
|
daemonMode: true,
|
|
22144
22632
|
machineNickname: payload.machineNickname,
|
|
22633
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
22634
|
+
workspaceCount: (wsState.workspaces || []).length,
|
|
22145
22635
|
// managedIdes: server only saves id, type, cdpConnected
|
|
22146
22636
|
managedIdes: managedIdes.map((ide) => ({
|
|
22147
22637
|
ideType: ide.ideType,
|
|
@@ -22172,7 +22662,7 @@ var require_dist = __commonJS({
|
|
|
22172
22662
|
sendP2PPayload(payload) {
|
|
22173
22663
|
const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
|
|
22174
22664
|
if (hashTarget.machine) {
|
|
22175
|
-
const { freeMem: _f, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
|
|
22665
|
+
const { freeMem: _f, availableMem: _a2, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
|
|
22176
22666
|
hashTarget.machine = stableMachine;
|
|
22177
22667
|
}
|
|
22178
22668
|
const h = this.simpleHash(JSON.stringify(hashTarget));
|
|
@@ -22192,15 +22682,32 @@ var require_dist = __commonJS({
|
|
|
22192
22682
|
return h.toString(36);
|
|
22193
22683
|
}
|
|
22194
22684
|
};
|
|
22195
|
-
var
|
|
22196
|
-
var
|
|
22685
|
+
var os12 = __toESM2(require("os"));
|
|
22686
|
+
var path10 = __toESM2(require("path"));
|
|
22197
22687
|
var crypto4 = __toESM2(require("crypto"));
|
|
22198
22688
|
var import_chalk4 = __toESM2(require("chalk"));
|
|
22199
|
-
var
|
|
22200
|
-
var
|
|
22689
|
+
var os11 = __toESM2(require("os"));
|
|
22690
|
+
var path9 = __toESM2(require("path"));
|
|
22691
|
+
var import_child_process5 = require("child_process");
|
|
22201
22692
|
var pty;
|
|
22202
22693
|
try {
|
|
22203
22694
|
pty = require("node-pty");
|
|
22695
|
+
if (os11.platform() !== "win32") {
|
|
22696
|
+
try {
|
|
22697
|
+
const fs10 = require("fs");
|
|
22698
|
+
const ptyDir = path9.dirname(require.resolve("node-pty"));
|
|
22699
|
+
const arch3 = os11.arch() === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
22700
|
+
const helper = path9.join(ptyDir, "prebuilds", arch3, "spawn-helper");
|
|
22701
|
+
if (fs10.existsSync(helper)) {
|
|
22702
|
+
const stat = fs10.statSync(helper);
|
|
22703
|
+
if (!(stat.mode & 73)) {
|
|
22704
|
+
fs10.chmodSync(helper, stat.mode | 493);
|
|
22705
|
+
LOG5.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
22706
|
+
}
|
|
22707
|
+
}
|
|
22708
|
+
} catch {
|
|
22709
|
+
}
|
|
22710
|
+
}
|
|
22204
22711
|
} catch {
|
|
22205
22712
|
LOG5.error("CLI", "[ProviderCliAdapter] node-pty not found. Install: npm install node-pty@1.0.0");
|
|
22206
22713
|
}
|
|
@@ -22208,21 +22715,125 @@ var require_dist = __commonJS({
|
|
|
22208
22715
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
22209
22716
|
}
|
|
22210
22717
|
function findBinary(name) {
|
|
22211
|
-
const isWin =
|
|
22718
|
+
const isWin = os11.platform() === "win32";
|
|
22212
22719
|
try {
|
|
22213
22720
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
22214
|
-
return (0,
|
|
22721
|
+
return (0, import_child_process5.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
22215
22722
|
} catch {
|
|
22216
22723
|
return isWin ? `${name}.cmd` : name;
|
|
22217
22724
|
}
|
|
22218
22725
|
}
|
|
22726
|
+
function isScriptBinary(binaryPath) {
|
|
22727
|
+
if (!path9.isAbsolute(binaryPath)) return false;
|
|
22728
|
+
try {
|
|
22729
|
+
const fs10 = require("fs");
|
|
22730
|
+
const resolved = fs10.realpathSync(binaryPath);
|
|
22731
|
+
const head = Buffer.alloc(8);
|
|
22732
|
+
const fd = fs10.openSync(resolved, "r");
|
|
22733
|
+
fs10.readSync(fd, head, 0, 8, 0);
|
|
22734
|
+
fs10.closeSync(fd);
|
|
22735
|
+
let i = 0;
|
|
22736
|
+
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
22737
|
+
return head[i] === 35 && head[i + 1] === 33;
|
|
22738
|
+
} catch {
|
|
22739
|
+
return false;
|
|
22740
|
+
}
|
|
22741
|
+
}
|
|
22742
|
+
function looksLikeMachOOrElf(filePath) {
|
|
22743
|
+
if (!path9.isAbsolute(filePath)) return false;
|
|
22744
|
+
try {
|
|
22745
|
+
const fs10 = require("fs");
|
|
22746
|
+
const resolved = fs10.realpathSync(filePath);
|
|
22747
|
+
const buf = Buffer.alloc(8);
|
|
22748
|
+
const fd = fs10.openSync(resolved, "r");
|
|
22749
|
+
fs10.readSync(fd, buf, 0, 8, 0);
|
|
22750
|
+
fs10.closeSync(fd);
|
|
22751
|
+
let i = 0;
|
|
22752
|
+
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
22753
|
+
const b = buf.subarray(i);
|
|
22754
|
+
if (b.length < 4) return false;
|
|
22755
|
+
if (b[0] === 127 && b[1] === 69 && b[2] === 76 && b[3] === 70) return true;
|
|
22756
|
+
const le = b.readUInt32LE(0);
|
|
22757
|
+
const be = b.readUInt32BE(0);
|
|
22758
|
+
const magics = [4277009102, 4277009103, 3405691582, 3199925962];
|
|
22759
|
+
return magics.some((m) => m === le || m === be);
|
|
22760
|
+
} catch {
|
|
22761
|
+
return false;
|
|
22762
|
+
}
|
|
22763
|
+
}
|
|
22764
|
+
function shSingleQuote(arg) {
|
|
22765
|
+
if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
|
|
22766
|
+
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
22767
|
+
}
|
|
22768
|
+
function parsePatternEntry(x) {
|
|
22769
|
+
if (x instanceof RegExp) return x;
|
|
22770
|
+
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
22771
|
+
try {
|
|
22772
|
+
const s = x;
|
|
22773
|
+
return new RegExp(s.source, s.flags || "");
|
|
22774
|
+
} catch {
|
|
22775
|
+
return null;
|
|
22776
|
+
}
|
|
22777
|
+
}
|
|
22778
|
+
return null;
|
|
22779
|
+
}
|
|
22780
|
+
function coercePatternArray(raw, fallbacks) {
|
|
22781
|
+
if (!Array.isArray(raw)) return [...fallbacks];
|
|
22782
|
+
const parsed = raw.map(parsePatternEntry).filter((r) => r != null);
|
|
22783
|
+
return parsed.length > 0 ? parsed : [...fallbacks];
|
|
22784
|
+
}
|
|
22785
|
+
var FALLBACK_PROMPT = [
|
|
22786
|
+
/Type your message/i,
|
|
22787
|
+
/^>\s*$/m,
|
|
22788
|
+
// '>' alone on its own line
|
|
22789
|
+
/[›➤]\s*$/,
|
|
22790
|
+
/for shortcuts/i,
|
|
22791
|
+
/\?\s*for help/i,
|
|
22792
|
+
/Press enter/i
|
|
22793
|
+
// NOTE: removed /^[\s\u2500-\u257f]*>\s*$/m — the box-drawing char range is too wide and
|
|
22794
|
+
// can match dialog-clearing ANSI output, causing false prompt detection in approval state.
|
|
22795
|
+
];
|
|
22796
|
+
var FALLBACK_GENERATING = [
|
|
22797
|
+
/[\u2800-\u28ff]/,
|
|
22798
|
+
// Braille spinner blocks (universal TUI)
|
|
22799
|
+
/esc to (cancel|interrupt|stop)/i,
|
|
22800
|
+
// Common TUI generation status line
|
|
22801
|
+
/generating\.\.\./i,
|
|
22802
|
+
/Claude is (?:thinking|processing|working)/i
|
|
22803
|
+
// Specific Claude Code status
|
|
22804
|
+
];
|
|
22805
|
+
var FALLBACK_APPROVAL = [
|
|
22806
|
+
/Allow\s+once/i,
|
|
22807
|
+
/Always\s+allow/i,
|
|
22808
|
+
/\(y\/n\)/i,
|
|
22809
|
+
/\[Y\/n\]/i,
|
|
22810
|
+
/Run\s+this\s+command/i
|
|
22811
|
+
// NOTE: removed /Do you want to (?:run|execute|allow)/i — too broad, matches AI explanation
|
|
22812
|
+
// text like "Do you want to allow this feature?" causing false approval notifications.
|
|
22813
|
+
];
|
|
22814
|
+
function defaultCleanOutput(raw, _lastUserInput) {
|
|
22815
|
+
return stripAnsi(raw).trim();
|
|
22816
|
+
}
|
|
22817
|
+
function normalizeCliProviderForRuntime(raw) {
|
|
22818
|
+
const patterns = raw?.patterns || {};
|
|
22819
|
+
return {
|
|
22820
|
+
...raw,
|
|
22821
|
+
patterns: {
|
|
22822
|
+
prompt: coercePatternArray(patterns.prompt, FALLBACK_PROMPT),
|
|
22823
|
+
generating: coercePatternArray(patterns.generating, FALLBACK_GENERATING),
|
|
22824
|
+
approval: coercePatternArray(patterns.approval, FALLBACK_APPROVAL),
|
|
22825
|
+
ready: coercePatternArray(patterns.ready, [])
|
|
22826
|
+
},
|
|
22827
|
+
cleanOutput: typeof raw?.cleanOutput === "function" ? raw.cleanOutput : defaultCleanOutput
|
|
22828
|
+
};
|
|
22829
|
+
}
|
|
22219
22830
|
var ProviderCliAdapter = class {
|
|
22220
22831
|
constructor(provider2, workingDir, extraArgs = []) {
|
|
22221
22832
|
this.extraArgs = extraArgs;
|
|
22222
|
-
this.provider = provider2;
|
|
22833
|
+
this.provider = normalizeCliProviderForRuntime(provider2);
|
|
22223
22834
|
this.cliType = provider2.type;
|
|
22224
22835
|
this.cliName = provider2.name;
|
|
22225
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
22836
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os11.homedir()) : workingDir;
|
|
22226
22837
|
const t = provider2.timeouts || {};
|
|
22227
22838
|
this.timeouts = {
|
|
22228
22839
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -22259,6 +22870,11 @@ var require_dist = __commonJS({
|
|
|
22259
22870
|
logBuffer = [];
|
|
22260
22871
|
// Approval cooldown
|
|
22261
22872
|
lastApprovalResolvedAt = 0;
|
|
22873
|
+
// Approval state machine
|
|
22874
|
+
approvalTransitionBuffer = "";
|
|
22875
|
+
approvalExitTimeout = null;
|
|
22876
|
+
// Resize redraw suppression
|
|
22877
|
+
resizeSuppressUntil = 0;
|
|
22262
22878
|
// Resolved timeouts (provider defaults + overrides)
|
|
22263
22879
|
timeouts;
|
|
22264
22880
|
// ─── Lifecycle ─────────────────────────────────
|
|
@@ -22280,20 +22896,25 @@ var require_dist = __commonJS({
|
|
|
22280
22896
|
if (!pty) throw new Error("node-pty is not installed");
|
|
22281
22897
|
const { spawn: spawnConfig } = this.provider;
|
|
22282
22898
|
const binaryPath = findBinary(spawnConfig.command);
|
|
22283
|
-
const isWin =
|
|
22899
|
+
const isWin = os11.platform() === "win32";
|
|
22284
22900
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
22285
22901
|
LOG5.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
22286
22902
|
let shellCmd;
|
|
22287
22903
|
let shellArgs;
|
|
22288
|
-
|
|
22904
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
22905
|
+
const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
|
|
22906
|
+
if (useShell) {
|
|
22907
|
+
if (!spawnConfig.shell && !isWin) {
|
|
22908
|
+
LOG5.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
|
|
22909
|
+
}
|
|
22289
22910
|
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
22290
|
-
const fullCmd = [binaryPath, ...allArgs].join(" ");
|
|
22911
|
+
const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
|
|
22291
22912
|
shellArgs = isWin ? ["/c", fullCmd] : ["-l", "-c", fullCmd];
|
|
22292
22913
|
} else {
|
|
22293
22914
|
shellCmd = binaryPath;
|
|
22294
22915
|
shellArgs = allArgs;
|
|
22295
22916
|
}
|
|
22296
|
-
|
|
22917
|
+
const ptyOpts = {
|
|
22297
22918
|
name: "xterm-256color",
|
|
22298
22919
|
cols: 120,
|
|
22299
22920
|
rows: 40,
|
|
@@ -22302,7 +22923,21 @@ var require_dist = __commonJS({
|
|
|
22302
22923
|
...process.env,
|
|
22303
22924
|
...spawnConfig.env
|
|
22304
22925
|
}
|
|
22305
|
-
}
|
|
22926
|
+
};
|
|
22927
|
+
try {
|
|
22928
|
+
this.ptyProcess = pty.spawn(shellCmd, shellArgs, ptyOpts);
|
|
22929
|
+
} catch (err) {
|
|
22930
|
+
const msg = err?.message || String(err);
|
|
22931
|
+
if (!isWin && !useShell && /posix_spawn|spawn/i.test(msg)) {
|
|
22932
|
+
LOG5.warn("CLI", `[${this.cliType}] Direct spawn failed (${msg}), retrying via login shell`);
|
|
22933
|
+
shellCmd = process.env.SHELL || "/bin/zsh";
|
|
22934
|
+
const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
|
|
22935
|
+
shellArgs = ["-l", "-c", fullCmd];
|
|
22936
|
+
this.ptyProcess = pty.spawn(shellCmd, shellArgs, ptyOpts);
|
|
22937
|
+
} else {
|
|
22938
|
+
throw err;
|
|
22939
|
+
}
|
|
22940
|
+
}
|
|
22306
22941
|
this.ptyProcess.onData((data) => {
|
|
22307
22942
|
this.handleOutput(data);
|
|
22308
22943
|
if (this.onPtyDataCallback) {
|
|
@@ -22330,6 +22965,7 @@ var require_dist = __commonJS({
|
|
|
22330
22965
|
}
|
|
22331
22966
|
// ─── Output state machine ────────────────────────────
|
|
22332
22967
|
handleOutput(rawData) {
|
|
22968
|
+
if (Date.now() < this.resizeSuppressUntil) return;
|
|
22333
22969
|
const cleanData = stripAnsi(rawData);
|
|
22334
22970
|
const { patterns } = this.provider;
|
|
22335
22971
|
if (cleanData.trim()) {
|
|
@@ -22362,30 +22998,55 @@ var require_dist = __commonJS({
|
|
|
22362
22998
|
const hasApproval = patterns.approval.some((p) => p.test(this.recentOutputBuffer));
|
|
22363
22999
|
if (hasApproval && this.currentStatus !== "waiting_approval") {
|
|
22364
23000
|
if (this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown) return;
|
|
23001
|
+
const ctxLines = this.recentOutputBuffer.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
|
|
22365
23002
|
this.isWaitingForResponse = true;
|
|
22366
23003
|
this.currentStatus = "waiting_approval";
|
|
22367
23004
|
this.recentOutputBuffer = "";
|
|
22368
|
-
|
|
23005
|
+
this.approvalTransitionBuffer = "";
|
|
22369
23006
|
this.activeModal = {
|
|
22370
23007
|
message: ctxLines.slice(-5).join(" ").slice(0, 200) || "Approval required",
|
|
22371
23008
|
buttons: ["Allow once", "Always allow", "Deny"]
|
|
22372
23009
|
};
|
|
22373
23010
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
23011
|
+
if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
|
|
23012
|
+
this.approvalExitTimeout = setTimeout(() => {
|
|
23013
|
+
if (this.currentStatus === "waiting_approval") {
|
|
23014
|
+
LOG5.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-exiting waiting_approval`);
|
|
23015
|
+
this.activeModal = null;
|
|
23016
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
23017
|
+
this.recentOutputBuffer = "";
|
|
23018
|
+
this.approvalTransitionBuffer = "";
|
|
23019
|
+
this.approvalExitTimeout = null;
|
|
23020
|
+
this.currentStatus = this.isWaitingForResponse ? "generating" : "idle";
|
|
23021
|
+
this.onStatusChange?.();
|
|
23022
|
+
}
|
|
23023
|
+
}, 6e4);
|
|
22374
23024
|
this.onStatusChange?.();
|
|
22375
23025
|
return;
|
|
22376
23026
|
}
|
|
22377
23027
|
if (this.currentStatus === "waiting_approval") {
|
|
22378
|
-
|
|
22379
|
-
const
|
|
23028
|
+
this.approvalTransitionBuffer = (this.approvalTransitionBuffer + cleanData).slice(-500);
|
|
23029
|
+
const genResume = patterns.generating.some((p) => p.test(this.approvalTransitionBuffer));
|
|
23030
|
+
const promptResume = patterns.prompt.some((p) => p.test(this.approvalTransitionBuffer));
|
|
22380
23031
|
if (genResume) {
|
|
23032
|
+
if (this.approvalExitTimeout) {
|
|
23033
|
+
clearTimeout(this.approvalExitTimeout);
|
|
23034
|
+
this.approvalExitTimeout = null;
|
|
23035
|
+
}
|
|
22381
23036
|
this.currentStatus = "generating";
|
|
22382
23037
|
this.activeModal = null;
|
|
22383
23038
|
this.recentOutputBuffer = "";
|
|
23039
|
+
this.approvalTransitionBuffer = "";
|
|
22384
23040
|
this.lastApprovalResolvedAt = Date.now();
|
|
22385
23041
|
this.onStatusChange?.();
|
|
22386
23042
|
} else if (promptResume) {
|
|
23043
|
+
if (this.approvalExitTimeout) {
|
|
23044
|
+
clearTimeout(this.approvalExitTimeout);
|
|
23045
|
+
this.approvalExitTimeout = null;
|
|
23046
|
+
}
|
|
22387
23047
|
this.activeModal = null;
|
|
22388
23048
|
this.recentOutputBuffer = "";
|
|
23049
|
+
this.approvalTransitionBuffer = "";
|
|
22389
23050
|
this.lastApprovalResolvedAt = Date.now();
|
|
22390
23051
|
this.finishResponse();
|
|
22391
23052
|
}
|
|
@@ -22411,7 +23072,8 @@ var require_dist = __commonJS({
|
|
|
22411
23072
|
this.onStatusChange?.();
|
|
22412
23073
|
return;
|
|
22413
23074
|
}
|
|
22414
|
-
|
|
23075
|
+
const trailingLines = cleanData.split("\n").slice(-2).join("\n");
|
|
23076
|
+
if (patterns.prompt.some((p) => p.test(trailingLines))) {
|
|
22415
23077
|
this.finishResponse();
|
|
22416
23078
|
} else {
|
|
22417
23079
|
this.idleTimeout = setTimeout(() => {
|
|
@@ -22432,6 +23094,10 @@ var require_dist = __commonJS({
|
|
|
22432
23094
|
clearTimeout(this.idleTimeout);
|
|
22433
23095
|
this.idleTimeout = null;
|
|
22434
23096
|
}
|
|
23097
|
+
if (this.approvalExitTimeout) {
|
|
23098
|
+
clearTimeout(this.approvalExitTimeout);
|
|
23099
|
+
this.approvalExitTimeout = null;
|
|
23100
|
+
}
|
|
22435
23101
|
const lastUserText = this.messages.filter((m) => m.role === "user").pop()?.content;
|
|
22436
23102
|
let response = this.provider.cleanOutput(this.responseBuffer, lastUserText);
|
|
22437
23103
|
if (lastUserText && response) {
|
|
@@ -22481,6 +23147,10 @@ var require_dist = __commonJS({
|
|
|
22481
23147
|
this.shutdown();
|
|
22482
23148
|
}
|
|
22483
23149
|
shutdown() {
|
|
23150
|
+
if (this.approvalExitTimeout) {
|
|
23151
|
+
clearTimeout(this.approvalExitTimeout);
|
|
23152
|
+
this.approvalExitTimeout = null;
|
|
23153
|
+
}
|
|
22484
23154
|
if (this.ptyProcess) {
|
|
22485
23155
|
this.ptyProcess.write("");
|
|
22486
23156
|
setTimeout(() => {
|
|
@@ -22508,16 +23178,29 @@ var require_dist = __commonJS({
|
|
|
22508
23178
|
writeRaw(data) {
|
|
22509
23179
|
this.ptyProcess?.write(data);
|
|
22510
23180
|
}
|
|
23181
|
+
/**
|
|
23182
|
+
* Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
|
|
23183
|
+
* Index 0 = first option (already selected by default — just Enter).
|
|
23184
|
+
* Index N = press Arrow Down N times, then Enter.
|
|
23185
|
+
*/
|
|
23186
|
+
resolveModal(buttonIndex) {
|
|
23187
|
+
if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
|
|
23188
|
+
const DOWN = "\x1B[B";
|
|
23189
|
+
const keys = DOWN.repeat(Math.max(0, buttonIndex)) + "\r";
|
|
23190
|
+
this.ptyProcess.write(keys);
|
|
23191
|
+
}
|
|
22511
23192
|
resize(cols, rows) {
|
|
22512
23193
|
if (this.ptyProcess) {
|
|
22513
23194
|
try {
|
|
22514
23195
|
this.ptyProcess.resize(cols, rows);
|
|
23196
|
+
this.resizeSuppressUntil = Date.now() + 300;
|
|
22515
23197
|
} catch {
|
|
22516
23198
|
}
|
|
22517
23199
|
}
|
|
22518
23200
|
}
|
|
22519
23201
|
};
|
|
22520
23202
|
init_config();
|
|
23203
|
+
init_workspaces();
|
|
22521
23204
|
var crypto3 = __toESM2(require("crypto"));
|
|
22522
23205
|
var CliProviderInstance = class {
|
|
22523
23206
|
constructor(provider2, workingDir, cliArgs = [], instanceId) {
|
|
@@ -22631,20 +23314,24 @@ var require_dist = __commonJS({
|
|
|
22631
23314
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
22632
23315
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
22633
23316
|
if (newStatus !== this.lastStatus) {
|
|
23317
|
+
LOG5.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
|
|
22634
23318
|
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
22635
23319
|
this.generatingStartedAt = now;
|
|
22636
23320
|
this.pushEvent({ event: "agent:generating_started", chatTitle, timestamp: now });
|
|
22637
23321
|
} else if (newStatus === "waiting_approval") {
|
|
22638
23322
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
23323
|
+
const modal = adapterStatus.activeModal;
|
|
23324
|
+
LOG5.info("CLI", `[${this.type}] approval modal: "${modal?.message?.slice(0, 80) ?? "none"}"`);
|
|
22639
23325
|
this.pushEvent({
|
|
22640
23326
|
event: "agent:waiting_approval",
|
|
22641
23327
|
chatTitle,
|
|
22642
23328
|
timestamp: now,
|
|
22643
|
-
modalMessage:
|
|
22644
|
-
modalButtons:
|
|
23329
|
+
modalMessage: modal?.message,
|
|
23330
|
+
modalButtons: modal?.buttons
|
|
22645
23331
|
});
|
|
22646
23332
|
} else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
|
|
22647
23333
|
const duration3 = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
23334
|
+
LOG5.info("CLI", `[${this.type}] completed in ${duration3}s`);
|
|
22648
23335
|
this.pushEvent({ event: "agent:generating_completed", chatTitle, duration: duration3, timestamp: now });
|
|
22649
23336
|
this.generatingStartedAt = 0;
|
|
22650
23337
|
} else if (newStatus === "stopped") {
|
|
@@ -22679,7 +23366,7 @@ var require_dist = __commonJS({
|
|
|
22679
23366
|
}
|
|
22680
23367
|
};
|
|
22681
23368
|
var import_stream = require("stream");
|
|
22682
|
-
var
|
|
23369
|
+
var import_child_process6 = require("child_process");
|
|
22683
23370
|
var import_sdk = (init_acp(), __toCommonJS(acp_exports));
|
|
22684
23371
|
function flattenContent(content) {
|
|
22685
23372
|
if (typeof content === "string") return content;
|
|
@@ -22996,7 +23683,7 @@ var require_dist = __commonJS({
|
|
|
22996
23683
|
this.errorMessage = null;
|
|
22997
23684
|
this.errorReason = null;
|
|
22998
23685
|
this.stderrBuffer = [];
|
|
22999
|
-
this.process = (0,
|
|
23686
|
+
this.process = (0, import_child_process6.spawn)(command, args, {
|
|
23000
23687
|
cwd: this.workingDir,
|
|
23001
23688
|
env,
|
|
23002
23689
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -23100,13 +23787,13 @@ var require_dist = __commonJS({
|
|
|
23100
23787
|
}
|
|
23101
23788
|
this.currentStatus = "waiting_approval";
|
|
23102
23789
|
this.detectStatusTransition();
|
|
23103
|
-
const approved = await new Promise((
|
|
23104
|
-
this.permissionResolvers.push(
|
|
23790
|
+
const approved = await new Promise((resolve7) => {
|
|
23791
|
+
this.permissionResolvers.push(resolve7);
|
|
23105
23792
|
setTimeout(() => {
|
|
23106
|
-
const idx = this.permissionResolvers.indexOf(
|
|
23793
|
+
const idx = this.permissionResolvers.indexOf(resolve7);
|
|
23107
23794
|
if (idx >= 0) {
|
|
23108
23795
|
this.permissionResolvers.splice(idx, 1);
|
|
23109
|
-
|
|
23796
|
+
resolve7(false);
|
|
23110
23797
|
}
|
|
23111
23798
|
}, 3e5);
|
|
23112
23799
|
});
|
|
@@ -23574,6 +24261,24 @@ var require_dist = __commonJS({
|
|
|
23574
24261
|
const hash2 = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
|
|
23575
24262
|
return `${cliType}_${hash2}`;
|
|
23576
24263
|
}
|
|
24264
|
+
persistRecentDir(cliType, dir) {
|
|
24265
|
+
try {
|
|
24266
|
+
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
24267
|
+
const provider2 = this.providerLoader.getByAlias(cliType);
|
|
24268
|
+
const actKind = provider2?.category === "acp" ? "acp" : "cli";
|
|
24269
|
+
let next = loadConfig4();
|
|
24270
|
+
console.log(import_chalk4.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
|
|
24271
|
+
const recent = next.recentCliWorkspaces || [];
|
|
24272
|
+
if (!recent.includes(dir)) {
|
|
24273
|
+
next = { ...next, recentCliWorkspaces: [dir, ...recent].slice(0, 10) };
|
|
24274
|
+
}
|
|
24275
|
+
next = appendWorkspaceActivity(next, dir, { kind: actKind, agentType: normalizedType });
|
|
24276
|
+
saveConfig2(next);
|
|
24277
|
+
console.log(import_chalk4.default.green(` \u2713 Recent workspace saved: ${dir}`));
|
|
24278
|
+
} catch (e) {
|
|
24279
|
+
console.error(import_chalk4.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
24280
|
+
}
|
|
24281
|
+
}
|
|
23577
24282
|
createAdapter(cliType, workingDir, cliArgs) {
|
|
23578
24283
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
23579
24284
|
const provider2 = this.providerLoader.getMeta(normalizedType);
|
|
@@ -23585,8 +24290,9 @@ var require_dist = __commonJS({
|
|
|
23585
24290
|
}
|
|
23586
24291
|
// ─── Session start/management ──────────────────────────────
|
|
23587
24292
|
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
23588
|
-
const trimmed = (workingDir ||
|
|
23589
|
-
|
|
24293
|
+
const trimmed = (workingDir || "").trim();
|
|
24294
|
+
if (!trimmed) throw new Error("working directory required");
|
|
24295
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path10.resolve(trimmed);
|
|
23590
24296
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
23591
24297
|
const provider2 = this.providerLoader.getByAlias(cliType);
|
|
23592
24298
|
const key = crypto4.randomUUID();
|
|
@@ -23596,8 +24302,8 @@ var require_dist = __commonJS({
|
|
|
23596
24302
|
const spawnCmd = provider2.spawn?.command;
|
|
23597
24303
|
if (spawnCmd) {
|
|
23598
24304
|
try {
|
|
23599
|
-
const { execSync:
|
|
23600
|
-
|
|
24305
|
+
const { execSync: execSync7 } = require("child_process");
|
|
24306
|
+
execSync7(`which ${spawnCmd}`, { stdio: "ignore" });
|
|
23601
24307
|
} catch {
|
|
23602
24308
|
const installInfo = provider2.install || `Install: check ${provider2.displayName || provider2.name} documentation`;
|
|
23603
24309
|
throw new Error(
|
|
@@ -23664,18 +24370,52 @@ ${installInfo}`
|
|
|
23664
24370
|
const instanceManager = this.deps.getInstanceManager();
|
|
23665
24371
|
if (provider2 && instanceManager) {
|
|
23666
24372
|
const cliInstance = new CliProviderInstance(provider2, resolvedDir, cliArgs, key);
|
|
23667
|
-
|
|
23668
|
-
|
|
23669
|
-
|
|
23670
|
-
|
|
23671
|
-
|
|
23672
|
-
|
|
23673
|
-
|
|
24373
|
+
try {
|
|
24374
|
+
await instanceManager.addInstance(key, cliInstance, {
|
|
24375
|
+
serverConn: this.deps.getServerConn(),
|
|
24376
|
+
settings: {},
|
|
24377
|
+
onPtyData: (data) => {
|
|
24378
|
+
this.deps.getP2p()?.broadcastPtyOutput(key, data);
|
|
24379
|
+
}
|
|
24380
|
+
});
|
|
24381
|
+
} catch (spawnErr) {
|
|
24382
|
+
LOG5.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
24383
|
+
instanceManager.removeInstance(key);
|
|
24384
|
+
throw new Error(`Failed to start ${cliInfo.displayName}: ${spawnErr?.message}`);
|
|
24385
|
+
}
|
|
23674
24386
|
this.adapters.set(key, cliInstance.getAdapter());
|
|
23675
24387
|
console.log(import_chalk4.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
24388
|
+
const checkStopped = setInterval(() => {
|
|
24389
|
+
try {
|
|
24390
|
+
const adapter = this.adapters.get(key);
|
|
24391
|
+
if (!adapter) {
|
|
24392
|
+
clearInterval(checkStopped);
|
|
24393
|
+
return;
|
|
24394
|
+
}
|
|
24395
|
+
const status = adapter.getStatus?.();
|
|
24396
|
+
if (status?.status === "stopped" || status?.status === "error") {
|
|
24397
|
+
clearInterval(checkStopped);
|
|
24398
|
+
setTimeout(() => {
|
|
24399
|
+
if (this.adapters.has(key)) {
|
|
24400
|
+
this.adapters.delete(key);
|
|
24401
|
+
this.deps.removeAgentTracking(key);
|
|
24402
|
+
instanceManager.removeInstance(key);
|
|
24403
|
+
LOG5.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
|
|
24404
|
+
this.deps.onStatusChange();
|
|
24405
|
+
}
|
|
24406
|
+
}, 5e3);
|
|
24407
|
+
}
|
|
24408
|
+
} catch {
|
|
24409
|
+
}
|
|
24410
|
+
}, 3e3);
|
|
23676
24411
|
} else {
|
|
23677
24412
|
const adapter = this.createAdapter(cliType, resolvedDir, cliArgs);
|
|
23678
|
-
|
|
24413
|
+
try {
|
|
24414
|
+
await adapter.spawn();
|
|
24415
|
+
} catch (spawnErr) {
|
|
24416
|
+
LOG5.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
24417
|
+
throw new Error(`Failed to start ${cliInfo.displayName}: ${spawnErr?.message}`);
|
|
24418
|
+
}
|
|
23679
24419
|
const serverConn = this.deps.getServerConn();
|
|
23680
24420
|
if (serverConn && typeof adapter.setServerConn === "function") {
|
|
23681
24421
|
adapter.setServerConn(serverConn);
|
|
@@ -23683,12 +24423,12 @@ ${installInfo}`
|
|
|
23683
24423
|
adapter.setOnStatusChange(() => {
|
|
23684
24424
|
this.deps.onStatusChange();
|
|
23685
24425
|
const status = adapter.getStatus?.();
|
|
23686
|
-
if (status?.status === "stopped") {
|
|
24426
|
+
if (status?.status === "stopped" || status?.status === "error") {
|
|
23687
24427
|
setTimeout(() => {
|
|
23688
24428
|
if (this.adapters.get(key) === adapter) {
|
|
23689
24429
|
this.adapters.delete(key);
|
|
23690
24430
|
this.deps.removeAgentTracking(key);
|
|
23691
|
-
|
|
24431
|
+
LOG5.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${adapter.cliType}`);
|
|
23692
24432
|
this.deps.onStatusChange();
|
|
23693
24433
|
}
|
|
23694
24434
|
}, 3e3);
|
|
@@ -23712,12 +24452,24 @@ ${installInfo}`
|
|
|
23712
24452
|
async stopSession(key) {
|
|
23713
24453
|
const adapter = this.adapters.get(key);
|
|
23714
24454
|
if (adapter) {
|
|
23715
|
-
|
|
24455
|
+
try {
|
|
24456
|
+
adapter.shutdown();
|
|
24457
|
+
} catch (e) {
|
|
24458
|
+
LOG5.warn("CLI", `Shutdown error for ${adapter.cliType}: ${e?.message} (force-cleaning)`);
|
|
24459
|
+
}
|
|
23716
24460
|
this.adapters.delete(key);
|
|
23717
24461
|
this.deps.removeAgentTracking(key);
|
|
23718
24462
|
this.deps.getInstanceManager()?.removeInstance(key);
|
|
23719
|
-
|
|
24463
|
+
LOG5.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
|
|
23720
24464
|
this.deps.onStatusChange();
|
|
24465
|
+
} else {
|
|
24466
|
+
const im = this.deps.getInstanceManager();
|
|
24467
|
+
if (im) {
|
|
24468
|
+
im.removeInstance(key);
|
|
24469
|
+
this.deps.removeAgentTracking(key);
|
|
24470
|
+
LOG5.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
|
|
24471
|
+
this.deps.onStatusChange();
|
|
24472
|
+
}
|
|
23721
24473
|
}
|
|
23722
24474
|
}
|
|
23723
24475
|
shutdownAll() {
|
|
@@ -23758,8 +24510,28 @@ ${installInfo}`
|
|
|
23758
24510
|
switch (cmd) {
|
|
23759
24511
|
case "launch_cli": {
|
|
23760
24512
|
const cliType = args?.cliType;
|
|
23761
|
-
const
|
|
23762
|
-
const
|
|
24513
|
+
const config2 = loadConfig4();
|
|
24514
|
+
const resolved = resolveLaunchDirectory(
|
|
24515
|
+
{
|
|
24516
|
+
dir: args?.dir,
|
|
24517
|
+
workspaceId: args?.workspaceId,
|
|
24518
|
+
useDefaultWorkspace: args?.useDefaultWorkspace === true,
|
|
24519
|
+
useHome: args?.useHome === true
|
|
24520
|
+
},
|
|
24521
|
+
config2
|
|
24522
|
+
);
|
|
24523
|
+
if (!resolved.ok) {
|
|
24524
|
+
const ws = getWorkspaceState(config2);
|
|
24525
|
+
return {
|
|
24526
|
+
success: false,
|
|
24527
|
+
error: resolved.message,
|
|
24528
|
+
code: resolved.code,
|
|
24529
|
+
workspaces: ws.workspaces,
|
|
24530
|
+
defaultWorkspacePath: ws.defaultWorkspacePath
|
|
24531
|
+
};
|
|
24532
|
+
}
|
|
24533
|
+
const dir = resolved.path;
|
|
24534
|
+
const launchSource = resolved.source;
|
|
23763
24535
|
if (!cliType) throw new Error("cliType required");
|
|
23764
24536
|
await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel);
|
|
23765
24537
|
let newKey = null;
|
|
@@ -23768,19 +24540,8 @@ ${installInfo}`
|
|
|
23768
24540
|
newKey = k;
|
|
23769
24541
|
}
|
|
23770
24542
|
}
|
|
23771
|
-
|
|
23772
|
-
|
|
23773
|
-
console.log(import_chalk4.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
|
|
23774
|
-
const recent = config2.recentCliWorkspaces || [];
|
|
23775
|
-
if (!recent.includes(dir)) {
|
|
23776
|
-
const updated = [dir, ...recent].slice(0, 10);
|
|
23777
|
-
saveConfig2({ ...config2, recentCliWorkspaces: updated });
|
|
23778
|
-
console.log(import_chalk4.default.green(` \u2713 Recent workspace saved: ${dir}`));
|
|
23779
|
-
}
|
|
23780
|
-
} catch (e) {
|
|
23781
|
-
console.error(import_chalk4.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
23782
|
-
}
|
|
23783
|
-
return { success: true, cliType, dir, id: newKey, defaultedToHome };
|
|
24543
|
+
this.persistRecentDir(cliType, dir);
|
|
24544
|
+
return { success: true, cliType, dir, id: newKey, launchSource };
|
|
23784
24545
|
}
|
|
23785
24546
|
case "stop_cli": {
|
|
23786
24547
|
const cliType = args?.cliType;
|
|
@@ -23796,11 +24557,32 @@ ${installInfo}`
|
|
|
23796
24557
|
}
|
|
23797
24558
|
case "restart_session": {
|
|
23798
24559
|
const cliType = args?.cliType || args?.agentType || args?.ideType;
|
|
23799
|
-
const
|
|
24560
|
+
const cfg = loadConfig4();
|
|
24561
|
+
const rdir = resolveLaunchDirectory(
|
|
24562
|
+
{
|
|
24563
|
+
dir: args?.dir,
|
|
24564
|
+
workspaceId: args?.workspaceId,
|
|
24565
|
+
useDefaultWorkspace: args?.useDefaultWorkspace === true,
|
|
24566
|
+
useHome: args?.useHome === true
|
|
24567
|
+
},
|
|
24568
|
+
cfg
|
|
24569
|
+
);
|
|
24570
|
+
if (!rdir.ok) {
|
|
24571
|
+
const ws = getWorkspaceState(cfg);
|
|
24572
|
+
return {
|
|
24573
|
+
success: false,
|
|
24574
|
+
error: rdir.message,
|
|
24575
|
+
code: rdir.code,
|
|
24576
|
+
workspaces: ws.workspaces,
|
|
24577
|
+
defaultWorkspacePath: ws.defaultWorkspacePath
|
|
24578
|
+
};
|
|
24579
|
+
}
|
|
24580
|
+
const dir = rdir.path;
|
|
23800
24581
|
if (!cliType) throw new Error("cliType required");
|
|
23801
24582
|
const found = this.findAdapter(cliType, { instanceKey: args?._targetInstance, dir });
|
|
23802
24583
|
if (found) await this.stopSession(found.key);
|
|
23803
24584
|
await this.startSession(cliType, dir);
|
|
24585
|
+
this.persistRecentDir(cliType, dir);
|
|
23804
24586
|
return { success: true, restarted: true };
|
|
23805
24587
|
}
|
|
23806
24588
|
case "agent_command": {
|
|
@@ -24428,12 +25210,12 @@ ${installInfo}`
|
|
|
24428
25210
|
this.eventListeners = [];
|
|
24429
25211
|
}
|
|
24430
25212
|
};
|
|
24431
|
-
var
|
|
24432
|
-
var
|
|
24433
|
-
var
|
|
24434
|
-
var
|
|
25213
|
+
var fs8 = __toESM2(require("fs"));
|
|
25214
|
+
var path11 = __toESM2(require("path"));
|
|
25215
|
+
var os13 = __toESM2(require("os"));
|
|
25216
|
+
var import_child_process7 = require("child_process");
|
|
24435
25217
|
var import_os3 = require("os");
|
|
24436
|
-
var ARCHIVE_PATH =
|
|
25218
|
+
var ARCHIVE_PATH = path11.join(os13.homedir(), ".adhdev", "version-history.json");
|
|
24437
25219
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
24438
25220
|
var VersionArchive2 = class {
|
|
24439
25221
|
history = {};
|
|
@@ -24442,8 +25224,8 @@ ${installInfo}`
|
|
|
24442
25224
|
}
|
|
24443
25225
|
load() {
|
|
24444
25226
|
try {
|
|
24445
|
-
if (
|
|
24446
|
-
this.history = JSON.parse(
|
|
25227
|
+
if (fs8.existsSync(ARCHIVE_PATH)) {
|
|
25228
|
+
this.history = JSON.parse(fs8.readFileSync(ARCHIVE_PATH, "utf-8"));
|
|
24447
25229
|
}
|
|
24448
25230
|
} catch {
|
|
24449
25231
|
this.history = {};
|
|
@@ -24480,15 +25262,15 @@ ${installInfo}`
|
|
|
24480
25262
|
}
|
|
24481
25263
|
save() {
|
|
24482
25264
|
try {
|
|
24483
|
-
|
|
24484
|
-
|
|
25265
|
+
fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
|
|
25266
|
+
fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
24485
25267
|
} catch {
|
|
24486
25268
|
}
|
|
24487
25269
|
}
|
|
24488
25270
|
};
|
|
24489
25271
|
function runCommand(cmd, timeout = 1e4) {
|
|
24490
25272
|
try {
|
|
24491
|
-
return (0,
|
|
25273
|
+
return (0, import_child_process7.execSync)(cmd, {
|
|
24492
25274
|
encoding: "utf-8",
|
|
24493
25275
|
timeout,
|
|
24494
25276
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -24520,19 +25302,19 @@ ${installInfo}`
|
|
|
24520
25302
|
function checkPathExists2(paths) {
|
|
24521
25303
|
for (const p of paths) {
|
|
24522
25304
|
if (p.includes("*")) {
|
|
24523
|
-
const home =
|
|
24524
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
24525
|
-
if (
|
|
25305
|
+
const home = os13.homedir();
|
|
25306
|
+
const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
|
|
25307
|
+
if (fs8.existsSync(resolved)) return resolved;
|
|
24526
25308
|
} else {
|
|
24527
|
-
if (
|
|
25309
|
+
if (fs8.existsSync(p)) return p;
|
|
24528
25310
|
}
|
|
24529
25311
|
}
|
|
24530
25312
|
return null;
|
|
24531
25313
|
}
|
|
24532
25314
|
function getMacAppVersion(appPath) {
|
|
24533
25315
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
24534
|
-
const plistPath =
|
|
24535
|
-
if (!
|
|
25316
|
+
const plistPath = path11.join(appPath, "Contents", "Info.plist");
|
|
25317
|
+
if (!fs8.existsSync(plistPath)) return null;
|
|
24536
25318
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
24537
25319
|
return raw || null;
|
|
24538
25320
|
}
|
|
@@ -24557,8 +25339,8 @@ ${installInfo}`
|
|
|
24557
25339
|
const cliBin = provider2.cli ? findBinary2(provider2.cli) : null;
|
|
24558
25340
|
let resolvedBin = cliBin;
|
|
24559
25341
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
24560
|
-
const bundled =
|
|
24561
|
-
if (provider2.cli &&
|
|
25342
|
+
const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider2.cli || "");
|
|
25343
|
+
if (provider2.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
|
|
24562
25344
|
}
|
|
24563
25345
|
info.installed = !!(appPath || resolvedBin);
|
|
24564
25346
|
info.path = appPath || null;
|
|
@@ -24595,9 +25377,9 @@ ${installInfo}`
|
|
|
24595
25377
|
return results;
|
|
24596
25378
|
}
|
|
24597
25379
|
var http2 = __toESM2(require("http"));
|
|
24598
|
-
var
|
|
24599
|
-
var
|
|
24600
|
-
var
|
|
25380
|
+
var fs9 = __toESM2(require("fs"));
|
|
25381
|
+
var path12 = __toESM2(require("path"));
|
|
25382
|
+
var os14 = __toESM2(require("os"));
|
|
24601
25383
|
function generateFiles(type, name, category, opts = {}) {
|
|
24602
25384
|
const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
|
|
24603
25385
|
if (category === "cli" || category === "acp") {
|
|
@@ -24996,8 +25778,8 @@ async (params) => {
|
|
|
24996
25778
|
}
|
|
24997
25779
|
getEndpointList() {
|
|
24998
25780
|
return this.routes.map((r) => {
|
|
24999
|
-
const
|
|
25000
|
-
return `${r.method.padEnd(5)} ${
|
|
25781
|
+
const path13 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
25782
|
+
return `${r.method.padEnd(5)} ${path13}`;
|
|
25001
25783
|
});
|
|
25002
25784
|
}
|
|
25003
25785
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -25028,15 +25810,15 @@ async (params) => {
|
|
|
25028
25810
|
this.json(res, 500, { error: e.message });
|
|
25029
25811
|
}
|
|
25030
25812
|
});
|
|
25031
|
-
return new Promise((
|
|
25813
|
+
return new Promise((resolve7, reject) => {
|
|
25032
25814
|
this.server.listen(port, "127.0.0.1", () => {
|
|
25033
25815
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
25034
|
-
|
|
25816
|
+
resolve7();
|
|
25035
25817
|
});
|
|
25036
25818
|
this.server.on("error", (e) => {
|
|
25037
25819
|
if (e.code === "EADDRINUSE") {
|
|
25038
25820
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
25039
|
-
|
|
25821
|
+
resolve7();
|
|
25040
25822
|
} else {
|
|
25041
25823
|
reject(e);
|
|
25042
25824
|
}
|
|
@@ -25119,20 +25901,20 @@ async (params) => {
|
|
|
25119
25901
|
child.stderr?.on("data", (d) => {
|
|
25120
25902
|
stderr += d.toString().slice(0, 2e3);
|
|
25121
25903
|
});
|
|
25122
|
-
await new Promise((
|
|
25904
|
+
await new Promise((resolve7) => {
|
|
25123
25905
|
const timer = setTimeout(() => {
|
|
25124
25906
|
child.kill();
|
|
25125
|
-
|
|
25907
|
+
resolve7();
|
|
25126
25908
|
}, 3e3);
|
|
25127
25909
|
child.on("exit", () => {
|
|
25128
25910
|
clearTimeout(timer);
|
|
25129
|
-
|
|
25911
|
+
resolve7();
|
|
25130
25912
|
});
|
|
25131
25913
|
child.stdout?.once("data", () => {
|
|
25132
25914
|
setTimeout(() => {
|
|
25133
25915
|
child.kill();
|
|
25134
25916
|
clearTimeout(timer);
|
|
25135
|
-
|
|
25917
|
+
resolve7();
|
|
25136
25918
|
}, 500);
|
|
25137
25919
|
});
|
|
25138
25920
|
});
|
|
@@ -25342,12 +26124,12 @@ async (params) => {
|
|
|
25342
26124
|
// ─── DevConsole SPA ───
|
|
25343
26125
|
getConsoleDistDir() {
|
|
25344
26126
|
const candidates = [
|
|
25345
|
-
|
|
25346
|
-
|
|
25347
|
-
|
|
26127
|
+
path12.resolve(__dirname, "../../web-devconsole/dist"),
|
|
26128
|
+
path12.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
26129
|
+
path12.join(process.cwd(), "packages/web-devconsole/dist")
|
|
25348
26130
|
];
|
|
25349
26131
|
for (const dir of candidates) {
|
|
25350
|
-
if (
|
|
26132
|
+
if (fs9.existsSync(path12.join(dir, "index.html"))) return dir;
|
|
25351
26133
|
}
|
|
25352
26134
|
return null;
|
|
25353
26135
|
}
|
|
@@ -25357,9 +26139,9 @@ async (params) => {
|
|
|
25357
26139
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
25358
26140
|
return;
|
|
25359
26141
|
}
|
|
25360
|
-
const htmlPath =
|
|
26142
|
+
const htmlPath = path12.join(distDir, "index.html");
|
|
25361
26143
|
try {
|
|
25362
|
-
const html =
|
|
26144
|
+
const html = fs9.readFileSync(htmlPath, "utf-8");
|
|
25363
26145
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
25364
26146
|
res.end(html);
|
|
25365
26147
|
} catch (e) {
|
|
@@ -25382,15 +26164,15 @@ async (params) => {
|
|
|
25382
26164
|
this.json(res, 404, { error: "Not found" });
|
|
25383
26165
|
return;
|
|
25384
26166
|
}
|
|
25385
|
-
const safePath =
|
|
25386
|
-
const filePath =
|
|
26167
|
+
const safePath = path12.normalize(pathname).replace(/^\.\.\//, "");
|
|
26168
|
+
const filePath = path12.join(distDir, safePath);
|
|
25387
26169
|
if (!filePath.startsWith(distDir)) {
|
|
25388
26170
|
this.json(res, 403, { error: "Forbidden" });
|
|
25389
26171
|
return;
|
|
25390
26172
|
}
|
|
25391
26173
|
try {
|
|
25392
|
-
const content =
|
|
25393
|
-
const ext =
|
|
26174
|
+
const content = fs9.readFileSync(filePath);
|
|
26175
|
+
const ext = path12.extname(filePath);
|
|
25394
26176
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
25395
26177
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
25396
26178
|
res.end(content);
|
|
@@ -25489,26 +26271,26 @@ async (params) => {
|
|
|
25489
26271
|
const provider2 = this.providerLoader.getMeta(type);
|
|
25490
26272
|
if (!provider2) return null;
|
|
25491
26273
|
const cat = provider2.category;
|
|
25492
|
-
const builtinDir = this.providerLoader.builtinDir ||
|
|
25493
|
-
const userDir =
|
|
26274
|
+
const builtinDir = this.providerLoader.builtinDir || path12.resolve(__dirname, "../providers/_builtin");
|
|
26275
|
+
const userDir = path12.join(os14.homedir(), ".adhdev", "providers");
|
|
25494
26276
|
const directCandidates = [
|
|
25495
|
-
|
|
25496
|
-
|
|
25497
|
-
|
|
26277
|
+
path12.join(userDir, type),
|
|
26278
|
+
path12.join(builtinDir, cat, type),
|
|
26279
|
+
path12.join(builtinDir, type)
|
|
25498
26280
|
];
|
|
25499
26281
|
for (const d of directCandidates) {
|
|
25500
|
-
if (
|
|
26282
|
+
if (fs9.existsSync(path12.join(d, "provider.json"))) return d;
|
|
25501
26283
|
}
|
|
25502
|
-
const catDir =
|
|
25503
|
-
if (
|
|
26284
|
+
const catDir = path12.join(builtinDir, cat);
|
|
26285
|
+
if (fs9.existsSync(catDir)) {
|
|
25504
26286
|
try {
|
|
25505
|
-
for (const entry of
|
|
26287
|
+
for (const entry of fs9.readdirSync(catDir, { withFileTypes: true })) {
|
|
25506
26288
|
if (!entry.isDirectory()) continue;
|
|
25507
|
-
const jsonPath =
|
|
25508
|
-
if (
|
|
26289
|
+
const jsonPath = path12.join(catDir, entry.name, "provider.json");
|
|
26290
|
+
if (fs9.existsSync(jsonPath)) {
|
|
25509
26291
|
try {
|
|
25510
|
-
const data = JSON.parse(
|
|
25511
|
-
if (data.type === type) return
|
|
26292
|
+
const data = JSON.parse(fs9.readFileSync(jsonPath, "utf-8"));
|
|
26293
|
+
if (data.type === type) return path12.join(catDir, entry.name);
|
|
25512
26294
|
} catch {
|
|
25513
26295
|
}
|
|
25514
26296
|
}
|
|
@@ -25528,14 +26310,14 @@ async (params) => {
|
|
|
25528
26310
|
const files = [];
|
|
25529
26311
|
const scan = (d, prefix) => {
|
|
25530
26312
|
try {
|
|
25531
|
-
for (const entry of
|
|
26313
|
+
for (const entry of fs9.readdirSync(d, { withFileTypes: true })) {
|
|
25532
26314
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
25533
26315
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
25534
26316
|
if (entry.isDirectory()) {
|
|
25535
26317
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
25536
|
-
scan(
|
|
26318
|
+
scan(path12.join(d, entry.name), rel);
|
|
25537
26319
|
} else {
|
|
25538
|
-
const stat =
|
|
26320
|
+
const stat = fs9.statSync(path12.join(d, entry.name));
|
|
25539
26321
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
25540
26322
|
}
|
|
25541
26323
|
}
|
|
@@ -25558,16 +26340,16 @@ async (params) => {
|
|
|
25558
26340
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
25559
26341
|
return;
|
|
25560
26342
|
}
|
|
25561
|
-
const fullPath =
|
|
26343
|
+
const fullPath = path12.resolve(dir, path12.normalize(filePath));
|
|
25562
26344
|
if (!fullPath.startsWith(dir)) {
|
|
25563
26345
|
this.json(res, 403, { error: "Forbidden" });
|
|
25564
26346
|
return;
|
|
25565
26347
|
}
|
|
25566
|
-
if (!
|
|
26348
|
+
if (!fs9.existsSync(fullPath) || fs9.statSync(fullPath).isDirectory()) {
|
|
25567
26349
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
25568
26350
|
return;
|
|
25569
26351
|
}
|
|
25570
|
-
const content =
|
|
26352
|
+
const content = fs9.readFileSync(fullPath, "utf-8");
|
|
25571
26353
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
25572
26354
|
}
|
|
25573
26355
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -25583,15 +26365,15 @@ async (params) => {
|
|
|
25583
26365
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
25584
26366
|
return;
|
|
25585
26367
|
}
|
|
25586
|
-
const fullPath =
|
|
26368
|
+
const fullPath = path12.resolve(dir, path12.normalize(filePath));
|
|
25587
26369
|
if (!fullPath.startsWith(dir)) {
|
|
25588
26370
|
this.json(res, 403, { error: "Forbidden" });
|
|
25589
26371
|
return;
|
|
25590
26372
|
}
|
|
25591
26373
|
try {
|
|
25592
|
-
if (
|
|
25593
|
-
|
|
25594
|
-
|
|
26374
|
+
if (fs9.existsSync(fullPath)) fs9.copyFileSync(fullPath, fullPath + ".bak");
|
|
26375
|
+
fs9.mkdirSync(path12.dirname(fullPath), { recursive: true });
|
|
26376
|
+
fs9.writeFileSync(fullPath, content, "utf-8");
|
|
25595
26377
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
25596
26378
|
this.providerLoader.reload();
|
|
25597
26379
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -25607,9 +26389,9 @@ async (params) => {
|
|
|
25607
26389
|
return;
|
|
25608
26390
|
}
|
|
25609
26391
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
25610
|
-
const p =
|
|
25611
|
-
if (
|
|
25612
|
-
const source =
|
|
26392
|
+
const p = path12.join(dir, name);
|
|
26393
|
+
if (fs9.existsSync(p)) {
|
|
26394
|
+
const source = fs9.readFileSync(p, "utf-8");
|
|
25613
26395
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
25614
26396
|
return;
|
|
25615
26397
|
}
|
|
@@ -25628,11 +26410,11 @@ async (params) => {
|
|
|
25628
26410
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
25629
26411
|
return;
|
|
25630
26412
|
}
|
|
25631
|
-
const target =
|
|
25632
|
-
const targetPath =
|
|
26413
|
+
const target = fs9.existsSync(path12.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
26414
|
+
const targetPath = path12.join(dir, target);
|
|
25633
26415
|
try {
|
|
25634
|
-
if (
|
|
25635
|
-
|
|
26416
|
+
if (fs9.existsSync(targetPath)) fs9.copyFileSync(targetPath, targetPath + ".bak");
|
|
26417
|
+
fs9.writeFileSync(targetPath, source, "utf-8");
|
|
25636
26418
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
25637
26419
|
this.providerLoader.reload();
|
|
25638
26420
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -25647,18 +26429,18 @@ async (params) => {
|
|
|
25647
26429
|
return;
|
|
25648
26430
|
}
|
|
25649
26431
|
let scriptsPath = "";
|
|
25650
|
-
const directScripts =
|
|
25651
|
-
if (
|
|
26432
|
+
const directScripts = path12.join(dir, "scripts.js");
|
|
26433
|
+
if (fs9.existsSync(directScripts)) {
|
|
25652
26434
|
scriptsPath = directScripts;
|
|
25653
26435
|
} else {
|
|
25654
|
-
const scriptsDir =
|
|
25655
|
-
if (
|
|
25656
|
-
const versions =
|
|
25657
|
-
return
|
|
26436
|
+
const scriptsDir = path12.join(dir, "scripts");
|
|
26437
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
26438
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
26439
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
25658
26440
|
}).sort().reverse();
|
|
25659
26441
|
for (const ver of versions) {
|
|
25660
|
-
const p =
|
|
25661
|
-
if (
|
|
26442
|
+
const p = path12.join(scriptsDir, ver, "scripts.js");
|
|
26443
|
+
if (fs9.existsSync(p)) {
|
|
25662
26444
|
scriptsPath = p;
|
|
25663
26445
|
break;
|
|
25664
26446
|
}
|
|
@@ -25670,7 +26452,7 @@ async (params) => {
|
|
|
25670
26452
|
return;
|
|
25671
26453
|
}
|
|
25672
26454
|
try {
|
|
25673
|
-
const source =
|
|
26455
|
+
const source = fs9.readFileSync(scriptsPath, "utf-8");
|
|
25674
26456
|
const hints = {};
|
|
25675
26457
|
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
25676
26458
|
let match;
|
|
@@ -25814,14 +26596,14 @@ async (params) => {
|
|
|
25814
26596
|
child.stderr?.on("data", (d) => {
|
|
25815
26597
|
stderr += d.toString();
|
|
25816
26598
|
});
|
|
25817
|
-
await new Promise((
|
|
26599
|
+
await new Promise((resolve7) => {
|
|
25818
26600
|
const timer = setTimeout(() => {
|
|
25819
26601
|
child.kill();
|
|
25820
|
-
|
|
26602
|
+
resolve7();
|
|
25821
26603
|
}, timeout);
|
|
25822
26604
|
child.on("exit", () => {
|
|
25823
26605
|
clearTimeout(timer);
|
|
25824
|
-
|
|
26606
|
+
resolve7();
|
|
25825
26607
|
});
|
|
25826
26608
|
});
|
|
25827
26609
|
const elapsed = Date.now() - start;
|
|
@@ -25871,26 +26653,26 @@ async (params) => {
|
|
|
25871
26653
|
}
|
|
25872
26654
|
let targetDir;
|
|
25873
26655
|
if (location === "user") {
|
|
25874
|
-
targetDir =
|
|
26656
|
+
targetDir = path12.join(os14.homedir(), ".adhdev", "providers", type);
|
|
25875
26657
|
} else {
|
|
25876
|
-
const builtinDir =
|
|
25877
|
-
targetDir =
|
|
26658
|
+
const builtinDir = path12.resolve(__dirname, "../providers/_builtin");
|
|
26659
|
+
targetDir = path12.join(builtinDir, category, type);
|
|
25878
26660
|
}
|
|
25879
|
-
const jsonPath =
|
|
25880
|
-
if (
|
|
26661
|
+
const jsonPath = path12.join(targetDir, "provider.json");
|
|
26662
|
+
if (fs9.existsSync(jsonPath)) {
|
|
25881
26663
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
25882
26664
|
return;
|
|
25883
26665
|
}
|
|
25884
26666
|
try {
|
|
25885
26667
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 });
|
|
25886
|
-
|
|
25887
|
-
|
|
26668
|
+
fs9.mkdirSync(targetDir, { recursive: true });
|
|
26669
|
+
fs9.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
25888
26670
|
const createdFiles = ["provider.json"];
|
|
25889
26671
|
if (result.files) {
|
|
25890
26672
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
25891
|
-
const fullPath =
|
|
25892
|
-
|
|
25893
|
-
|
|
26673
|
+
const fullPath = path12.join(targetDir, relPath);
|
|
26674
|
+
fs9.mkdirSync(path12.dirname(fullPath), { recursive: true });
|
|
26675
|
+
fs9.writeFileSync(fullPath, content, "utf-8");
|
|
25894
26676
|
createdFiles.push(relPath);
|
|
25895
26677
|
}
|
|
25896
26678
|
}
|
|
@@ -26725,24 +27507,24 @@ async (params) => {
|
|
|
26725
27507
|
}
|
|
26726
27508
|
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "loading_reference", message: `\uB808\uD37C\uB7F0\uC2A4 \uC2A4\uD06C\uB9BD\uD2B8 \uB85C\uB4DC \uC911 (${reference})...` } });
|
|
26727
27509
|
let referenceScripts = {};
|
|
26728
|
-
const builtinDir = this.providerLoader.builtinDir ||
|
|
26729
|
-
const refDir =
|
|
26730
|
-
if (
|
|
26731
|
-
const scriptsDir =
|
|
26732
|
-
if (
|
|
26733
|
-
const versions =
|
|
27510
|
+
const builtinDir = this.providerLoader.builtinDir || path12.resolve(__dirname, "../providers/_builtin");
|
|
27511
|
+
const refDir = path12.join(builtinDir, "ide", reference);
|
|
27512
|
+
if (fs9.existsSync(refDir)) {
|
|
27513
|
+
const scriptsDir = path12.join(refDir, "scripts");
|
|
27514
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
27515
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
26734
27516
|
try {
|
|
26735
|
-
return
|
|
27517
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
26736
27518
|
} catch {
|
|
26737
27519
|
return false;
|
|
26738
27520
|
}
|
|
26739
27521
|
}).sort().reverse();
|
|
26740
27522
|
if (versions.length > 0) {
|
|
26741
|
-
const latestDir =
|
|
26742
|
-
for (const file2 of
|
|
27523
|
+
const latestDir = path12.join(scriptsDir, versions[0]);
|
|
27524
|
+
for (const file2 of fs9.readdirSync(latestDir)) {
|
|
26743
27525
|
if (file2.endsWith(".js")) {
|
|
26744
27526
|
try {
|
|
26745
|
-
referenceScripts[file2] =
|
|
27527
|
+
referenceScripts[file2] = fs9.readFileSync(path12.join(latestDir, file2), "utf-8");
|
|
26746
27528
|
} catch {
|
|
26747
27529
|
}
|
|
26748
27530
|
}
|
|
@@ -26751,16 +27533,16 @@ async (params) => {
|
|
|
26751
27533
|
}
|
|
26752
27534
|
}
|
|
26753
27535
|
const prompt = this.buildAutoImplPrompt(type, provider2, providerDir, functions, domContext, referenceScripts);
|
|
26754
|
-
const tmpDir =
|
|
26755
|
-
if (!
|
|
26756
|
-
const promptFile =
|
|
26757
|
-
|
|
27536
|
+
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
27537
|
+
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
27538
|
+
const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
27539
|
+
fs9.writeFileSync(promptFile, prompt, "utf-8");
|
|
26758
27540
|
this.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
26759
27541
|
const agentProvider = this.providerLoader.resolve(agent) || this.providerLoader.getMeta(agent);
|
|
26760
27542
|
const spawn3 = agentProvider?.spawn;
|
|
26761
27543
|
if (!spawn3?.command) {
|
|
26762
27544
|
try {
|
|
26763
|
-
|
|
27545
|
+
fs9.unlinkSync(promptFile);
|
|
26764
27546
|
} catch {
|
|
26765
27547
|
}
|
|
26766
27548
|
this.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -26861,7 +27643,7 @@ async (params) => {
|
|
|
26861
27643
|
} catch {
|
|
26862
27644
|
}
|
|
26863
27645
|
try {
|
|
26864
|
-
|
|
27646
|
+
fs9.unlinkSync(promptFile);
|
|
26865
27647
|
} catch {
|
|
26866
27648
|
}
|
|
26867
27649
|
this.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -26917,12 +27699,12 @@ async (params) => {
|
|
|
26917
27699
|
} else {
|
|
26918
27700
|
args = [...baseArgs];
|
|
26919
27701
|
}
|
|
26920
|
-
const { execSync:
|
|
27702
|
+
const { execSync: execSync7 } = await import("child_process");
|
|
26921
27703
|
try {
|
|
26922
|
-
|
|
27704
|
+
execSync7(`which ${command}`, { stdio: "pipe" });
|
|
26923
27705
|
} catch {
|
|
26924
27706
|
try {
|
|
26925
|
-
|
|
27707
|
+
fs9.unlinkSync(promptFile);
|
|
26926
27708
|
} catch {
|
|
26927
27709
|
}
|
|
26928
27710
|
this.json(res, 400, { error: `Agent binary '${command}' not found on PATH. Install it first: ${agentProvider?.install || "check provider docs"}` });
|
|
@@ -26978,7 +27760,7 @@ async (params) => {
|
|
|
26978
27760
|
} catch {
|
|
26979
27761
|
}
|
|
26980
27762
|
try {
|
|
26981
|
-
|
|
27763
|
+
fs9.unlinkSync(promptFile);
|
|
26982
27764
|
} catch {
|
|
26983
27765
|
}
|
|
26984
27766
|
this.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -27008,23 +27790,23 @@ async (params) => {
|
|
|
27008
27790
|
lines.push("## Current Target Files");
|
|
27009
27791
|
lines.push("These are the files you need to EDIT. They contain TODO stubs \u2014 replace them with working implementations.");
|
|
27010
27792
|
lines.push("");
|
|
27011
|
-
const scriptsDir =
|
|
27012
|
-
if (
|
|
27013
|
-
const versions =
|
|
27793
|
+
const scriptsDir = path12.join(providerDir, "scripts");
|
|
27794
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
27795
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
27014
27796
|
try {
|
|
27015
|
-
return
|
|
27797
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
27016
27798
|
} catch {
|
|
27017
27799
|
return false;
|
|
27018
27800
|
}
|
|
27019
27801
|
}).sort().reverse();
|
|
27020
27802
|
if (versions.length > 0) {
|
|
27021
|
-
const vDir =
|
|
27803
|
+
const vDir = path12.join(scriptsDir, versions[0]);
|
|
27022
27804
|
lines.push(`Scripts version directory: \`${vDir}\``);
|
|
27023
27805
|
lines.push("");
|
|
27024
|
-
for (const file2 of
|
|
27806
|
+
for (const file2 of fs9.readdirSync(vDir)) {
|
|
27025
27807
|
if (file2.endsWith(".js")) {
|
|
27026
27808
|
try {
|
|
27027
|
-
const content =
|
|
27809
|
+
const content = fs9.readFileSync(path12.join(vDir, file2), "utf-8");
|
|
27028
27810
|
lines.push(`### \`${file2}\``);
|
|
27029
27811
|
lines.push("```javascript");
|
|
27030
27812
|
lines.push(content);
|
|
@@ -27095,7 +27877,7 @@ async (params) => {
|
|
|
27095
27877
|
lines.push("## Required Return Format");
|
|
27096
27878
|
lines.push("| Function | Return JSON |");
|
|
27097
27879
|
lines.push("|---|---|");
|
|
27098
|
-
lines.push("| readChat | `{ id, status, title, messages: [{role, content, index}], inputContent, activeModal }` |");
|
|
27880
|
+
lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal }` \u2014 optional `kind`: standard, thought, tool, terminal; optional `meta`: e.g. `{ label, isRunning }` for dashboard |");
|
|
27099
27881
|
lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
|
|
27100
27882
|
lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
|
|
27101
27883
|
lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
|
|
@@ -27219,20 +28001,20 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27219
28001
|
res.end(JSON.stringify(data, null, 2));
|
|
27220
28002
|
}
|
|
27221
28003
|
async readBody(req) {
|
|
27222
|
-
return new Promise((
|
|
28004
|
+
return new Promise((resolve7) => {
|
|
27223
28005
|
let body = "";
|
|
27224
28006
|
req.on("data", (chunk) => body += chunk);
|
|
27225
28007
|
req.on("end", () => {
|
|
27226
28008
|
try {
|
|
27227
|
-
|
|
28009
|
+
resolve7(JSON.parse(body));
|
|
27228
28010
|
} catch {
|
|
27229
|
-
|
|
28011
|
+
resolve7({});
|
|
27230
28012
|
}
|
|
27231
28013
|
});
|
|
27232
28014
|
});
|
|
27233
28015
|
}
|
|
27234
28016
|
};
|
|
27235
|
-
var
|
|
28017
|
+
var import_child_process8 = require("child_process");
|
|
27236
28018
|
var EXTENSION_CATALOG = [
|
|
27237
28019
|
// AI Agent extensions
|
|
27238
28020
|
{
|
|
@@ -27309,7 +28091,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27309
28091
|
function isExtensionInstalled(ide, marketplaceId) {
|
|
27310
28092
|
if (!ide.cliCommand) return false;
|
|
27311
28093
|
try {
|
|
27312
|
-
const result = (0,
|
|
28094
|
+
const result = (0, import_child_process8.execSync)(`"${ide.cliCommand}" --list-extensions`, {
|
|
27313
28095
|
encoding: "utf-8",
|
|
27314
28096
|
timeout: 15e3,
|
|
27315
28097
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -27346,12 +28128,12 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27346
28128
|
const res = await fetch(extension.vsixUrl);
|
|
27347
28129
|
if (res.ok) {
|
|
27348
28130
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
27349
|
-
const
|
|
27350
|
-
|
|
27351
|
-
return new Promise((
|
|
28131
|
+
const fs10 = await import("fs");
|
|
28132
|
+
fs10.writeFileSync(vsixPath, buffer);
|
|
28133
|
+
return new Promise((resolve7) => {
|
|
27352
28134
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
27353
|
-
(0,
|
|
27354
|
-
|
|
28135
|
+
(0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
|
|
28136
|
+
resolve7({
|
|
27355
28137
|
extensionId: extension.id,
|
|
27356
28138
|
marketplaceId: extension.marketplaceId,
|
|
27357
28139
|
success: !error48,
|
|
@@ -27364,11 +28146,11 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27364
28146
|
} catch (e) {
|
|
27365
28147
|
}
|
|
27366
28148
|
}
|
|
27367
|
-
return new Promise((
|
|
28149
|
+
return new Promise((resolve7) => {
|
|
27368
28150
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
27369
|
-
(0,
|
|
28151
|
+
(0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
|
|
27370
28152
|
if (error48) {
|
|
27371
|
-
|
|
28153
|
+
resolve7({
|
|
27372
28154
|
extensionId: extension.id,
|
|
27373
28155
|
marketplaceId: extension.marketplaceId,
|
|
27374
28156
|
success: false,
|
|
@@ -27376,7 +28158,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27376
28158
|
error: stderr || error48.message
|
|
27377
28159
|
});
|
|
27378
28160
|
} else {
|
|
27379
|
-
|
|
28161
|
+
resolve7({
|
|
27380
28162
|
extensionId: extension.id,
|
|
27381
28163
|
marketplaceId: extension.marketplaceId,
|
|
27382
28164
|
success: true,
|
|
@@ -27403,7 +28185,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27403
28185
|
if (!ide.cliCommand) return false;
|
|
27404
28186
|
try {
|
|
27405
28187
|
const args = workspacePath ? `"${workspacePath}"` : "";
|
|
27406
|
-
(0,
|
|
28188
|
+
(0, import_child_process8.exec)(`"${ide.cliCommand}" ${args}`, { timeout: 1e4 });
|
|
27407
28189
|
return true;
|
|
27408
28190
|
} catch {
|
|
27409
28191
|
return false;
|
|
@@ -27762,7 +28544,7 @@ var init_server_connection = __esm({
|
|
|
27762
28544
|
});
|
|
27763
28545
|
|
|
27764
28546
|
// src/daemon-p2p.ts
|
|
27765
|
-
var fs, import_daemon_core2, path, os, logFile, log, logDebug, DaemonP2PSender;
|
|
28547
|
+
var fs, import_daemon_core2, path, os, import_node_module, import_meta, esmRequire, logFile, log, logDebug, DaemonP2PSender;
|
|
27766
28548
|
var init_daemon_p2p = __esm({
|
|
27767
28549
|
"src/daemon-p2p.ts"() {
|
|
27768
28550
|
"use strict";
|
|
@@ -27770,6 +28552,9 @@ var init_daemon_p2p = __esm({
|
|
|
27770
28552
|
import_daemon_core2 = __toESM(require_dist());
|
|
27771
28553
|
path = __toESM(require("path"));
|
|
27772
28554
|
os = __toESM(require("os"));
|
|
28555
|
+
import_node_module = require("module");
|
|
28556
|
+
import_meta = {};
|
|
28557
|
+
esmRequire = (0, import_node_module.createRequire)(import_meta.url);
|
|
27773
28558
|
logFile = path.join(os.tmpdir(), "adhdev_daemon_p2p.log");
|
|
27774
28559
|
log = (msg) => {
|
|
27775
28560
|
import_daemon_core2.LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
|
|
@@ -27814,12 +28599,13 @@ var init_daemon_p2p = __esm({
|
|
|
27814
28599
|
/** node-datachannel Load */
|
|
27815
28600
|
tryLoadNodeDatachannel() {
|
|
27816
28601
|
try {
|
|
27817
|
-
this.nodeDatachannel =
|
|
28602
|
+
this.nodeDatachannel = esmRequire("node-datachannel");
|
|
27818
28603
|
const keys = Object.keys(this.nodeDatachannel).join(",");
|
|
27819
28604
|
log(`node-datachannel loaded \u2705 (keys: ${keys.substring(0, 100)})`);
|
|
27820
28605
|
return;
|
|
27821
28606
|
} catch (e) {
|
|
27822
|
-
log(`node-datachannel not found: ${e?.message}
|
|
28607
|
+
log(`node-datachannel not found: ${e?.message}
|
|
28608
|
+
${e?.stack || ""}`);
|
|
27823
28609
|
}
|
|
27824
28610
|
const platform2 = process.platform;
|
|
27825
28611
|
const arch = process.arch;
|
|
@@ -27838,10 +28624,10 @@ var init_daemon_p2p = __esm({
|
|
|
27838
28624
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
27839
28625
|
fs.copyFileSync(prebuildPath, targetPath);
|
|
27840
28626
|
try {
|
|
27841
|
-
delete
|
|
28627
|
+
delete esmRequire.cache[esmRequire.resolve("node-datachannel")];
|
|
27842
28628
|
} catch {
|
|
27843
28629
|
}
|
|
27844
|
-
this.nodeDatachannel =
|
|
28630
|
+
this.nodeDatachannel = esmRequire("node-datachannel");
|
|
27845
28631
|
log(`node-datachannel loaded from prebuild (${prebuildKey}) \u2705`);
|
|
27846
28632
|
return;
|
|
27847
28633
|
}
|
|
@@ -27917,7 +28703,7 @@ var init_daemon_p2p = __esm({
|
|
|
27917
28703
|
token = config2.connectionToken || "";
|
|
27918
28704
|
} catch {
|
|
27919
28705
|
}
|
|
27920
|
-
const http =
|
|
28706
|
+
const http = esmRequire("https");
|
|
27921
28707
|
const data = await new Promise((resolve, reject) => {
|
|
27922
28708
|
const req = http.get(`${serverUrl}/api/v1/turn/credentials`, {
|
|
27923
28709
|
headers: { "Authorization": `Bearer ${token}` }
|
|
@@ -28015,14 +28801,27 @@ var init_daemon_p2p = __esm({
|
|
|
28015
28801
|
converted.push(url2);
|
|
28016
28802
|
} else if ((url2.startsWith("turn:") || url2.startsWith("turns:")) && server.username && server.credential) {
|
|
28017
28803
|
const cleanUrl = url2.split("?")[0];
|
|
28018
|
-
const
|
|
28019
|
-
|
|
28804
|
+
const transport = url2.includes("transport=tcp") ? "tcp" : "udp";
|
|
28805
|
+
const isTls = url2.startsWith("turns:");
|
|
28806
|
+
const parts = cleanUrl.replace(/^turns?:/, "").split(":");
|
|
28807
|
+
const hostname4 = parts[0];
|
|
28808
|
+
const port = parseInt(parts[1]) || (isTls ? 5349 : 3478);
|
|
28809
|
+
let relayType = "TurnUdp";
|
|
28810
|
+
if (isTls) relayType = "TurnTls";
|
|
28811
|
+
else if (transport === "tcp") relayType = "TurnTcp";
|
|
28812
|
+
converted.push({
|
|
28813
|
+
hostname: hostname4,
|
|
28814
|
+
port,
|
|
28815
|
+
username: server.username,
|
|
28816
|
+
password: server.credential,
|
|
28817
|
+
relayType
|
|
28818
|
+
});
|
|
28020
28819
|
}
|
|
28021
28820
|
}
|
|
28022
28821
|
}
|
|
28023
28822
|
if (converted.length > 0) {
|
|
28024
28823
|
iceServers = converted;
|
|
28025
|
-
const hasTurn = converted.some((s) => s
|
|
28824
|
+
const hasTurn = converted.some((s) => typeof s === "object");
|
|
28026
28825
|
log(`ICE servers from auth: ${converted.length} (TURN: ${hasTurn ? "\u2705" : "\u274C"})`);
|
|
28027
28826
|
}
|
|
28028
28827
|
}
|
|
@@ -28046,17 +28845,18 @@ var init_daemon_p2p = __esm({
|
|
|
28046
28845
|
const timeout = setTimeout(() => {
|
|
28047
28846
|
const peer = this.peers.get(pid);
|
|
28048
28847
|
if (peer?.state === "connecting") {
|
|
28049
|
-
log(`connection timeout (
|
|
28848
|
+
log(`connection timeout (30s) for peer ${pid}`);
|
|
28050
28849
|
peer.state = "failed";
|
|
28051
28850
|
this.notifyStateChange();
|
|
28052
28851
|
}
|
|
28053
|
-
},
|
|
28852
|
+
}, 3e4);
|
|
28054
28853
|
try {
|
|
28055
28854
|
pc.onLocalDescription((sdp, type) => {
|
|
28056
28855
|
log(`onLocalDescription for peer ${pid}: type=${type}`);
|
|
28057
28856
|
this.serverConn.sendMessage("p2p_offer", { sdp, type, peerId: pid });
|
|
28058
28857
|
});
|
|
28059
28858
|
pc.onLocalCandidate((candidate, mid) => {
|
|
28859
|
+
log(`onLocalCandidate for peer ${pid}: ${candidate.substring(0, 80)}`);
|
|
28060
28860
|
this.serverConn.sendMessage("p2p_ice", { candidate, mid, peerId: pid });
|
|
28061
28861
|
});
|
|
28062
28862
|
pc.onStateChange((pcState) => {
|
|
@@ -28401,6 +29201,10 @@ var init_daemon_p2p = __esm({
|
|
|
28401
29201
|
log(`p2p_answer for unknown peer ${peerId} \u2014 ignoring`);
|
|
28402
29202
|
return;
|
|
28403
29203
|
}
|
|
29204
|
+
if (peer.remoteDescriptionSet) {
|
|
29205
|
+
log(`p2p_answer ignored: already applied for peer ${peerId} (duplicate relay)`);
|
|
29206
|
+
return;
|
|
29207
|
+
}
|
|
28404
29208
|
const pcState = peer.pc.state();
|
|
28405
29209
|
if (pcState === "closed" || pcState === "failed") {
|
|
28406
29210
|
log(`p2p_answer ignored: peer ${peerId} PC state is ${pcState}`);
|
|
@@ -28433,11 +29237,13 @@ var init_daemon_p2p = __esm({
|
|
|
28433
29237
|
}
|
|
28434
29238
|
const peer = this.peers.get(peerId);
|
|
28435
29239
|
if (peer?.pc && payload.candidate) {
|
|
29240
|
+
log(`p2p_ice received from peer ${peerId}: ${String(payload.candidate).substring(0, 80)}`);
|
|
28436
29241
|
if (!peer.remoteDescriptionSet) {
|
|
28437
29242
|
peer.pendingCandidates.push({
|
|
28438
29243
|
candidate: payload.candidate,
|
|
28439
29244
|
mid: payload.mid || payload.sdpMid || "0"
|
|
28440
29245
|
});
|
|
29246
|
+
log(`Queued ICE candidate (remoteDesc not set yet), queue size: ${peer.pendingCandidates.length}`);
|
|
28441
29247
|
} else {
|
|
28442
29248
|
try {
|
|
28443
29249
|
peer.pc.addRemoteCandidate(payload.candidate, payload.mid || payload.sdpMid || "0");
|
|
@@ -28445,6 +29251,8 @@ var init_daemon_p2p = __esm({
|
|
|
28445
29251
|
log(`ICE candidate error for peer ${peerId}: ${e?.message}`);
|
|
28446
29252
|
}
|
|
28447
29253
|
}
|
|
29254
|
+
} else {
|
|
29255
|
+
log(`p2p_ice ignored: peer=${!!peer}, pc=${!!peer?.pc}, candidate=${!!payload.candidate}`);
|
|
28448
29256
|
}
|
|
28449
29257
|
return;
|
|
28450
29258
|
}
|
|
@@ -28865,8 +29673,10 @@ var init_adhdev_daemon = __esm({
|
|
|
28865
29673
|
this.p2p.onStateChange((state) => {
|
|
28866
29674
|
if (state === "connected") {
|
|
28867
29675
|
import_daemon_core4.LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
|
|
29676
|
+
this.statusReporter?.resetP2PHash();
|
|
28868
29677
|
this.statusReporter?.sendUnifiedStatusReport().catch((e) => import_daemon_core4.LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
|
|
28869
29678
|
setTimeout(() => {
|
|
29679
|
+
this.statusReporter?.resetP2PHash();
|
|
28870
29680
|
this.statusReporter?.sendUnifiedStatusReport().catch(() => {
|
|
28871
29681
|
});
|
|
28872
29682
|
}, 2e3);
|
|
@@ -28998,6 +29808,7 @@ var init_adhdev_daemon = __esm({
|
|
|
28998
29808
|
"open_recent",
|
|
28999
29809
|
"get_commands",
|
|
29000
29810
|
"get_recent_workspaces",
|
|
29811
|
+
"get_cli_history",
|
|
29001
29812
|
"open_panel",
|
|
29002
29813
|
"open_file",
|
|
29003
29814
|
"create_terminal",
|
|
@@ -29054,6 +29865,7 @@ var init_adhdev_daemon = __esm({
|
|
|
29054
29865
|
return;
|
|
29055
29866
|
}
|
|
29056
29867
|
const result = await this.components.router.execute(cmd, args, source);
|
|
29868
|
+
if (cmd.startsWith("workspace_")) this.statusReporter?.throttledReport();
|
|
29057
29869
|
this.sendResult(msg, result.success, result);
|
|
29058
29870
|
} catch (e) {
|
|
29059
29871
|
console.error(import_chalk.default.red(` \u2717 Command failed: ${e.message}`));
|
|
@@ -29085,7 +29897,9 @@ var init_adhdev_daemon = __esm({
|
|
|
29085
29897
|
return { success: true, history };
|
|
29086
29898
|
}
|
|
29087
29899
|
}
|
|
29088
|
-
|
|
29900
|
+
const routed = await this.components.router.execute(cmdType, data, "p2p");
|
|
29901
|
+
if (cmdType.startsWith("workspace_")) this.statusReporter?.throttledReport();
|
|
29902
|
+
return routed;
|
|
29089
29903
|
} catch (e) {
|
|
29090
29904
|
(0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: false, error: e.message, durationMs: Date.now() - cmdStart });
|
|
29091
29905
|
return { success: false, error: e.message };
|
|
@@ -29146,9 +29960,16 @@ var init_adhdev_daemon = __esm({
|
|
|
29146
29960
|
}
|
|
29147
29961
|
return null;
|
|
29148
29962
|
}
|
|
29149
|
-
/** Return CDP manager for specific IDE */
|
|
29963
|
+
/** Return CDP manager for specific IDE (exact match first, then prefix match for multi-window keys) */
|
|
29150
29964
|
getCdpFor(ideType) {
|
|
29151
|
-
|
|
29965
|
+
if (!this.components) return null;
|
|
29966
|
+
const key = ideType.toLowerCase();
|
|
29967
|
+
const exact = this.components.cdpManagers.get(key);
|
|
29968
|
+
if (exact) return exact;
|
|
29969
|
+
for (const [k, m] of this.components.cdpManagers.entries()) {
|
|
29970
|
+
if (k.startsWith(key + "_") && m.isConnected) return m;
|
|
29971
|
+
}
|
|
29972
|
+
return null;
|
|
29152
29973
|
}
|
|
29153
29974
|
};
|
|
29154
29975
|
}
|
|
@@ -29693,7 +30514,7 @@ program.name("adhdev").description("\u{1F9A6} ADHDev \u2014 Agent Dashboard Hub
|
|
|
29693
30514
|
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) => {
|
|
29694
30515
|
await runWizard({ force: options.force });
|
|
29695
30516
|
});
|
|
29696
|
-
program.command("launch [target]").description("Launch IDE with CDP or start CLI agent (e.g. cursor, gemini, claude)").option("-w, --workspace <path>", "Workspace
|
|
30517
|
+
program.command("launch [target]").description("Launch IDE with CDP or start CLI agent (e.g. cursor, gemini, claude)").option("-w, --workspace <path>", "Workspace directory to open").option("-n, --new-window", "Open in a new window").option("-d, --dir <path>", "Working directory for CLI agent", process.cwd()).action(async (targetArg, options) => {
|
|
29697
30518
|
const resolvedType = targetArg ? _cliProviderLoader.resolveAlias(targetArg.toLowerCase()) : null;
|
|
29698
30519
|
const resolvedProvider = resolvedType ? _cliProviderLoader.get(resolvedType) : null;
|
|
29699
30520
|
const cliType = resolvedProvider && (resolvedProvider.category === "cli" || resolvedProvider.category === "acp") ? resolvedType : null;
|