@adhdev/daemon-core 0.9.53 → 0.9.54
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/commands/handler.d.ts +2 -0
- package/dist/git/git-commands.d.ts +86 -0
- package/dist/git/git-diff.d.ts +17 -0
- package/dist/git/git-executor.d.ts +34 -0
- package/dist/git/git-monitor.d.ts +57 -0
- package/dist/git/git-snapshot-store.d.ts +50 -0
- package/dist/git/git-status.d.ts +19 -0
- package/dist/git/git-summary.d.ts +10 -0
- package/dist/git/git-types.d.ts +113 -0
- package/dist/git/index.d.ts +14 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1575 -385
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1548 -382
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +7 -1
- package/dist/status/builders.d.ts +2 -0
- package/dist/status/snapshot.d.ts +2 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/commands/handler.ts +9 -1
- package/src/git/git-commands.ts +385 -0
- package/src/git/git-diff.ts +303 -0
- package/src/git/git-executor.ts +268 -0
- package/src/git/git-monitor.ts +194 -0
- package/src/git/git-snapshot-store.ts +238 -0
- package/src/git/git-status.ts +193 -0
- package/src/git/git-summary.ts +43 -0
- package/src/git/git-types.ts +153 -0
- package/src/git/index.ts +72 -0
- package/src/index.ts +4 -0
- package/src/shared-types.ts +33 -1
- package/src/status/builders.ts +26 -4
- package/src/status/snapshot.ts +10 -2
package/dist/index.mjs
CHANGED
|
@@ -265,7 +265,7 @@ var init_config = __esm({
|
|
|
265
265
|
|
|
266
266
|
// src/logging/logger.ts
|
|
267
267
|
import * as fs2 from "fs";
|
|
268
|
-
import * as
|
|
268
|
+
import * as path9 from "path";
|
|
269
269
|
import * as os4 from "os";
|
|
270
270
|
function setLogLevel(level) {
|
|
271
271
|
currentLevel = level;
|
|
@@ -281,13 +281,13 @@ function getDaemonLogDir() {
|
|
|
281
281
|
return LOG_DIR;
|
|
282
282
|
}
|
|
283
283
|
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
284
|
-
return
|
|
284
|
+
return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
285
285
|
}
|
|
286
286
|
function checkDateRotation() {
|
|
287
287
|
const today = getDateStr();
|
|
288
288
|
if (today !== currentDate) {
|
|
289
289
|
currentDate = today;
|
|
290
|
-
currentLogFile =
|
|
290
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
291
291
|
cleanOldLogs();
|
|
292
292
|
}
|
|
293
293
|
}
|
|
@@ -301,7 +301,7 @@ function cleanOldLogs() {
|
|
|
301
301
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
302
302
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
303
303
|
try {
|
|
304
|
-
fs2.unlinkSync(
|
|
304
|
+
fs2.unlinkSync(path9.join(LOG_DIR, file));
|
|
305
305
|
} catch {
|
|
306
306
|
}
|
|
307
307
|
}
|
|
@@ -311,8 +311,8 @@ function cleanOldLogs() {
|
|
|
311
311
|
}
|
|
312
312
|
function rotateSizeIfNeeded() {
|
|
313
313
|
try {
|
|
314
|
-
const
|
|
315
|
-
if (
|
|
314
|
+
const stat2 = fs2.statSync(currentLogFile);
|
|
315
|
+
if (stat2.size > MAX_LOG_SIZE) {
|
|
316
316
|
const backup = currentLogFile.replace(".log", ".1.log");
|
|
317
317
|
try {
|
|
318
318
|
fs2.unlinkSync(backup);
|
|
@@ -424,7 +424,7 @@ var init_logger = __esm({
|
|
|
424
424
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
425
425
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
426
426
|
currentLevel = "info";
|
|
427
|
-
LOG_DIR = process.platform === "win32" ?
|
|
427
|
+
LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os4.homedir(), "Library", "Logs", "adhdev") : path9.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
428
428
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
429
429
|
MAX_LOG_DAYS = 7;
|
|
430
430
|
try {
|
|
@@ -432,16 +432,16 @@ var init_logger = __esm({
|
|
|
432
432
|
} catch {
|
|
433
433
|
}
|
|
434
434
|
currentDate = getDateStr();
|
|
435
|
-
currentLogFile =
|
|
435
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
436
436
|
cleanOldLogs();
|
|
437
437
|
try {
|
|
438
|
-
const oldLog =
|
|
438
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
439
439
|
if (fs2.existsSync(oldLog)) {
|
|
440
|
-
const
|
|
441
|
-
const oldDate =
|
|
442
|
-
fs2.renameSync(oldLog,
|
|
440
|
+
const stat2 = fs2.statSync(oldLog);
|
|
441
|
+
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
442
|
+
fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
443
443
|
}
|
|
444
|
-
const oldLogBackup =
|
|
444
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
445
445
|
if (fs2.existsSync(oldLogBackup)) {
|
|
446
446
|
fs2.unlinkSync(oldLogBackup);
|
|
447
447
|
}
|
|
@@ -473,7 +473,7 @@ var init_logger = __esm({
|
|
|
473
473
|
}
|
|
474
474
|
};
|
|
475
475
|
interceptorInstalled = false;
|
|
476
|
-
LOG_PATH =
|
|
476
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
477
477
|
}
|
|
478
478
|
});
|
|
479
479
|
|
|
@@ -1380,8 +1380,8 @@ var init_pty_transport = __esm({
|
|
|
1380
1380
|
if (cwd) {
|
|
1381
1381
|
try {
|
|
1382
1382
|
const fs16 = __require("fs");
|
|
1383
|
-
const
|
|
1384
|
-
if (!
|
|
1383
|
+
const stat2 = fs16.statSync(cwd);
|
|
1384
|
+
if (!stat2.isDirectory()) cwd = os8.homedir();
|
|
1385
1385
|
} catch {
|
|
1386
1386
|
cwd = os8.homedir();
|
|
1387
1387
|
}
|
|
@@ -1401,7 +1401,7 @@ var init_pty_transport = __esm({
|
|
|
1401
1401
|
|
|
1402
1402
|
// src/cli-adapters/provider-cli-shared.ts
|
|
1403
1403
|
import * as os9 from "os";
|
|
1404
|
-
import * as
|
|
1404
|
+
import * as path13 from "path";
|
|
1405
1405
|
import { execSync as execSync3 } from "child_process";
|
|
1406
1406
|
function stripAnsi(str) {
|
|
1407
1407
|
return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
|
|
@@ -1466,9 +1466,9 @@ function buildCliScreenSnapshot(text) {
|
|
|
1466
1466
|
function findBinary(name) {
|
|
1467
1467
|
const trimmed = String(name || "").trim();
|
|
1468
1468
|
if (!trimmed) return trimmed;
|
|
1469
|
-
const expanded = trimmed.startsWith("~") ?
|
|
1470
|
-
if (
|
|
1471
|
-
return
|
|
1469
|
+
const expanded = trimmed.startsWith("~") ? path13.join(os9.homedir(), trimmed.slice(1)) : trimmed;
|
|
1470
|
+
if (path13.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
1471
|
+
return path13.isAbsolute(expanded) ? expanded : path13.resolve(expanded);
|
|
1472
1472
|
}
|
|
1473
1473
|
const isWin = os9.platform() === "win32";
|
|
1474
1474
|
try {
|
|
@@ -1484,7 +1484,7 @@ function findBinary(name) {
|
|
|
1484
1484
|
}
|
|
1485
1485
|
}
|
|
1486
1486
|
function isScriptBinary(binaryPath) {
|
|
1487
|
-
if (!
|
|
1487
|
+
if (!path13.isAbsolute(binaryPath)) return false;
|
|
1488
1488
|
try {
|
|
1489
1489
|
const fs16 = __require("fs");
|
|
1490
1490
|
const resolved = fs16.realpathSync(binaryPath);
|
|
@@ -1500,7 +1500,7 @@ function isScriptBinary(binaryPath) {
|
|
|
1500
1500
|
}
|
|
1501
1501
|
}
|
|
1502
1502
|
function looksLikeMachOOrElf(filePath) {
|
|
1503
|
-
if (!
|
|
1503
|
+
if (!path13.isAbsolute(filePath)) return false;
|
|
1504
1504
|
try {
|
|
1505
1505
|
const fs16 = __require("fs");
|
|
1506
1506
|
const resolved = fs16.realpathSync(filePath);
|
|
@@ -1961,7 +1961,7 @@ var init_provider_cli_config = __esm({
|
|
|
1961
1961
|
|
|
1962
1962
|
// src/cli-adapters/provider-cli-runtime.ts
|
|
1963
1963
|
import * as os10 from "os";
|
|
1964
|
-
import * as
|
|
1964
|
+
import * as path14 from "path";
|
|
1965
1965
|
import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from "@adhdev/session-host-core";
|
|
1966
1966
|
function resolveCliSpawnPlan(options) {
|
|
1967
1967
|
const { provider, runtimeSettings, workingDir, extraArgs } = options;
|
|
@@ -1972,9 +1972,9 @@ function resolveCliSpawnPlan(options) {
|
|
|
1972
1972
|
const allArgs = [...spawnConfig.args, ...extraArgs];
|
|
1973
1973
|
let shellCmd;
|
|
1974
1974
|
let shellArgs;
|
|
1975
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1975
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1976
1976
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1977
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !
|
|
1977
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1978
1978
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1979
1979
|
if (useShell) {
|
|
1980
1980
|
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
@@ -2851,7 +2851,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2851
2851
|
`[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
|
|
2852
2852
|
);
|
|
2853
2853
|
}
|
|
2854
|
-
await new Promise((
|
|
2854
|
+
await new Promise((resolve15) => setTimeout(resolve15, 50));
|
|
2855
2855
|
}
|
|
2856
2856
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
2857
2857
|
LOG.warn(
|
|
@@ -4039,7 +4039,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
4039
4039
|
const deadline = Date.now() + 1e4;
|
|
4040
4040
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
4041
4041
|
this.resolveStartupState("send_wait");
|
|
4042
|
-
await new Promise((
|
|
4042
|
+
await new Promise((resolve15) => setTimeout(resolve15, 50));
|
|
4043
4043
|
}
|
|
4044
4044
|
}
|
|
4045
4045
|
if (!allowInterventionPrompt) {
|
|
@@ -4120,13 +4120,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
4120
4120
|
}
|
|
4121
4121
|
this.responseEpoch += 1;
|
|
4122
4122
|
this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
4123
|
-
await new Promise((
|
|
4123
|
+
await new Promise((resolve15, reject) => {
|
|
4124
4124
|
let resolved = false;
|
|
4125
4125
|
const completion = {
|
|
4126
4126
|
resolveOnce: () => {
|
|
4127
4127
|
if (resolved) return;
|
|
4128
4128
|
resolved = true;
|
|
4129
|
-
|
|
4129
|
+
resolve15();
|
|
4130
4130
|
},
|
|
4131
4131
|
rejectOnce: (error) => {
|
|
4132
4132
|
if (resolved) return;
|
|
@@ -4288,17 +4288,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
4288
4288
|
}
|
|
4289
4289
|
}
|
|
4290
4290
|
waitForStopped(timeoutMs) {
|
|
4291
|
-
return new Promise((
|
|
4291
|
+
return new Promise((resolve15) => {
|
|
4292
4292
|
const startedAt = Date.now();
|
|
4293
4293
|
const timer = setInterval(() => {
|
|
4294
4294
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
4295
4295
|
clearInterval(timer);
|
|
4296
|
-
|
|
4296
|
+
resolve15(true);
|
|
4297
4297
|
return;
|
|
4298
4298
|
}
|
|
4299
4299
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
4300
4300
|
clearInterval(timer);
|
|
4301
|
-
|
|
4301
|
+
resolve15(false);
|
|
4302
4302
|
}
|
|
4303
4303
|
}, 100);
|
|
4304
4304
|
});
|
|
@@ -4524,20 +4524,1137 @@ var init_provider_cli_adapter = __esm({
|
|
|
4524
4524
|
}
|
|
4525
4525
|
});
|
|
4526
4526
|
|
|
4527
|
+
// src/git/git-executor.ts
|
|
4528
|
+
import { execFile } from "child_process";
|
|
4529
|
+
import { constants } from "fs";
|
|
4530
|
+
import { access, realpath, stat } from "fs/promises";
|
|
4531
|
+
import * as path from "path";
|
|
4532
|
+
import { promisify } from "util";
|
|
4533
|
+
var execFileAsync = promisify(execFile);
|
|
4534
|
+
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
4535
|
+
var DEFAULT_MAX_BUFFER = 1024 * 1024;
|
|
4536
|
+
var GitCommandError = class extends Error {
|
|
4537
|
+
reason;
|
|
4538
|
+
stdout;
|
|
4539
|
+
stderr;
|
|
4540
|
+
exitCode;
|
|
4541
|
+
signal;
|
|
4542
|
+
argv;
|
|
4543
|
+
cwd;
|
|
4544
|
+
constructor(reason, message, details = {}) {
|
|
4545
|
+
super(message);
|
|
4546
|
+
if (details.cause !== void 0) {
|
|
4547
|
+
this.cause = details.cause;
|
|
4548
|
+
}
|
|
4549
|
+
this.name = "GitCommandError";
|
|
4550
|
+
this.reason = reason;
|
|
4551
|
+
this.stdout = normalizeGitOutput(details.stdout);
|
|
4552
|
+
this.stderr = normalizeGitOutput(details.stderr);
|
|
4553
|
+
this.exitCode = details.exitCode;
|
|
4554
|
+
this.signal = details.signal;
|
|
4555
|
+
this.argv = details.argv ? [...details.argv] : void 0;
|
|
4556
|
+
this.cwd = details.cwd;
|
|
4557
|
+
}
|
|
4558
|
+
};
|
|
4559
|
+
async function resolveGitRepository(workspace, options = {}) {
|
|
4560
|
+
const normalizedWorkspace = await validateWorkspace(workspace);
|
|
4561
|
+
const result = await execGitRaw(normalizedWorkspace, ["rev-parse", "--show-toplevel"], options, {
|
|
4562
|
+
mapNotGitRepo: true
|
|
4563
|
+
});
|
|
4564
|
+
const repoRoot = path.resolve(result.stdout.trim());
|
|
4565
|
+
if (!repoRoot) {
|
|
4566
|
+
throw new GitCommandError("not_git_repo", "Git did not return a repository root", {
|
|
4567
|
+
stdout: result.stdout,
|
|
4568
|
+
stderr: result.stderr,
|
|
4569
|
+
argv: ["rev-parse", "--show-toplevel"],
|
|
4570
|
+
cwd: normalizedWorkspace
|
|
4571
|
+
});
|
|
4572
|
+
}
|
|
4573
|
+
return {
|
|
4574
|
+
workspace: normalizedWorkspace,
|
|
4575
|
+
repoRoot,
|
|
4576
|
+
isGitRepo: true
|
|
4577
|
+
};
|
|
4578
|
+
}
|
|
4579
|
+
async function runGit(repoOrWorkspace, argv, options = {}) {
|
|
4580
|
+
validateGitArgv(argv);
|
|
4581
|
+
const repo = typeof repoOrWorkspace === "string" ? await resolveGitRepository(repoOrWorkspace, options) : repoOrWorkspace;
|
|
4582
|
+
if (!repo.repoRoot || !repo.isGitRepo) {
|
|
4583
|
+
throw new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
|
|
4584
|
+
argv,
|
|
4585
|
+
cwd: repo.workspace
|
|
4586
|
+
});
|
|
4587
|
+
}
|
|
4588
|
+
const cwd = options.cwd ? await validateWorkspace(options.cwd) : await validateWorkspace(repo.workspace);
|
|
4589
|
+
const canonicalRepoRoot = await realpath(repo.repoRoot);
|
|
4590
|
+
const canonicalCwd = await realpath(cwd);
|
|
4591
|
+
if (!isPathInside(canonicalRepoRoot, canonicalCwd)) {
|
|
4592
|
+
throw new GitCommandError("path_outside_repo", "Git cwd is outside the repository root", {
|
|
4593
|
+
argv,
|
|
4594
|
+
cwd
|
|
4595
|
+
});
|
|
4596
|
+
}
|
|
4597
|
+
return execGitRaw(cwd, argv, options);
|
|
4598
|
+
}
|
|
4599
|
+
function normalizeGitOutput(value) {
|
|
4600
|
+
if (typeof value === "string") return value.replace(/\r\n/g, "\n");
|
|
4601
|
+
if (Buffer.isBuffer(value)) return value.toString("utf8").replace(/\r\n/g, "\n");
|
|
4602
|
+
if (value == null) return "";
|
|
4603
|
+
return String(value).replace(/\r\n/g, "\n");
|
|
4604
|
+
}
|
|
4605
|
+
function isPathInside(parent, child) {
|
|
4606
|
+
const relative3 = path.relative(path.resolve(parent), path.resolve(child));
|
|
4607
|
+
return relative3 === "" || !relative3.startsWith("..") && !path.isAbsolute(relative3);
|
|
4608
|
+
}
|
|
4609
|
+
async function validateWorkspace(workspace) {
|
|
4610
|
+
if (typeof workspace !== "string" || workspace.length === 0 || workspace.includes("\0")) {
|
|
4611
|
+
throw new GitCommandError("invalid_args", "Workspace must be a non-empty path");
|
|
4612
|
+
}
|
|
4613
|
+
if (!path.isAbsolute(workspace)) {
|
|
4614
|
+
throw new GitCommandError("invalid_args", "Workspace must be an absolute path", { cwd: workspace });
|
|
4615
|
+
}
|
|
4616
|
+
const normalizedWorkspace = path.resolve(workspace);
|
|
4617
|
+
try {
|
|
4618
|
+
const info = await stat(normalizedWorkspace);
|
|
4619
|
+
if (!info.isDirectory()) {
|
|
4620
|
+
throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
|
|
4621
|
+
cwd: normalizedWorkspace
|
|
4622
|
+
});
|
|
4623
|
+
}
|
|
4624
|
+
await access(normalizedWorkspace, constants.R_OK);
|
|
4625
|
+
} catch (error) {
|
|
4626
|
+
if (error instanceof GitCommandError) throw error;
|
|
4627
|
+
throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
|
|
4628
|
+
cwd: normalizedWorkspace,
|
|
4629
|
+
cause: error
|
|
4630
|
+
});
|
|
4631
|
+
}
|
|
4632
|
+
return normalizedWorkspace;
|
|
4633
|
+
}
|
|
4634
|
+
function validateGitArgv(argv) {
|
|
4635
|
+
if (!Array.isArray(argv) || argv.length === 0) {
|
|
4636
|
+
throw new GitCommandError("invalid_args", "Git argv must be a non-empty string array", { argv });
|
|
4637
|
+
}
|
|
4638
|
+
for (const arg of argv) {
|
|
4639
|
+
if (typeof arg !== "string" || arg.length === 0 || arg.includes("\0")) {
|
|
4640
|
+
throw new GitCommandError("invalid_args", "Git argv contains an invalid argument", { argv });
|
|
4641
|
+
}
|
|
4642
|
+
}
|
|
4643
|
+
if (argv.includes("-C") || argv.some((arg) => arg.startsWith("--git-dir") || arg.startsWith("--work-tree"))) {
|
|
4644
|
+
throw new GitCommandError("invalid_args", "Git argv contains unsafe repository override arguments", {
|
|
4645
|
+
argv
|
|
4646
|
+
});
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
async function execGitRaw(cwd, argv, options, behavior = {}) {
|
|
4650
|
+
validateGitArgv(argv);
|
|
4651
|
+
try {
|
|
4652
|
+
const result = await execFileAsync("git", [...argv], {
|
|
4653
|
+
cwd,
|
|
4654
|
+
encoding: "utf8",
|
|
4655
|
+
timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
4656
|
+
maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER,
|
|
4657
|
+
windowsHide: true
|
|
4658
|
+
});
|
|
4659
|
+
return {
|
|
4660
|
+
stdout: normalizeGitOutput(result.stdout),
|
|
4661
|
+
stderr: normalizeGitOutput(result.stderr)
|
|
4662
|
+
};
|
|
4663
|
+
} catch (error) {
|
|
4664
|
+
throw mapExecError(error, cwd, argv, behavior);
|
|
4665
|
+
}
|
|
4666
|
+
}
|
|
4667
|
+
function mapExecError(error, cwd, argv, behavior) {
|
|
4668
|
+
const execError = error;
|
|
4669
|
+
const stdout = normalizeGitOutput(execError.stdout);
|
|
4670
|
+
const stderr = normalizeGitOutput(execError.stderr);
|
|
4671
|
+
const code = execError.code;
|
|
4672
|
+
const signal = execError.signal;
|
|
4673
|
+
const message = [stderr.trim(), execError.message].filter(Boolean).join("\n");
|
|
4674
|
+
if (code === "ENOENT") {
|
|
4675
|
+
return new GitCommandError("git_not_installed", "Git executable was not found", {
|
|
4676
|
+
stdout,
|
|
4677
|
+
stderr,
|
|
4678
|
+
exitCode: code,
|
|
4679
|
+
signal,
|
|
4680
|
+
argv,
|
|
4681
|
+
cwd,
|
|
4682
|
+
cause: error
|
|
4683
|
+
});
|
|
4684
|
+
}
|
|
4685
|
+
if (execError.killed || /timed out/i.test(execError.message)) {
|
|
4686
|
+
return new GitCommandError("timeout", "Git command timed out", {
|
|
4687
|
+
stdout,
|
|
4688
|
+
stderr,
|
|
4689
|
+
exitCode: code,
|
|
4690
|
+
signal,
|
|
4691
|
+
argv,
|
|
4692
|
+
cwd,
|
|
4693
|
+
cause: error
|
|
4694
|
+
});
|
|
4695
|
+
}
|
|
4696
|
+
if (behavior.mapNotGitRepo && /not a git repository/i.test(stderr + "\n" + execError.message)) {
|
|
4697
|
+
return new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
|
|
4698
|
+
stdout,
|
|
4699
|
+
stderr,
|
|
4700
|
+
exitCode: code,
|
|
4701
|
+
signal,
|
|
4702
|
+
argv,
|
|
4703
|
+
cwd,
|
|
4704
|
+
cause: error
|
|
4705
|
+
});
|
|
4706
|
+
}
|
|
4707
|
+
return new GitCommandError("git_command_failed", message || "Git command failed", {
|
|
4708
|
+
stdout,
|
|
4709
|
+
stderr,
|
|
4710
|
+
exitCode: code,
|
|
4711
|
+
signal,
|
|
4712
|
+
argv,
|
|
4713
|
+
cwd,
|
|
4714
|
+
cause: error
|
|
4715
|
+
});
|
|
4716
|
+
}
|
|
4717
|
+
|
|
4718
|
+
// src/git/git-status.ts
|
|
4719
|
+
async function getGitRepoStatus(workspace, options = {}) {
|
|
4720
|
+
const lastCheckedAt = Date.now();
|
|
4721
|
+
try {
|
|
4722
|
+
const repo = await resolveGitRepository(workspace, options);
|
|
4723
|
+
const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
|
|
4724
|
+
const parsed = parsePorcelainV2Status(statusOutput.stdout);
|
|
4725
|
+
const head = await readHead(repo, options);
|
|
4726
|
+
const stashCount = await readStashCount(repo, options);
|
|
4727
|
+
return {
|
|
4728
|
+
workspace: repo.workspace,
|
|
4729
|
+
repoRoot: repo.repoRoot,
|
|
4730
|
+
isGitRepo: true,
|
|
4731
|
+
branch: parsed.branch,
|
|
4732
|
+
headCommit: head.commit,
|
|
4733
|
+
headMessage: head.message,
|
|
4734
|
+
upstream: parsed.upstream,
|
|
4735
|
+
ahead: parsed.ahead,
|
|
4736
|
+
behind: parsed.behind,
|
|
4737
|
+
staged: parsed.staged,
|
|
4738
|
+
modified: parsed.modified,
|
|
4739
|
+
untracked: parsed.untracked,
|
|
4740
|
+
deleted: parsed.deleted,
|
|
4741
|
+
renamed: parsed.renamed,
|
|
4742
|
+
hasConflicts: parsed.conflictFiles.length > 0,
|
|
4743
|
+
conflictFiles: parsed.conflictFiles,
|
|
4744
|
+
stashCount,
|
|
4745
|
+
lastCheckedAt
|
|
4746
|
+
};
|
|
4747
|
+
} catch (error) {
|
|
4748
|
+
if (error instanceof GitCommandError) {
|
|
4749
|
+
return emptyStatus(workspace, lastCheckedAt, error);
|
|
4750
|
+
}
|
|
4751
|
+
return emptyStatus(
|
|
4752
|
+
workspace,
|
|
4753
|
+
lastCheckedAt,
|
|
4754
|
+
new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error })
|
|
4755
|
+
);
|
|
4756
|
+
}
|
|
4757
|
+
}
|
|
4758
|
+
function parsePorcelainV2Status(output) {
|
|
4759
|
+
const parsed = {
|
|
4760
|
+
branch: null,
|
|
4761
|
+
upstream: null,
|
|
4762
|
+
ahead: 0,
|
|
4763
|
+
behind: 0,
|
|
4764
|
+
staged: 0,
|
|
4765
|
+
modified: 0,
|
|
4766
|
+
untracked: 0,
|
|
4767
|
+
deleted: 0,
|
|
4768
|
+
renamed: 0,
|
|
4769
|
+
conflictFiles: []
|
|
4770
|
+
};
|
|
4771
|
+
for (const line of output.split("\n")) {
|
|
4772
|
+
if (!line) continue;
|
|
4773
|
+
if (line.startsWith("# branch.head ")) {
|
|
4774
|
+
const branch = line.slice("# branch.head ".length).trim();
|
|
4775
|
+
parsed.branch = branch && branch !== "(detached)" ? branch : null;
|
|
4776
|
+
continue;
|
|
4777
|
+
}
|
|
4778
|
+
if (line.startsWith("# branch.upstream ")) {
|
|
4779
|
+
parsed.upstream = line.slice("# branch.upstream ".length).trim() || null;
|
|
4780
|
+
continue;
|
|
4781
|
+
}
|
|
4782
|
+
if (line.startsWith("# branch.ab ")) {
|
|
4783
|
+
const match = line.match(/\+(-?\d+)\s+-(-?\d+)/);
|
|
4784
|
+
if (match) {
|
|
4785
|
+
parsed.ahead = Number.parseInt(match[1] ?? "0", 10) || 0;
|
|
4786
|
+
parsed.behind = Number.parseInt(match[2] ?? "0", 10) || 0;
|
|
4787
|
+
}
|
|
4788
|
+
continue;
|
|
4789
|
+
}
|
|
4790
|
+
if (line.startsWith("? ")) {
|
|
4791
|
+
parsed.untracked += 1;
|
|
4792
|
+
continue;
|
|
4793
|
+
}
|
|
4794
|
+
if (line.startsWith("u ")) {
|
|
4795
|
+
const fields = line.split(" ");
|
|
4796
|
+
const filePath = fields.slice(10).join(" ");
|
|
4797
|
+
if (filePath) parsed.conflictFiles.push(filePath);
|
|
4798
|
+
continue;
|
|
4799
|
+
}
|
|
4800
|
+
if (line.startsWith("1 ") || line.startsWith("2 ")) {
|
|
4801
|
+
const fields = line.split(" ");
|
|
4802
|
+
const xy = fields[1] ?? "..";
|
|
4803
|
+
const indexStatus = xy[0] ?? ".";
|
|
4804
|
+
const worktreeStatus = xy[1] ?? ".";
|
|
4805
|
+
if (isStagedStatus(indexStatus)) parsed.staged += 1;
|
|
4806
|
+
if (worktreeStatus === "M" || worktreeStatus === "T") parsed.modified += 1;
|
|
4807
|
+
if (indexStatus === "D" || worktreeStatus === "D") parsed.deleted += 1;
|
|
4808
|
+
if (indexStatus === "R" || worktreeStatus === "R") parsed.renamed += 1;
|
|
4809
|
+
if (xy.includes("U")) {
|
|
4810
|
+
const filePath = fields.slice(line.startsWith("2 ") ? 9 : 8).join(" ").split(" ")[0] ?? "";
|
|
4811
|
+
if (filePath) parsed.conflictFiles.push(filePath);
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
parsed.conflictFiles = Array.from(new Set(parsed.conflictFiles));
|
|
4816
|
+
return parsed;
|
|
4817
|
+
}
|
|
4818
|
+
async function readHead(repo, options) {
|
|
4819
|
+
try {
|
|
4820
|
+
const result = await runGit(repo, ["log", "-1", "--pretty=%h%x00%s"], options);
|
|
4821
|
+
const text = result.stdout.trimEnd();
|
|
4822
|
+
if (!text) return { commit: null, message: null };
|
|
4823
|
+
const [commit, ...messageParts] = text.split("\0");
|
|
4824
|
+
return {
|
|
4825
|
+
commit: commit || null,
|
|
4826
|
+
message: messageParts.join("\0") || null
|
|
4827
|
+
};
|
|
4828
|
+
} catch {
|
|
4829
|
+
return { commit: null, message: null };
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
async function readStashCount(repo, options) {
|
|
4833
|
+
try {
|
|
4834
|
+
const result = await runGit(repo, ["stash", "list", "--format=%gd"], options);
|
|
4835
|
+
return result.stdout.split("\n").filter((line) => line.trim().length > 0).length;
|
|
4836
|
+
} catch {
|
|
4837
|
+
return 0;
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4840
|
+
function isStagedStatus(status) {
|
|
4841
|
+
return status !== "." && status !== "?" && status !== "U";
|
|
4842
|
+
}
|
|
4843
|
+
function emptyStatus(workspace, lastCheckedAt, error) {
|
|
4844
|
+
return {
|
|
4845
|
+
workspace,
|
|
4846
|
+
repoRoot: null,
|
|
4847
|
+
isGitRepo: false,
|
|
4848
|
+
branch: null,
|
|
4849
|
+
headCommit: null,
|
|
4850
|
+
headMessage: null,
|
|
4851
|
+
upstream: null,
|
|
4852
|
+
ahead: 0,
|
|
4853
|
+
behind: 0,
|
|
4854
|
+
staged: 0,
|
|
4855
|
+
modified: 0,
|
|
4856
|
+
untracked: 0,
|
|
4857
|
+
deleted: 0,
|
|
4858
|
+
renamed: 0,
|
|
4859
|
+
hasConflicts: false,
|
|
4860
|
+
conflictFiles: [],
|
|
4861
|
+
stashCount: 0,
|
|
4862
|
+
lastCheckedAt,
|
|
4863
|
+
error: error.stderr || error.message,
|
|
4864
|
+
reason: error.reason
|
|
4865
|
+
};
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4868
|
+
// src/git/git-diff.ts
|
|
4869
|
+
import { readFile, realpath as realpath2 } from "fs/promises";
|
|
4870
|
+
import * as path2 from "path";
|
|
4871
|
+
var DEFAULT_MAX_FILES = 200;
|
|
4872
|
+
var DEFAULT_MAX_BYTES = 2e5;
|
|
4873
|
+
async function getGitDiffSummary(workspace, options = {}) {
|
|
4874
|
+
const lastCheckedAt = Date.now();
|
|
4875
|
+
try {
|
|
4876
|
+
const repo = await resolveGitRepository(workspace, options);
|
|
4877
|
+
const repoRoot = repo.repoRoot;
|
|
4878
|
+
const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
|
|
4879
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
|
|
4880
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
|
|
4881
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
|
|
4882
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
|
|
4883
|
+
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...options, cwd: repoRoot })
|
|
4884
|
+
]);
|
|
4885
|
+
const outputBytes = byteLength(
|
|
4886
|
+
unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
|
|
4887
|
+
);
|
|
4888
|
+
const changes = [
|
|
4889
|
+
...combineDiffEntries(unstagedNameStatus.stdout, unstagedNumstat.stdout, false),
|
|
4890
|
+
...combineDiffEntries(stagedNameStatus.stdout, stagedNumstat.stdout, true),
|
|
4891
|
+
...parseUntrackedFiles(untracked.stdout)
|
|
4892
|
+
];
|
|
4893
|
+
const maxFiles = normalizePositiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
|
|
4894
|
+
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
4895
|
+
const files = changes.slice(0, maxFiles);
|
|
4896
|
+
const truncated = changes.length > files.length || outputBytes > maxBytes;
|
|
4897
|
+
return {
|
|
4898
|
+
workspace: repo.workspace,
|
|
4899
|
+
repoRoot,
|
|
4900
|
+
isGitRepo: true,
|
|
4901
|
+
files,
|
|
4902
|
+
totalInsertions: files.reduce((sum, file) => sum + file.insertions, 0),
|
|
4903
|
+
totalDeletions: files.reduce((sum, file) => sum + file.deletions, 0),
|
|
4904
|
+
truncated,
|
|
4905
|
+
lastCheckedAt
|
|
4906
|
+
};
|
|
4907
|
+
} catch (error) {
|
|
4908
|
+
const gitError = error instanceof GitCommandError ? error : new GitCommandError("git_command_failed", "Failed to read Git diff summary", { cause: error });
|
|
4909
|
+
return {
|
|
4910
|
+
workspace,
|
|
4911
|
+
repoRoot: null,
|
|
4912
|
+
isGitRepo: false,
|
|
4913
|
+
files: [],
|
|
4914
|
+
totalInsertions: 0,
|
|
4915
|
+
totalDeletions: 0,
|
|
4916
|
+
truncated: false,
|
|
4917
|
+
lastCheckedAt,
|
|
4918
|
+
error: gitError.stderr || gitError.message,
|
|
4919
|
+
reason: gitError.reason
|
|
4920
|
+
};
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
4924
|
+
const lastCheckedAt = Date.now();
|
|
4925
|
+
const repo = await resolveGitRepository(workspace, options);
|
|
4926
|
+
const repoRoot = repo.repoRoot;
|
|
4927
|
+
const selected = await resolveRepoFilePath(repoRoot, filePath);
|
|
4928
|
+
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
4929
|
+
const [unstaged, staged] = await Promise.all([
|
|
4930
|
+
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot }),
|
|
4931
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot })
|
|
4932
|
+
]);
|
|
4933
|
+
let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
|
|
4934
|
+
if (!diff) {
|
|
4935
|
+
const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
|
|
4936
|
+
...options,
|
|
4937
|
+
cwd: repoRoot
|
|
4938
|
+
});
|
|
4939
|
+
const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
|
|
4940
|
+
if (untrackedFiles.includes(selected.relativePath)) {
|
|
4941
|
+
diff = await buildUntrackedDiff(selected.absolutePath, selected.relativePath, maxBytes + 1);
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
const bounded = truncateText(diff, maxBytes);
|
|
4945
|
+
return {
|
|
4946
|
+
workspace: repo.workspace,
|
|
4947
|
+
repoRoot,
|
|
4948
|
+
isGitRepo: true,
|
|
4949
|
+
path: selected.relativePath,
|
|
4950
|
+
diff: bounded.text,
|
|
4951
|
+
truncated: bounded.truncated,
|
|
4952
|
+
lastCheckedAt
|
|
4953
|
+
};
|
|
4954
|
+
}
|
|
4955
|
+
function combineDiffEntries(nameStatusOutput, numstatOutput, staged) {
|
|
4956
|
+
const statusEntries = parseNameStatus(nameStatusOutput);
|
|
4957
|
+
const numstatEntries = parseNumstat(numstatOutput);
|
|
4958
|
+
return statusEntries.map((entry, index) => {
|
|
4959
|
+
const stats = numstatEntries[index];
|
|
4960
|
+
return {
|
|
4961
|
+
path: entry.path,
|
|
4962
|
+
oldPath: entry.oldPath,
|
|
4963
|
+
status: entry.status,
|
|
4964
|
+
staged,
|
|
4965
|
+
insertions: stats?.insertions ?? 0,
|
|
4966
|
+
deletions: stats?.deletions ?? 0,
|
|
4967
|
+
binary: stats?.binary || void 0
|
|
4968
|
+
};
|
|
4969
|
+
});
|
|
4970
|
+
}
|
|
4971
|
+
function parseNameStatus(output) {
|
|
4972
|
+
return output.split("\n").filter(Boolean).map((line) => {
|
|
4973
|
+
const fields = line.split(" ");
|
|
4974
|
+
const code = fields[0] ?? "";
|
|
4975
|
+
const statusLetter = code[0] ?? "M";
|
|
4976
|
+
if (statusLetter === "R") {
|
|
4977
|
+
return {
|
|
4978
|
+
oldPath: fields[1] ?? "",
|
|
4979
|
+
path: fields[2] ?? fields[1] ?? "",
|
|
4980
|
+
status: "renamed"
|
|
4981
|
+
};
|
|
4982
|
+
}
|
|
4983
|
+
if (statusLetter === "C") {
|
|
4984
|
+
return {
|
|
4985
|
+
oldPath: fields[1] ?? "",
|
|
4986
|
+
path: fields[2] ?? fields[1] ?? "",
|
|
4987
|
+
status: "copied"
|
|
4988
|
+
};
|
|
4989
|
+
}
|
|
4990
|
+
return {
|
|
4991
|
+
path: fields[1] ?? "",
|
|
4992
|
+
status: mapNameStatus(statusLetter)
|
|
4993
|
+
};
|
|
4994
|
+
}).filter((entry) => entry.path.length > 0);
|
|
4995
|
+
}
|
|
4996
|
+
function parseNumstat(output) {
|
|
4997
|
+
return output.split("\n").filter(Boolean).map((line) => {
|
|
4998
|
+
const fields = line.split(" ");
|
|
4999
|
+
const insertionsText = fields[0] ?? "0";
|
|
5000
|
+
const deletionsText = fields[1] ?? "0";
|
|
5001
|
+
const binary = insertionsText === "-" || deletionsText === "-";
|
|
5002
|
+
return {
|
|
5003
|
+
path: fields.slice(2).join(" "),
|
|
5004
|
+
insertions: binary ? 0 : Number.parseInt(insertionsText, 10) || 0,
|
|
5005
|
+
deletions: binary ? 0 : Number.parseInt(deletionsText, 10) || 0,
|
|
5006
|
+
binary
|
|
5007
|
+
};
|
|
5008
|
+
});
|
|
5009
|
+
}
|
|
5010
|
+
function parseUntrackedFiles(output) {
|
|
5011
|
+
return output.split("\n").filter(Boolean).map((filePath) => ({
|
|
5012
|
+
path: filePath,
|
|
5013
|
+
status: "untracked",
|
|
5014
|
+
staged: false,
|
|
5015
|
+
insertions: 0,
|
|
5016
|
+
deletions: 0
|
|
5017
|
+
}));
|
|
5018
|
+
}
|
|
5019
|
+
function mapNameStatus(status) {
|
|
5020
|
+
switch (status) {
|
|
5021
|
+
case "A":
|
|
5022
|
+
return "added";
|
|
5023
|
+
case "D":
|
|
5024
|
+
return "deleted";
|
|
5025
|
+
case "R":
|
|
5026
|
+
return "renamed";
|
|
5027
|
+
case "C":
|
|
5028
|
+
return "copied";
|
|
5029
|
+
case "U":
|
|
5030
|
+
return "conflict";
|
|
5031
|
+
case "M":
|
|
5032
|
+
case "T":
|
|
5033
|
+
default:
|
|
5034
|
+
return "modified";
|
|
5035
|
+
}
|
|
5036
|
+
}
|
|
5037
|
+
async function resolveRepoFilePath(repoRoot, filePath) {
|
|
5038
|
+
if (typeof filePath !== "string" || filePath.length === 0 || filePath.includes("\0")) {
|
|
5039
|
+
throw new GitCommandError("invalid_args", "File path must be a non-empty path");
|
|
5040
|
+
}
|
|
5041
|
+
const canonicalRepoRoot = await realpath2(repoRoot).catch(() => path2.resolve(repoRoot));
|
|
5042
|
+
const absolutePath = path2.isAbsolute(filePath) ? path2.resolve(filePath) : path2.resolve(repoRoot, filePath);
|
|
5043
|
+
const checkPath = await realpath2(absolutePath).catch(() => absolutePath);
|
|
5044
|
+
const relativeBase = isPathInside(canonicalRepoRoot, checkPath) ? canonicalRepoRoot : path2.resolve(repoRoot);
|
|
5045
|
+
if (!isPathInside(canonicalRepoRoot, checkPath) && !isPathInside(repoRoot, absolutePath)) {
|
|
5046
|
+
throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
|
|
5047
|
+
cwd: repoRoot
|
|
5048
|
+
});
|
|
5049
|
+
}
|
|
5050
|
+
const relativePath = path2.relative(relativeBase, checkPath).split(path2.sep).join("/");
|
|
5051
|
+
if (!relativePath || relativePath.startsWith("..") || path2.isAbsolute(relativePath)) {
|
|
5052
|
+
throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
|
|
5053
|
+
cwd: repoRoot
|
|
5054
|
+
});
|
|
5055
|
+
}
|
|
5056
|
+
return { absolutePath, relativePath };
|
|
5057
|
+
}
|
|
5058
|
+
async function buildUntrackedDiff(absolutePath, relativePath, readLimit) {
|
|
5059
|
+
const content = await readFile(absolutePath, "utf8");
|
|
5060
|
+
const limitedContent = content.length > readLimit ? content.slice(0, readLimit) : content;
|
|
5061
|
+
const lines = limitedContent.length > 0 ? limitedContent.split("\n") : [];
|
|
5062
|
+
const plusLines = lines.filter((line, index) => index < lines.length - 1 || line.length > 0).map((line) => `+${line}`).join("\n");
|
|
5063
|
+
const lineCount = plusLines ? plusLines.split("\n").length : 0;
|
|
5064
|
+
return [
|
|
5065
|
+
`diff --git a/${relativePath} b/${relativePath}`,
|
|
5066
|
+
"new file mode 100644",
|
|
5067
|
+
"index 0000000..0000000",
|
|
5068
|
+
"--- /dev/null",
|
|
5069
|
+
`+++ b/${relativePath}`,
|
|
5070
|
+
`@@ -0,0 +1,${lineCount} @@`,
|
|
5071
|
+
plusLines
|
|
5072
|
+
].filter((line) => line.length > 0).join("\n");
|
|
5073
|
+
}
|
|
5074
|
+
function truncateText(text, maxBytes) {
|
|
5075
|
+
if (byteLength(text) <= maxBytes) return { text, truncated: false };
|
|
5076
|
+
return { text: Buffer.from(text, "utf8").subarray(0, maxBytes).toString("utf8"), truncated: true };
|
|
5077
|
+
}
|
|
5078
|
+
function byteLength(text) {
|
|
5079
|
+
return Buffer.byteLength(text, "utf8");
|
|
5080
|
+
}
|
|
5081
|
+
function normalizePositiveInteger(value, fallback) {
|
|
5082
|
+
if (!Number.isFinite(value) || value == null || value <= 0) return fallback;
|
|
5083
|
+
return Math.floor(value);
|
|
5084
|
+
}
|
|
5085
|
+
|
|
5086
|
+
// src/git/git-summary.ts
|
|
5087
|
+
function countStatusChangedFiles(status) {
|
|
5088
|
+
const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
|
|
5089
|
+
return status.staged + status.modified + status.untracked + status.deleted + status.renamed + conflictCount;
|
|
5090
|
+
}
|
|
5091
|
+
function createGitCompactSummary(status, diffSummary) {
|
|
5092
|
+
const statusChangedFiles = countStatusChangedFiles(status);
|
|
5093
|
+
const diffChangedFiles = diffSummary?.files.length ?? 0;
|
|
5094
|
+
const changedFiles = Math.max(statusChangedFiles, diffChangedFiles);
|
|
5095
|
+
const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
|
|
5096
|
+
return {
|
|
5097
|
+
isGitRepo: status.isGitRepo,
|
|
5098
|
+
repoRoot: status.repoRoot,
|
|
5099
|
+
branch: status.branch,
|
|
5100
|
+
dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
|
|
5101
|
+
changedFiles,
|
|
5102
|
+
ahead: status.ahead,
|
|
5103
|
+
behind: status.behind,
|
|
5104
|
+
hasConflicts: status.hasConflicts || conflictCount > 0,
|
|
5105
|
+
lastCheckedAt: Math.max(status.lastCheckedAt, diffSummary?.lastCheckedAt ?? status.lastCheckedAt),
|
|
5106
|
+
error: status.error ?? diffSummary?.error,
|
|
5107
|
+
reason: status.reason ?? diffSummary?.reason
|
|
5108
|
+
};
|
|
5109
|
+
}
|
|
5110
|
+
var summarizeGitStatus = createGitCompactSummary;
|
|
5111
|
+
|
|
5112
|
+
// src/git/git-snapshot-store.ts
|
|
5113
|
+
function normalizeCapacity(capacity) {
|
|
5114
|
+
return Math.max(1, Math.floor(capacity ?? 100));
|
|
5115
|
+
}
|
|
5116
|
+
function createEmptyDiffSummary(status) {
|
|
5117
|
+
return {
|
|
5118
|
+
workspace: status.workspace,
|
|
5119
|
+
repoRoot: status.repoRoot,
|
|
5120
|
+
isGitRepo: status.isGitRepo,
|
|
5121
|
+
files: [],
|
|
5122
|
+
totalInsertions: 0,
|
|
5123
|
+
totalDeletions: 0,
|
|
5124
|
+
truncated: false,
|
|
5125
|
+
lastCheckedAt: status.lastCheckedAt,
|
|
5126
|
+
error: status.error,
|
|
5127
|
+
reason: status.reason
|
|
5128
|
+
};
|
|
5129
|
+
}
|
|
5130
|
+
function changedFileKey(file) {
|
|
5131
|
+
return `${file.oldPath ?? ""}\0${file.path}`;
|
|
5132
|
+
}
|
|
5133
|
+
function uniqueSorted(values) {
|
|
5134
|
+
return Array.from(new Set(Array.from(values).filter(Boolean))).sort((a, b) => a.localeCompare(b));
|
|
5135
|
+
}
|
|
5136
|
+
function plural(count, singular, pluralText = `${singular}s`) {
|
|
5137
|
+
return count === 1 ? singular : pluralText;
|
|
5138
|
+
}
|
|
5139
|
+
function compareGitSnapshots(before, after) {
|
|
5140
|
+
const beforeFileKeys = new Set(before.diffSummary.files.map(changedFileKey));
|
|
5141
|
+
const changedAfterFiles = after.diffSummary.files.filter((file) => !beforeFileKeys.has(changedFileKey(file)));
|
|
5142
|
+
const addedFiles = [];
|
|
5143
|
+
const modifiedFiles = [];
|
|
5144
|
+
const deletedFiles = [];
|
|
5145
|
+
const renamedFiles = [];
|
|
5146
|
+
const untrackedFiles = [];
|
|
5147
|
+
const conflictFilesFromDiff = [];
|
|
5148
|
+
let totalInsertions = 0;
|
|
5149
|
+
let totalDeletions = 0;
|
|
5150
|
+
for (const file of changedAfterFiles) {
|
|
5151
|
+
totalInsertions += file.insertions;
|
|
5152
|
+
totalDeletions += file.deletions;
|
|
5153
|
+
switch (file.status) {
|
|
5154
|
+
case "added":
|
|
5155
|
+
case "copied":
|
|
5156
|
+
addedFiles.push(file.path);
|
|
5157
|
+
break;
|
|
5158
|
+
case "modified":
|
|
5159
|
+
modifiedFiles.push(file.path);
|
|
5160
|
+
break;
|
|
5161
|
+
case "deleted":
|
|
5162
|
+
deletedFiles.push(file.path);
|
|
5163
|
+
break;
|
|
5164
|
+
case "renamed":
|
|
5165
|
+
renamedFiles.push({ oldPath: file.oldPath ?? file.path, path: file.path });
|
|
5166
|
+
break;
|
|
5167
|
+
case "untracked":
|
|
5168
|
+
untrackedFiles.push(file.path);
|
|
5169
|
+
break;
|
|
5170
|
+
case "conflict":
|
|
5171
|
+
conflictFilesFromDiff.push(file.path);
|
|
5172
|
+
break;
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
renamedFiles.sort((a, b) => `${a.oldPath}\0${a.path}`.localeCompare(`${b.oldPath}\0${b.path}`));
|
|
5176
|
+
const conflictFiles = uniqueSorted([...after.status.conflictFiles, ...conflictFilesFromDiff]);
|
|
5177
|
+
const changedFiles = changedAfterFiles.length;
|
|
5178
|
+
const hasConflicts = after.status.hasConflicts || conflictFiles.length > 0;
|
|
5179
|
+
const summaryParts = [];
|
|
5180
|
+
if (changedFiles > 0) summaryParts.push(`${changedFiles} ${plural(changedFiles, "file")} changed`);
|
|
5181
|
+
if (addedFiles.length > 0) summaryParts.push(`${addedFiles.length} added`);
|
|
5182
|
+
if (modifiedFiles.length > 0) summaryParts.push(`${modifiedFiles.length} modified`);
|
|
5183
|
+
if (deletedFiles.length > 0) summaryParts.push(`${deletedFiles.length} deleted`);
|
|
5184
|
+
if (renamedFiles.length > 0) summaryParts.push(`${renamedFiles.length} renamed`);
|
|
5185
|
+
if (untrackedFiles.length > 0) summaryParts.push(`${untrackedFiles.length} untracked`);
|
|
5186
|
+
if (hasConflicts) summaryParts.push(`${conflictFiles.length || 1} ${plural(conflictFiles.length || 1, "conflict")}`);
|
|
5187
|
+
return {
|
|
5188
|
+
beforeSnapshotId: before.id,
|
|
5189
|
+
afterSnapshotId: after.id,
|
|
5190
|
+
workspace: after.workspace,
|
|
5191
|
+
repoRoot: after.repoRoot,
|
|
5192
|
+
changedFiles,
|
|
5193
|
+
addedFiles: uniqueSorted(addedFiles),
|
|
5194
|
+
modifiedFiles: uniqueSorted(modifiedFiles),
|
|
5195
|
+
deletedFiles: uniqueSorted(deletedFiles),
|
|
5196
|
+
renamedFiles,
|
|
5197
|
+
untrackedFiles: uniqueSorted(untrackedFiles),
|
|
5198
|
+
conflictFiles,
|
|
5199
|
+
totalInsertions,
|
|
5200
|
+
totalDeletions,
|
|
5201
|
+
hasConflicts,
|
|
5202
|
+
currentStatus: after.status,
|
|
5203
|
+
summaryText: summaryParts.length > 0 ? summaryParts.join(", ") : "No file-set changes between snapshots."
|
|
5204
|
+
};
|
|
5205
|
+
}
|
|
5206
|
+
var InMemoryGitSnapshotStore = class {
|
|
5207
|
+
snapshots = /* @__PURE__ */ new Map();
|
|
5208
|
+
order = [];
|
|
5209
|
+
capacity;
|
|
5210
|
+
now;
|
|
5211
|
+
idPrefix;
|
|
5212
|
+
getStatusProvider;
|
|
5213
|
+
getDiffSummaryProvider;
|
|
5214
|
+
counter = 0;
|
|
5215
|
+
constructor(options = {}) {
|
|
5216
|
+
this.capacity = normalizeCapacity(options.capacity);
|
|
5217
|
+
this.now = options.now ?? Date.now;
|
|
5218
|
+
this.idPrefix = options.idPrefix ?? "git-snapshot";
|
|
5219
|
+
this.getStatusProvider = options.getStatus;
|
|
5220
|
+
this.getDiffSummaryProvider = options.getDiffSummary;
|
|
5221
|
+
}
|
|
5222
|
+
async create(input) {
|
|
5223
|
+
const getStatus = input.getStatus ?? this.getStatusProvider;
|
|
5224
|
+
if (!getStatus) {
|
|
5225
|
+
throw new Error("GitSnapshotStore requires an injected getStatus provider");
|
|
5226
|
+
}
|
|
5227
|
+
const status = await getStatus(input.workspace);
|
|
5228
|
+
const getDiffSummary = input.getDiffSummary ?? this.getDiffSummaryProvider;
|
|
5229
|
+
const diffSummary = getDiffSummary ? await getDiffSummary(input.workspace, status) : createEmptyDiffSummary(status);
|
|
5230
|
+
const createdAt = this.now();
|
|
5231
|
+
const id = `${this.idPrefix}-${createdAt}-${++this.counter}`;
|
|
5232
|
+
const snapshot = {
|
|
5233
|
+
id,
|
|
5234
|
+
workspace: input.workspace,
|
|
5235
|
+
repoRoot: status.repoRoot ?? input.workspace,
|
|
5236
|
+
sessionId: input.sessionId,
|
|
5237
|
+
turnId: input.turnId,
|
|
5238
|
+
reason: input.reason,
|
|
5239
|
+
status,
|
|
5240
|
+
diffSummary,
|
|
5241
|
+
createdAt
|
|
5242
|
+
};
|
|
5243
|
+
this.snapshots.set(id, snapshot);
|
|
5244
|
+
this.order.push(id);
|
|
5245
|
+
this.enforceCapacity();
|
|
5246
|
+
return snapshot;
|
|
5247
|
+
}
|
|
5248
|
+
get(id) {
|
|
5249
|
+
return this.snapshots.get(id);
|
|
5250
|
+
}
|
|
5251
|
+
compare(beforeSnapshotId, afterSnapshotId) {
|
|
5252
|
+
const before = this.snapshots.get(beforeSnapshotId);
|
|
5253
|
+
if (!before) throw new Error(`Unknown before snapshot: ${beforeSnapshotId}`);
|
|
5254
|
+
const after = this.snapshots.get(afterSnapshotId);
|
|
5255
|
+
if (!after) throw new Error(`Unknown after snapshot: ${afterSnapshotId}`);
|
|
5256
|
+
return compareGitSnapshots(before, after);
|
|
5257
|
+
}
|
|
5258
|
+
list(query = {}) {
|
|
5259
|
+
const limit = Math.max(1, Math.floor(query.limit ?? this.capacity));
|
|
5260
|
+
return this.order.map((id) => this.snapshots.get(id)).filter((snapshot) => Boolean(snapshot)).filter((snapshot) => !query.workspace || snapshot.workspace === query.workspace).filter((snapshot) => !query.sessionId || snapshot.sessionId === query.sessionId).slice(-limit);
|
|
5261
|
+
}
|
|
5262
|
+
clear() {
|
|
5263
|
+
this.snapshots.clear();
|
|
5264
|
+
this.order.splice(0, this.order.length);
|
|
5265
|
+
}
|
|
5266
|
+
enforceCapacity() {
|
|
5267
|
+
while (this.order.length > this.capacity) {
|
|
5268
|
+
const evictedId = this.order.shift();
|
|
5269
|
+
if (evictedId) this.snapshots.delete(evictedId);
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
};
|
|
5273
|
+
function createGitSnapshotStore(options = {}) {
|
|
5274
|
+
return new InMemoryGitSnapshotStore(options);
|
|
5275
|
+
}
|
|
5276
|
+
|
|
5277
|
+
// src/git/git-monitor.ts
|
|
5278
|
+
var DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS = 5e3;
|
|
5279
|
+
var MIN_GIT_WORKSPACE_POLL_INTERVAL_MS = 1e3;
|
|
5280
|
+
function defaultStatusProvider(workspace) {
|
|
5281
|
+
return getGitRepoStatus(workspace);
|
|
5282
|
+
}
|
|
5283
|
+
function defaultDiffSummaryProvider(workspace) {
|
|
5284
|
+
return getGitDiffSummary(workspace);
|
|
5285
|
+
}
|
|
5286
|
+
function normalizeIntervalMs(value, defaultIntervalMs, minIntervalMs) {
|
|
5287
|
+
const requested = Number.isFinite(value) ? Math.floor(value) : defaultIntervalMs;
|
|
5288
|
+
return Math.max(minIntervalMs, requested > 0 ? requested : defaultIntervalMs);
|
|
5289
|
+
}
|
|
5290
|
+
function normalizeGitWorkspaceSubscriptionParams(params, options = {}) {
|
|
5291
|
+
const minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
|
|
5292
|
+
const defaultIntervalMs = Math.max(minIntervalMs, Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS));
|
|
5293
|
+
return {
|
|
5294
|
+
workspace: params.workspace,
|
|
5295
|
+
includeDiffSummary: Boolean(params.includeDiffSummary),
|
|
5296
|
+
intervalMs: normalizeIntervalMs(params.intervalMs, defaultIntervalMs, minIntervalMs)
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
5299
|
+
var GitWorkspaceMonitor = class {
|
|
5300
|
+
getStatusProvider;
|
|
5301
|
+
getDiffSummaryProvider;
|
|
5302
|
+
now;
|
|
5303
|
+
minIntervalMs;
|
|
5304
|
+
defaultIntervalMs;
|
|
5305
|
+
keyPrefix;
|
|
5306
|
+
cache = /* @__PURE__ */ new Map();
|
|
5307
|
+
listeners = /* @__PURE__ */ new Set();
|
|
5308
|
+
seq = 0;
|
|
5309
|
+
constructor(options = {}) {
|
|
5310
|
+
this.getStatusProvider = options.getStatus ?? defaultStatusProvider;
|
|
5311
|
+
this.getDiffSummaryProvider = options.getDiffSummary ?? defaultDiffSummaryProvider;
|
|
5312
|
+
this.now = options.now ?? Date.now;
|
|
5313
|
+
this.minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
|
|
5314
|
+
this.defaultIntervalMs = Math.max(
|
|
5315
|
+
this.minIntervalMs,
|
|
5316
|
+
Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS)
|
|
5317
|
+
);
|
|
5318
|
+
this.keyPrefix = options.keyPrefix ?? "git";
|
|
5319
|
+
}
|
|
5320
|
+
async refresh(params) {
|
|
5321
|
+
const normalized = this.normalize(typeof params === "string" ? { workspace: params } : params);
|
|
5322
|
+
const status = await this.getStatusProvider(normalized.workspace);
|
|
5323
|
+
const diffSummary = normalized.includeDiffSummary ? await this.getDiffSummaryProvider(normalized.workspace, status) : void 0;
|
|
5324
|
+
const compactSummary = createGitCompactSummary(status, diffSummary);
|
|
5325
|
+
const timestamp = this.now();
|
|
5326
|
+
const seq = ++this.seq;
|
|
5327
|
+
const key = this.keyForWorkspace(normalized.workspace);
|
|
5328
|
+
const update = {
|
|
5329
|
+
topic: "workspace.git",
|
|
5330
|
+
key,
|
|
5331
|
+
workspace: normalized.workspace,
|
|
5332
|
+
status,
|
|
5333
|
+
diffSummary,
|
|
5334
|
+
seq,
|
|
5335
|
+
timestamp
|
|
5336
|
+
};
|
|
5337
|
+
const cacheEntry = {
|
|
5338
|
+
key,
|
|
5339
|
+
workspace: normalized.workspace,
|
|
5340
|
+
status,
|
|
5341
|
+
diffSummary,
|
|
5342
|
+
compactSummary,
|
|
5343
|
+
seq,
|
|
5344
|
+
timestamp
|
|
5345
|
+
};
|
|
5346
|
+
this.cache.set(normalized.workspace, cacheEntry);
|
|
5347
|
+
this.emit(update, cacheEntry);
|
|
5348
|
+
return update;
|
|
5349
|
+
}
|
|
5350
|
+
poll(params) {
|
|
5351
|
+
return this.refresh(params);
|
|
5352
|
+
}
|
|
5353
|
+
getCached(workspace) {
|
|
5354
|
+
return this.cache.get(workspace);
|
|
5355
|
+
}
|
|
5356
|
+
getCompactSummary(workspace) {
|
|
5357
|
+
return this.cache.get(workspace)?.compactSummary;
|
|
5358
|
+
}
|
|
5359
|
+
onUpdate(listener) {
|
|
5360
|
+
this.listeners.add(listener);
|
|
5361
|
+
return () => {
|
|
5362
|
+
this.listeners.delete(listener);
|
|
5363
|
+
};
|
|
5364
|
+
}
|
|
5365
|
+
createSubscription(params, listener) {
|
|
5366
|
+
const normalized = this.normalize(params);
|
|
5367
|
+
const scopedListener = listener ? (update, cacheEntry) => {
|
|
5368
|
+
if (update.workspace === normalized.workspace) listener(update, cacheEntry);
|
|
5369
|
+
} : void 0;
|
|
5370
|
+
const unsubscribe = scopedListener ? this.onUpdate(scopedListener) : () => void 0;
|
|
5371
|
+
return {
|
|
5372
|
+
params: normalized,
|
|
5373
|
+
refresh: () => this.refresh(normalized),
|
|
5374
|
+
getCached: () => this.getCached(normalized.workspace),
|
|
5375
|
+
dispose: unsubscribe
|
|
5376
|
+
};
|
|
5377
|
+
}
|
|
5378
|
+
normalize(params) {
|
|
5379
|
+
return normalizeGitWorkspaceSubscriptionParams(params, {
|
|
5380
|
+
defaultIntervalMs: this.defaultIntervalMs,
|
|
5381
|
+
minIntervalMs: this.minIntervalMs
|
|
5382
|
+
});
|
|
5383
|
+
}
|
|
5384
|
+
keyForWorkspace(workspace) {
|
|
5385
|
+
return `${this.keyPrefix}:${workspace}`;
|
|
5386
|
+
}
|
|
5387
|
+
emit(update, cacheEntry) {
|
|
5388
|
+
for (const listener of this.listeners) {
|
|
5389
|
+
listener(update, cacheEntry);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
};
|
|
5393
|
+
function createGitWorkspaceMonitor(options = {}) {
|
|
5394
|
+
return new GitWorkspaceMonitor(options);
|
|
5395
|
+
}
|
|
5396
|
+
|
|
5397
|
+
// src/git/git-commands.ts
|
|
5398
|
+
import * as path3 from "path";
|
|
5399
|
+
var GIT_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
5400
|
+
"git_status",
|
|
5401
|
+
"git_diff_summary",
|
|
5402
|
+
"git_diff_file",
|
|
5403
|
+
"git_snapshot_create",
|
|
5404
|
+
"git_snapshot_compare",
|
|
5405
|
+
"git_log",
|
|
5406
|
+
"git_checkpoint",
|
|
5407
|
+
"git_stash_push",
|
|
5408
|
+
"git_stash_pop",
|
|
5409
|
+
"git_checkout_files"
|
|
5410
|
+
]);
|
|
5411
|
+
var MUTATING_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
5412
|
+
"git_checkpoint",
|
|
5413
|
+
"git_stash_push",
|
|
5414
|
+
"git_stash_pop",
|
|
5415
|
+
"git_checkout_files"
|
|
5416
|
+
]);
|
|
5417
|
+
var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
|
|
5418
|
+
"session_baseline",
|
|
5419
|
+
"before_user_input_dispatch",
|
|
5420
|
+
"before_agent_work",
|
|
5421
|
+
"after_agent_work",
|
|
5422
|
+
"manual"
|
|
5423
|
+
]);
|
|
5424
|
+
var FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
5425
|
+
"not_git_repo",
|
|
5426
|
+
"git_not_installed",
|
|
5427
|
+
"timeout",
|
|
5428
|
+
"path_outside_repo",
|
|
5429
|
+
"dirty_index_required",
|
|
5430
|
+
"conflict",
|
|
5431
|
+
"invalid_args",
|
|
5432
|
+
"git_command_failed"
|
|
5433
|
+
]);
|
|
5434
|
+
function failure(reason, error) {
|
|
5435
|
+
return { success: false, reason, error };
|
|
5436
|
+
}
|
|
5437
|
+
function serviceNotImplemented(command) {
|
|
5438
|
+
return failure("invalid_args", `${command} is not implemented: daemon-core Git service is not configured`);
|
|
5439
|
+
}
|
|
5440
|
+
var defaultSnapshotStore = createGitSnapshotStore({
|
|
5441
|
+
getStatus: (workspace) => getGitRepoStatus(workspace),
|
|
5442
|
+
getDiffSummary: (workspace) => getGitDiffSummary(workspace)
|
|
5443
|
+
});
|
|
5444
|
+
function createDefaultGitCommandServices() {
|
|
5445
|
+
return {
|
|
5446
|
+
getStatus: ({ workspace }) => getGitRepoStatus(workspace),
|
|
5447
|
+
getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
|
|
5448
|
+
getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
|
|
5449
|
+
createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
|
|
5450
|
+
workspace,
|
|
5451
|
+
reason,
|
|
5452
|
+
sessionId,
|
|
5453
|
+
turnId
|
|
5454
|
+
}),
|
|
5455
|
+
compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
|
|
5456
|
+
getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until })
|
|
5457
|
+
};
|
|
5458
|
+
}
|
|
5459
|
+
var defaultGitCommandServices = createDefaultGitCommandServices();
|
|
5460
|
+
function validateWorkspace2(args) {
|
|
5461
|
+
if (typeof args?.workspace !== "string") {
|
|
5462
|
+
return failure("invalid_args", "workspace must be a non-empty absolute path");
|
|
5463
|
+
}
|
|
5464
|
+
const workspace = args.workspace.trim();
|
|
5465
|
+
if (!workspace || !path3.isAbsolute(workspace)) {
|
|
5466
|
+
return failure("invalid_args", "workspace must be a non-empty absolute path");
|
|
5467
|
+
}
|
|
5468
|
+
return { workspace };
|
|
5469
|
+
}
|
|
5470
|
+
function validateRepoPath(args) {
|
|
5471
|
+
if (typeof args?.path !== "string" || !args.path.trim()) {
|
|
5472
|
+
return failure("invalid_args", "path must be a non-empty repository-relative path");
|
|
5473
|
+
}
|
|
5474
|
+
return { path: args.path.trim() };
|
|
5475
|
+
}
|
|
5476
|
+
function validateSnapshotId(args, key) {
|
|
5477
|
+
if (typeof args?.[key] !== "string" || !args[key].trim()) {
|
|
5478
|
+
return failure("invalid_args", `${key} must be a non-empty string`);
|
|
5479
|
+
}
|
|
5480
|
+
return args[key].trim();
|
|
5481
|
+
}
|
|
5482
|
+
function parseSnapshotReason(args) {
|
|
5483
|
+
if (args?.reason === void 0 || args?.reason === null || args?.reason === "") {
|
|
5484
|
+
return "manual";
|
|
5485
|
+
}
|
|
5486
|
+
if (typeof args.reason !== "string" || !SNAPSHOT_REASONS.has(args.reason)) {
|
|
5487
|
+
return failure("invalid_args", "reason must be a valid GitSnapshotReason");
|
|
5488
|
+
}
|
|
5489
|
+
return args.reason;
|
|
5490
|
+
}
|
|
5491
|
+
function optionalString(value) {
|
|
5492
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
5493
|
+
}
|
|
5494
|
+
function optionalBoolean(value) {
|
|
5495
|
+
return typeof value === "boolean" ? value : void 0;
|
|
5496
|
+
}
|
|
5497
|
+
function boundedLogLimit(value) {
|
|
5498
|
+
if (value === void 0 || value === null || value === "") return 50;
|
|
5499
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
5500
|
+
if (!Number.isFinite(numeric)) return 50;
|
|
5501
|
+
return Math.max(1, Math.min(200, Math.floor(numeric)));
|
|
5502
|
+
}
|
|
5503
|
+
function failureReasonFromError(error) {
|
|
5504
|
+
return typeof error?.reason === "string" && FAILURE_REASONS.has(error.reason) ? error.reason : "git_command_failed";
|
|
5505
|
+
}
|
|
5506
|
+
async function runService(fn) {
|
|
5507
|
+
try {
|
|
5508
|
+
return await fn();
|
|
5509
|
+
} catch (error) {
|
|
5510
|
+
return failure(failureReasonFromError(error), error?.message || "Git command failed");
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
function isGitCommandName(command) {
|
|
5514
|
+
return GIT_COMMAND_NAMES.has(command);
|
|
5515
|
+
}
|
|
5516
|
+
async function handleGitCommand(command, args, services = defaultGitCommandServices) {
|
|
5517
|
+
if (!isGitCommandName(command)) {
|
|
5518
|
+
return failure("invalid_args", `Unknown Git command: ${command}`);
|
|
5519
|
+
}
|
|
5520
|
+
if (MUTATING_COMMAND_NAMES.has(command)) {
|
|
5521
|
+
return failure("invalid_args", `${command} is not implemented in daemon-core read-only Git routing`);
|
|
5522
|
+
}
|
|
5523
|
+
const workspaceResult = validateWorkspace2(args);
|
|
5524
|
+
if ("success" in workspaceResult) return workspaceResult;
|
|
5525
|
+
const { workspace } = workspaceResult;
|
|
5526
|
+
switch (command) {
|
|
5527
|
+
case "git_status": {
|
|
5528
|
+
if (!services.getStatus) return serviceNotImplemented(command);
|
|
5529
|
+
const status = await runService(() => services.getStatus({ workspace }));
|
|
5530
|
+
return "success" in status ? status : { success: true, status };
|
|
5531
|
+
}
|
|
5532
|
+
case "git_diff_summary": {
|
|
5533
|
+
if (!services.getDiffSummary) return serviceNotImplemented(command);
|
|
5534
|
+
const diffSummary = await runService(() => services.getDiffSummary({ workspace, staged: optionalBoolean(args?.staged) }));
|
|
5535
|
+
return "success" in diffSummary ? diffSummary : { success: true, diffSummary };
|
|
5536
|
+
}
|
|
5537
|
+
case "git_diff_file": {
|
|
5538
|
+
if (!services.getDiffFile) return serviceNotImplemented(command);
|
|
5539
|
+
const pathResult = validateRepoPath(args);
|
|
5540
|
+
if (typeof pathResult !== "object" || "success" in pathResult) return pathResult;
|
|
5541
|
+
const diff = await runService(() => services.getDiffFile({
|
|
5542
|
+
workspace,
|
|
5543
|
+
path: pathResult.path,
|
|
5544
|
+
staged: optionalBoolean(args?.staged)
|
|
5545
|
+
}));
|
|
5546
|
+
return "success" in diff ? diff : { success: true, diff };
|
|
5547
|
+
}
|
|
5548
|
+
case "git_snapshot_create": {
|
|
5549
|
+
if (!services.createSnapshot) return serviceNotImplemented(command);
|
|
5550
|
+
const reason = parseSnapshotReason(args);
|
|
5551
|
+
if (typeof reason !== "string") return reason;
|
|
5552
|
+
const snapshot = await runService(() => services.createSnapshot({
|
|
5553
|
+
workspace,
|
|
5554
|
+
reason,
|
|
5555
|
+
sessionId: optionalString(args?.sessionId),
|
|
5556
|
+
turnId: optionalString(args?.turnId)
|
|
5557
|
+
}));
|
|
5558
|
+
return "success" in snapshot ? snapshot : { success: true, snapshot };
|
|
5559
|
+
}
|
|
5560
|
+
case "git_snapshot_compare": {
|
|
5561
|
+
if (!services.compareSnapshots) return serviceNotImplemented(command);
|
|
5562
|
+
const beforeSnapshotId = validateSnapshotId(args, "beforeSnapshotId");
|
|
5563
|
+
if (typeof beforeSnapshotId !== "string") return beforeSnapshotId;
|
|
5564
|
+
const afterSnapshotId = validateSnapshotId(args, "afterSnapshotId");
|
|
5565
|
+
if (typeof afterSnapshotId !== "string") return afterSnapshotId;
|
|
5566
|
+
const compare = await runService(() => services.compareSnapshots({ workspace, beforeSnapshotId, afterSnapshotId }));
|
|
5567
|
+
return "success" in compare ? compare : { success: true, compare };
|
|
5568
|
+
}
|
|
5569
|
+
case "git_log": {
|
|
5570
|
+
if (!services.getLog) {
|
|
5571
|
+
return failure("invalid_args", "git_log is not implemented: bounded daemon-core Git log service is not configured");
|
|
5572
|
+
}
|
|
5573
|
+
const log = await runService(() => services.getLog({
|
|
5574
|
+
workspace,
|
|
5575
|
+
limit: boundedLogLimit(args?.limit),
|
|
5576
|
+
path: optionalString(args?.path),
|
|
5577
|
+
since: optionalString(args?.since),
|
|
5578
|
+
until: optionalString(args?.until)
|
|
5579
|
+
}));
|
|
5580
|
+
return "success" in log ? log : { success: true, log };
|
|
5581
|
+
}
|
|
5582
|
+
default:
|
|
5583
|
+
return failure("invalid_args", `Unknown Git command: ${command}`);
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5586
|
+
function formatOptionalGitLogRangeArg(flag, value) {
|
|
5587
|
+
return value ? [`${flag}=${value}`] : [];
|
|
5588
|
+
}
|
|
5589
|
+
async function getGitLog(workspace, options) {
|
|
5590
|
+
const lastCheckedAt = Date.now();
|
|
5591
|
+
const repo = await resolveGitRepository(workspace);
|
|
5592
|
+
const repoRoot = repo.repoRoot;
|
|
5593
|
+
const boundedLimit = Math.max(1, Math.min(200, Math.floor(options.limit || 50)));
|
|
5594
|
+
const selectedPath = options.path ? validateGitLogPath(repoRoot, options.path) : void 0;
|
|
5595
|
+
const result = await runGit(
|
|
5596
|
+
repo,
|
|
5597
|
+
[
|
|
5598
|
+
"log",
|
|
5599
|
+
`--max-count=${boundedLimit}`,
|
|
5600
|
+
"--format=%H%x00%an%x00%ae%x00%at%x00%ct%x00%s",
|
|
5601
|
+
...formatOptionalGitLogRangeArg("--since", options.since),
|
|
5602
|
+
...formatOptionalGitLogRangeArg("--until", options.until),
|
|
5603
|
+
"--",
|
|
5604
|
+
...selectedPath ? [selectedPath] : []
|
|
5605
|
+
],
|
|
5606
|
+
{ cwd: repoRoot }
|
|
5607
|
+
);
|
|
5608
|
+
const entries = result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
|
|
5609
|
+
const [commit = "", authorName, authorEmail, authoredAt, committedAt, ...messageParts] = line.split("\0");
|
|
5610
|
+
return {
|
|
5611
|
+
commit,
|
|
5612
|
+
message: messageParts.join("\0"),
|
|
5613
|
+
authorName: authorName || void 0,
|
|
5614
|
+
authorEmail: authorEmail || void 0,
|
|
5615
|
+
authoredAt: authoredAt ? Number.parseInt(authoredAt, 10) * 1e3 : void 0,
|
|
5616
|
+
committedAt: committedAt ? Number.parseInt(committedAt, 10) * 1e3 : void 0
|
|
5617
|
+
};
|
|
5618
|
+
}).filter((entry) => entry.commit.length > 0);
|
|
5619
|
+
return {
|
|
5620
|
+
workspace: repo.workspace,
|
|
5621
|
+
repoRoot,
|
|
5622
|
+
isGitRepo: true,
|
|
5623
|
+
entries,
|
|
5624
|
+
limit: boundedLimit,
|
|
5625
|
+
truncated: entries.length >= boundedLimit,
|
|
5626
|
+
lastCheckedAt
|
|
5627
|
+
};
|
|
5628
|
+
}
|
|
5629
|
+
function validateGitLogPath(repoRoot, filePath) {
|
|
5630
|
+
if (!filePath.trim() || filePath.includes("\0")) {
|
|
5631
|
+
throw new GitCommandError("invalid_args", "path must be a non-empty repository-relative path");
|
|
5632
|
+
}
|
|
5633
|
+
if (path3.isAbsolute(filePath)) {
|
|
5634
|
+
throw new GitCommandError("invalid_args", "path must be repository-relative");
|
|
5635
|
+
}
|
|
5636
|
+
const normalized = path3.normalize(filePath).split(path3.sep).join("/");
|
|
5637
|
+
const absolutePath = path3.resolve(repoRoot, normalized);
|
|
5638
|
+
if (!isPathInside(repoRoot, absolutePath) || normalized.startsWith("../") || normalized === "..") {
|
|
5639
|
+
throw new GitCommandError("path_outside_repo", "Git log path is outside the repository root");
|
|
5640
|
+
}
|
|
5641
|
+
return normalized;
|
|
5642
|
+
}
|
|
5643
|
+
|
|
4527
5644
|
// src/index.ts
|
|
4528
5645
|
init_config();
|
|
4529
5646
|
|
|
4530
5647
|
// src/config/workspaces.ts
|
|
4531
5648
|
import * as fs from "fs";
|
|
4532
5649
|
import * as os from "os";
|
|
4533
|
-
import * as
|
|
5650
|
+
import * as path4 from "path";
|
|
4534
5651
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4535
5652
|
var MAX_WORKSPACES = 50;
|
|
4536
5653
|
function expandPath(p) {
|
|
4537
5654
|
const t = (p || "").trim();
|
|
4538
5655
|
if (!t) return "";
|
|
4539
|
-
if (t.startsWith("~")) return
|
|
4540
|
-
return
|
|
5656
|
+
if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
5657
|
+
return path4.resolve(t);
|
|
4541
5658
|
}
|
|
4542
5659
|
function validateWorkspacePath(absPath) {
|
|
4543
5660
|
try {
|
|
@@ -4551,7 +5668,7 @@ function validateWorkspacePath(absPath) {
|
|
|
4551
5668
|
}
|
|
4552
5669
|
}
|
|
4553
5670
|
function defaultWorkspaceLabel(absPath) {
|
|
4554
|
-
const base =
|
|
5671
|
+
const base = path4.basename(absPath) || absPath;
|
|
4555
5672
|
return base;
|
|
4556
5673
|
}
|
|
4557
5674
|
function getDefaultWorkspacePath(config) {
|
|
@@ -4642,9 +5759,9 @@ function resolveIdeLaunchWorkspace(args, config) {
|
|
|
4642
5759
|
return getDefaultWorkspacePath(config) || void 0;
|
|
4643
5760
|
}
|
|
4644
5761
|
function findWorkspaceByPath(config, rawPath) {
|
|
4645
|
-
const abs =
|
|
5762
|
+
const abs = path4.resolve(expandPath(rawPath));
|
|
4646
5763
|
if (!abs) return void 0;
|
|
4647
|
-
return (config.workspaces || []).find((w) =>
|
|
5764
|
+
return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
|
|
4648
5765
|
}
|
|
4649
5766
|
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
4650
5767
|
const abs = expandPath(rawPath);
|
|
@@ -4660,7 +5777,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
|
|
|
4660
5777
|
const v = validateWorkspacePath(abs);
|
|
4661
5778
|
if (!v.ok) return { error: v.error };
|
|
4662
5779
|
const list = [...config.workspaces || []];
|
|
4663
|
-
if (list.some((w) =>
|
|
5780
|
+
if (list.some((w) => path4.resolve(w.path) === abs)) {
|
|
4664
5781
|
return { error: "Workspace already in list" };
|
|
4665
5782
|
}
|
|
4666
5783
|
if (list.length >= MAX_WORKSPACES) {
|
|
@@ -4694,7 +5811,7 @@ function setDefaultWorkspaceId(config, id) {
|
|
|
4694
5811
|
}
|
|
4695
5812
|
|
|
4696
5813
|
// src/config/recent-activity.ts
|
|
4697
|
-
import * as
|
|
5814
|
+
import * as path5 from "path";
|
|
4698
5815
|
|
|
4699
5816
|
// src/providers/summary-metadata.ts
|
|
4700
5817
|
function normalizeSummaryItem(item) {
|
|
@@ -4763,9 +5880,9 @@ var MAX_ACTIVITY = 30;
|
|
|
4763
5880
|
function normalizeWorkspace(workspace) {
|
|
4764
5881
|
if (!workspace) return "";
|
|
4765
5882
|
try {
|
|
4766
|
-
return
|
|
5883
|
+
return path5.resolve(expandPath(workspace));
|
|
4767
5884
|
} catch {
|
|
4768
|
-
return
|
|
5885
|
+
return path5.resolve(workspace);
|
|
4769
5886
|
}
|
|
4770
5887
|
}
|
|
4771
5888
|
function buildRecentActivityKey(entry) {
|
|
@@ -4933,14 +6050,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
|
|
|
4933
6050
|
}
|
|
4934
6051
|
|
|
4935
6052
|
// src/config/saved-sessions.ts
|
|
4936
|
-
import * as
|
|
6053
|
+
import * as path6 from "path";
|
|
4937
6054
|
var MAX_SAVED_SESSIONS = 500;
|
|
4938
6055
|
function normalizeWorkspace2(workspace) {
|
|
4939
6056
|
if (!workspace) return "";
|
|
4940
6057
|
try {
|
|
4941
|
-
return
|
|
6058
|
+
return path6.resolve(expandPath(workspace));
|
|
4942
6059
|
} catch {
|
|
4943
|
-
return
|
|
6060
|
+
return path6.resolve(workspace);
|
|
4944
6061
|
}
|
|
4945
6062
|
}
|
|
4946
6063
|
function buildSavedProviderSessionKey(providerSessionId) {
|
|
@@ -5059,7 +6176,7 @@ function resetState() {
|
|
|
5059
6176
|
import { execSync } from "child_process";
|
|
5060
6177
|
import { existsSync as existsSync4 } from "fs";
|
|
5061
6178
|
import { platform, homedir as homedir3 } from "os";
|
|
5062
|
-
import * as
|
|
6179
|
+
import * as path7 from "path";
|
|
5063
6180
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
5064
6181
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
5065
6182
|
function registerIDEDefinition(def) {
|
|
@@ -5078,9 +6195,9 @@ function getMergedDefinitions() {
|
|
|
5078
6195
|
function findCliCommand(command) {
|
|
5079
6196
|
const trimmed = String(command || "").trim();
|
|
5080
6197
|
if (!trimmed) return null;
|
|
5081
|
-
if (
|
|
5082
|
-
const candidate = trimmed.startsWith("~") ?
|
|
5083
|
-
const resolved =
|
|
6198
|
+
if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
6199
|
+
const candidate = trimmed.startsWith("~") ? path7.join(homedir3(), trimmed.slice(1)) : trimmed;
|
|
6200
|
+
const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
|
|
5084
6201
|
return existsSync4(resolved) ? resolved : null;
|
|
5085
6202
|
}
|
|
5086
6203
|
try {
|
|
@@ -5108,7 +6225,7 @@ function getIdeVersion(cliCommand) {
|
|
|
5108
6225
|
function checkPathExists(paths) {
|
|
5109
6226
|
const home = homedir3();
|
|
5110
6227
|
for (const p of paths) {
|
|
5111
|
-
const normalized = p.startsWith("~") ?
|
|
6228
|
+
const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
|
|
5112
6229
|
if (normalized.includes("*")) {
|
|
5113
6230
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5114
6231
|
const resolved = normalized.replace("*", username);
|
|
@@ -5166,7 +6283,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5166
6283
|
// src/detection/cli-detector.ts
|
|
5167
6284
|
import { exec } from "child_process";
|
|
5168
6285
|
import * as os2 from "os";
|
|
5169
|
-
import * as
|
|
6286
|
+
import * as path8 from "path";
|
|
5170
6287
|
import { existsSync as existsSync5 } from "fs";
|
|
5171
6288
|
function parseVersion(raw) {
|
|
5172
6289
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
@@ -5179,36 +6296,36 @@ function shellQuote(value) {
|
|
|
5179
6296
|
function expandHome(value) {
|
|
5180
6297
|
const trimmed = value.trim();
|
|
5181
6298
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
5182
|
-
return
|
|
6299
|
+
return path8.join(os2.homedir(), trimmed.slice(1));
|
|
5183
6300
|
}
|
|
5184
6301
|
function isExplicitCommandPath(command) {
|
|
5185
6302
|
const trimmed = command.trim();
|
|
5186
|
-
return
|
|
6303
|
+
return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
5187
6304
|
}
|
|
5188
6305
|
function resolveCommandPath(command) {
|
|
5189
6306
|
const trimmed = command.trim();
|
|
5190
6307
|
if (!trimmed) return null;
|
|
5191
6308
|
if (isExplicitCommandPath(trimmed)) {
|
|
5192
6309
|
const expanded = expandHome(trimmed);
|
|
5193
|
-
const candidate =
|
|
6310
|
+
const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
|
|
5194
6311
|
return existsSync5(candidate) ? candidate : null;
|
|
5195
6312
|
}
|
|
5196
6313
|
return null;
|
|
5197
6314
|
}
|
|
5198
6315
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
5199
|
-
return new Promise((
|
|
6316
|
+
return new Promise((resolve15) => {
|
|
5200
6317
|
const child = exec(cmd, {
|
|
5201
6318
|
encoding: "utf-8",
|
|
5202
6319
|
timeout: timeoutMs,
|
|
5203
6320
|
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
5204
6321
|
}, (err, stdout) => {
|
|
5205
6322
|
if (err || !stdout?.trim()) {
|
|
5206
|
-
|
|
6323
|
+
resolve15(null);
|
|
5207
6324
|
} else {
|
|
5208
|
-
|
|
6325
|
+
resolve15(stdout.trim());
|
|
5209
6326
|
}
|
|
5210
6327
|
});
|
|
5211
|
-
child.on("error", () =>
|
|
6328
|
+
child.on("error", () => resolve15(null));
|
|
5212
6329
|
});
|
|
5213
6330
|
}
|
|
5214
6331
|
async function detectCLIs(providerLoader, options) {
|
|
@@ -5573,7 +6690,7 @@ var DaemonCdpManager = class {
|
|
|
5573
6690
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
5574
6691
|
*/
|
|
5575
6692
|
static listAllTargets(port) {
|
|
5576
|
-
return new Promise((
|
|
6693
|
+
return new Promise((resolve15) => {
|
|
5577
6694
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
5578
6695
|
let data = "";
|
|
5579
6696
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -5589,16 +6706,16 @@ var DaemonCdpManager = class {
|
|
|
5589
6706
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
5590
6707
|
);
|
|
5591
6708
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
5592
|
-
|
|
6709
|
+
resolve15(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
5593
6710
|
} catch {
|
|
5594
|
-
|
|
6711
|
+
resolve15([]);
|
|
5595
6712
|
}
|
|
5596
6713
|
});
|
|
5597
6714
|
});
|
|
5598
|
-
req.on("error", () =>
|
|
6715
|
+
req.on("error", () => resolve15([]));
|
|
5599
6716
|
req.setTimeout(2e3, () => {
|
|
5600
6717
|
req.destroy();
|
|
5601
|
-
|
|
6718
|
+
resolve15([]);
|
|
5602
6719
|
});
|
|
5603
6720
|
});
|
|
5604
6721
|
}
|
|
@@ -5638,7 +6755,7 @@ var DaemonCdpManager = class {
|
|
|
5638
6755
|
}
|
|
5639
6756
|
}
|
|
5640
6757
|
findTargetOnPort(port) {
|
|
5641
|
-
return new Promise((
|
|
6758
|
+
return new Promise((resolve15) => {
|
|
5642
6759
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
5643
6760
|
let data = "";
|
|
5644
6761
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -5649,7 +6766,7 @@ var DaemonCdpManager = class {
|
|
|
5649
6766
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
5650
6767
|
);
|
|
5651
6768
|
if (pages.length === 0) {
|
|
5652
|
-
|
|
6769
|
+
resolve15(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
5653
6770
|
return;
|
|
5654
6771
|
}
|
|
5655
6772
|
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -5668,25 +6785,25 @@ var DaemonCdpManager = class {
|
|
|
5668
6785
|
this._targetId = selected.target.id;
|
|
5669
6786
|
}
|
|
5670
6787
|
this._pageTitle = selected.target.title || "";
|
|
5671
|
-
|
|
6788
|
+
resolve15(selected.target);
|
|
5672
6789
|
return;
|
|
5673
6790
|
}
|
|
5674
6791
|
if (previousTargetId) {
|
|
5675
6792
|
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
5676
|
-
|
|
6793
|
+
resolve15(null);
|
|
5677
6794
|
return;
|
|
5678
6795
|
}
|
|
5679
6796
|
this._pageTitle = list[0]?.title || "";
|
|
5680
|
-
|
|
6797
|
+
resolve15(list[0]);
|
|
5681
6798
|
} catch {
|
|
5682
|
-
|
|
6799
|
+
resolve15(null);
|
|
5683
6800
|
}
|
|
5684
6801
|
});
|
|
5685
6802
|
});
|
|
5686
|
-
req.on("error", () =>
|
|
6803
|
+
req.on("error", () => resolve15(null));
|
|
5687
6804
|
req.setTimeout(2e3, () => {
|
|
5688
6805
|
req.destroy();
|
|
5689
|
-
|
|
6806
|
+
resolve15(null);
|
|
5690
6807
|
});
|
|
5691
6808
|
});
|
|
5692
6809
|
}
|
|
@@ -5697,7 +6814,7 @@ var DaemonCdpManager = class {
|
|
|
5697
6814
|
this.extensionProviders = providers;
|
|
5698
6815
|
}
|
|
5699
6816
|
connectToTarget(wsUrl) {
|
|
5700
|
-
return new Promise((
|
|
6817
|
+
return new Promise((resolve15) => {
|
|
5701
6818
|
this.ws = new WebSocket(wsUrl);
|
|
5702
6819
|
this.ws.on("open", async () => {
|
|
5703
6820
|
this._connected = true;
|
|
@@ -5707,17 +6824,17 @@ var DaemonCdpManager = class {
|
|
|
5707
6824
|
}
|
|
5708
6825
|
this.connectBrowserWs().catch(() => {
|
|
5709
6826
|
});
|
|
5710
|
-
|
|
6827
|
+
resolve15(true);
|
|
5711
6828
|
});
|
|
5712
6829
|
this.ws.on("message", (data) => {
|
|
5713
6830
|
try {
|
|
5714
6831
|
const msg = JSON.parse(data.toString());
|
|
5715
6832
|
if (msg.id && this.pending.has(msg.id)) {
|
|
5716
|
-
const { resolve:
|
|
6833
|
+
const { resolve: resolve16, reject } = this.pending.get(msg.id);
|
|
5717
6834
|
this.pending.delete(msg.id);
|
|
5718
6835
|
this.failureCount = 0;
|
|
5719
6836
|
if (msg.error) reject(new Error(msg.error.message));
|
|
5720
|
-
else
|
|
6837
|
+
else resolve16(msg.result);
|
|
5721
6838
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
5722
6839
|
this.contexts.add(msg.params.context.id);
|
|
5723
6840
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -5740,7 +6857,7 @@ var DaemonCdpManager = class {
|
|
|
5740
6857
|
this.ws.on("error", (err) => {
|
|
5741
6858
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
5742
6859
|
this._connected = false;
|
|
5743
|
-
|
|
6860
|
+
resolve15(false);
|
|
5744
6861
|
});
|
|
5745
6862
|
});
|
|
5746
6863
|
}
|
|
@@ -5754,7 +6871,7 @@ var DaemonCdpManager = class {
|
|
|
5754
6871
|
return;
|
|
5755
6872
|
}
|
|
5756
6873
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
5757
|
-
await new Promise((
|
|
6874
|
+
await new Promise((resolve15, reject) => {
|
|
5758
6875
|
this.browserWs = new WebSocket(browserWsUrl);
|
|
5759
6876
|
this.browserWs.on("open", async () => {
|
|
5760
6877
|
this._browserConnected = true;
|
|
@@ -5764,16 +6881,16 @@ var DaemonCdpManager = class {
|
|
|
5764
6881
|
} catch (e) {
|
|
5765
6882
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
5766
6883
|
}
|
|
5767
|
-
|
|
6884
|
+
resolve15();
|
|
5768
6885
|
});
|
|
5769
6886
|
this.browserWs.on("message", (data) => {
|
|
5770
6887
|
try {
|
|
5771
6888
|
const msg = JSON.parse(data.toString());
|
|
5772
6889
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
5773
|
-
const { resolve:
|
|
6890
|
+
const { resolve: resolve16, reject: reject2 } = this.browserPending.get(msg.id);
|
|
5774
6891
|
this.browserPending.delete(msg.id);
|
|
5775
6892
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
5776
|
-
else
|
|
6893
|
+
else resolve16(msg.result);
|
|
5777
6894
|
}
|
|
5778
6895
|
} catch {
|
|
5779
6896
|
}
|
|
@@ -5793,31 +6910,31 @@ var DaemonCdpManager = class {
|
|
|
5793
6910
|
}
|
|
5794
6911
|
}
|
|
5795
6912
|
getBrowserWsUrl() {
|
|
5796
|
-
return new Promise((
|
|
6913
|
+
return new Promise((resolve15) => {
|
|
5797
6914
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
5798
6915
|
let data = "";
|
|
5799
6916
|
res.on("data", (chunk) => data += chunk.toString());
|
|
5800
6917
|
res.on("end", () => {
|
|
5801
6918
|
try {
|
|
5802
6919
|
const info = JSON.parse(data);
|
|
5803
|
-
|
|
6920
|
+
resolve15(info.webSocketDebuggerUrl || null);
|
|
5804
6921
|
} catch {
|
|
5805
|
-
|
|
6922
|
+
resolve15(null);
|
|
5806
6923
|
}
|
|
5807
6924
|
});
|
|
5808
6925
|
});
|
|
5809
|
-
req.on("error", () =>
|
|
6926
|
+
req.on("error", () => resolve15(null));
|
|
5810
6927
|
req.setTimeout(3e3, () => {
|
|
5811
6928
|
req.destroy();
|
|
5812
|
-
|
|
6929
|
+
resolve15(null);
|
|
5813
6930
|
});
|
|
5814
6931
|
});
|
|
5815
6932
|
}
|
|
5816
6933
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
5817
|
-
return new Promise((
|
|
6934
|
+
return new Promise((resolve15, reject) => {
|
|
5818
6935
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
5819
6936
|
const id = this.browserMsgId++;
|
|
5820
|
-
this.browserPending.set(id, { resolve:
|
|
6937
|
+
this.browserPending.set(id, { resolve: resolve15, reject });
|
|
5821
6938
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
5822
6939
|
setTimeout(() => {
|
|
5823
6940
|
if (this.browserPending.has(id)) {
|
|
@@ -5857,11 +6974,11 @@ var DaemonCdpManager = class {
|
|
|
5857
6974
|
}
|
|
5858
6975
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
5859
6976
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
5860
|
-
return new Promise((
|
|
6977
|
+
return new Promise((resolve15, reject) => {
|
|
5861
6978
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
5862
6979
|
if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
|
|
5863
6980
|
const id = this.msgId++;
|
|
5864
|
-
this.pending.set(id, { resolve:
|
|
6981
|
+
this.pending.set(id, { resolve: resolve15, reject });
|
|
5865
6982
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
5866
6983
|
setTimeout(() => {
|
|
5867
6984
|
if (this.pending.has(id)) {
|
|
@@ -6110,7 +7227,7 @@ var DaemonCdpManager = class {
|
|
|
6110
7227
|
const browserWs = this.browserWs;
|
|
6111
7228
|
let msgId = this.browserMsgId;
|
|
6112
7229
|
const sendWs = (method, params = {}, sessionId) => {
|
|
6113
|
-
return new Promise((
|
|
7230
|
+
return new Promise((resolve15, reject) => {
|
|
6114
7231
|
const mid = msgId++;
|
|
6115
7232
|
this.browserMsgId = msgId;
|
|
6116
7233
|
const handler = (raw) => {
|
|
@@ -6119,7 +7236,7 @@ var DaemonCdpManager = class {
|
|
|
6119
7236
|
if (msg.id === mid) {
|
|
6120
7237
|
browserWs.removeListener("message", handler);
|
|
6121
7238
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
6122
|
-
else
|
|
7239
|
+
else resolve15(msg.result);
|
|
6123
7240
|
}
|
|
6124
7241
|
} catch {
|
|
6125
7242
|
}
|
|
@@ -6320,14 +7437,14 @@ var DaemonCdpManager = class {
|
|
|
6320
7437
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
6321
7438
|
throw new Error("CDP not connected");
|
|
6322
7439
|
}
|
|
6323
|
-
return new Promise((
|
|
7440
|
+
return new Promise((resolve15, reject) => {
|
|
6324
7441
|
const id = getNextId();
|
|
6325
7442
|
pendingMap.set(id, {
|
|
6326
7443
|
resolve: (result) => {
|
|
6327
7444
|
if (result?.result?.subtype === "error") {
|
|
6328
7445
|
reject(new Error(result.result.description));
|
|
6329
7446
|
} else {
|
|
6330
|
-
|
|
7447
|
+
resolve15(result?.result?.value);
|
|
6331
7448
|
}
|
|
6332
7449
|
},
|
|
6333
7450
|
reject
|
|
@@ -6359,10 +7476,10 @@ var DaemonCdpManager = class {
|
|
|
6359
7476
|
throw new Error("CDP not connected");
|
|
6360
7477
|
}
|
|
6361
7478
|
const sendViaSession = (method, params = {}) => {
|
|
6362
|
-
return new Promise((
|
|
7479
|
+
return new Promise((resolve15, reject) => {
|
|
6363
7480
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
6364
7481
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
6365
|
-
pendingMap.set(id, { resolve:
|
|
7482
|
+
pendingMap.set(id, { resolve: resolve15, reject });
|
|
6366
7483
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
6367
7484
|
setTimeout(() => {
|
|
6368
7485
|
if (pendingMap.has(id)) {
|
|
@@ -7109,9 +8226,9 @@ ${cleanBody}`;
|
|
|
7109
8226
|
// src/config/chat-history.ts
|
|
7110
8227
|
init_chat_message_normalization();
|
|
7111
8228
|
import * as fs3 from "fs";
|
|
7112
|
-
import * as
|
|
8229
|
+
import * as path10 from "path";
|
|
7113
8230
|
import * as os5 from "os";
|
|
7114
|
-
var HISTORY_DIR =
|
|
8231
|
+
var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
|
|
7115
8232
|
var RETAIN_DAYS = 30;
|
|
7116
8233
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
7117
8234
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -7274,8 +8391,8 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
7274
8391
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
7275
8392
|
return new Map(files.map((file) => {
|
|
7276
8393
|
try {
|
|
7277
|
-
const
|
|
7278
|
-
return [file, `${file}:${
|
|
8394
|
+
const stat2 = fs3.statSync(path10.join(dir, file));
|
|
8395
|
+
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
7279
8396
|
} catch {
|
|
7280
8397
|
return [file, `${file}:missing`];
|
|
7281
8398
|
}
|
|
@@ -7285,7 +8402,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
7285
8402
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
7286
8403
|
}
|
|
7287
8404
|
function getSavedHistoryIndexFilePath(dir) {
|
|
7288
|
-
return
|
|
8405
|
+
return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
7289
8406
|
}
|
|
7290
8407
|
function getSavedHistoryIndexLockPath(dir) {
|
|
7291
8408
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -7338,8 +8455,8 @@ function acquireSavedHistoryIndexLock(dir) {
|
|
|
7338
8455
|
} catch (error) {
|
|
7339
8456
|
if (error?.code !== "EEXIST") return null;
|
|
7340
8457
|
try {
|
|
7341
|
-
const
|
|
7342
|
-
if (Date.now() -
|
|
8458
|
+
const stat2 = fs3.statSync(lockPath);
|
|
8459
|
+
if (Date.now() - stat2.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
7343
8460
|
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
7344
8461
|
continue;
|
|
7345
8462
|
}
|
|
@@ -7387,7 +8504,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
7387
8504
|
}
|
|
7388
8505
|
for (const file of Array.from(currentEntries.keys())) {
|
|
7389
8506
|
if (incomingFiles.has(file)) continue;
|
|
7390
|
-
if (!fs3.existsSync(
|
|
8507
|
+
if (!fs3.existsSync(path10.join(dir, file))) {
|
|
7391
8508
|
currentEntries.delete(file);
|
|
7392
8509
|
}
|
|
7393
8510
|
}
|
|
@@ -7402,8 +8519,8 @@ function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
|
7402
8519
|
}
|
|
7403
8520
|
function buildSavedHistoryIndexFileSignature(dir) {
|
|
7404
8521
|
try {
|
|
7405
|
-
const
|
|
7406
|
-
return `index:${
|
|
8522
|
+
const stat2 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
8523
|
+
return `index:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
7407
8524
|
} catch {
|
|
7408
8525
|
return "index:missing";
|
|
7409
8526
|
}
|
|
@@ -7413,8 +8530,8 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
7413
8530
|
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
7414
8531
|
const files = listHistoryFiles(dir);
|
|
7415
8532
|
for (const file of files) {
|
|
7416
|
-
const
|
|
7417
|
-
if (
|
|
8533
|
+
const stat2 = fs3.statSync(path10.join(dir, file));
|
|
8534
|
+
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
7418
8535
|
}
|
|
7419
8536
|
return false;
|
|
7420
8537
|
} catch {
|
|
@@ -7423,14 +8540,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
7423
8540
|
}
|
|
7424
8541
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
7425
8542
|
try {
|
|
7426
|
-
const
|
|
7427
|
-
return `${file}:${
|
|
8543
|
+
const stat2 = fs3.statSync(path10.join(dir, file));
|
|
8544
|
+
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
7428
8545
|
} catch {
|
|
7429
8546
|
return `${file}:missing`;
|
|
7430
8547
|
}
|
|
7431
8548
|
}
|
|
7432
8549
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
7433
|
-
const filePath =
|
|
8550
|
+
const filePath = path10.join(dir, file);
|
|
7434
8551
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
7435
8552
|
const currentEntry = entries.get(file) || null;
|
|
7436
8553
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -7503,7 +8620,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
7503
8620
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
7504
8621
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
7505
8622
|
if (!historySessionId) return null;
|
|
7506
|
-
const filePath =
|
|
8623
|
+
const filePath = path10.join(dir, file);
|
|
7507
8624
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
7508
8625
|
const lines = content.split("\n").filter(Boolean);
|
|
7509
8626
|
let messageCount = 0;
|
|
@@ -7590,7 +8707,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
7590
8707
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
7591
8708
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
7592
8709
|
for (const file of files.slice().sort()) {
|
|
7593
|
-
const filePath =
|
|
8710
|
+
const filePath = path10.join(dir, file);
|
|
7594
8711
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
7595
8712
|
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
7596
8713
|
const persisted = persistedEntries.get(file);
|
|
@@ -7710,12 +8827,12 @@ var ChatHistoryWriter = class {
|
|
|
7710
8827
|
});
|
|
7711
8828
|
}
|
|
7712
8829
|
if (newMessages.length === 0) return;
|
|
7713
|
-
const dir =
|
|
8830
|
+
const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
|
|
7714
8831
|
fs3.mkdirSync(dir, { recursive: true });
|
|
7715
8832
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
7716
8833
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
7717
8834
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
7718
|
-
const filePath =
|
|
8835
|
+
const filePath = path10.join(dir, fileName);
|
|
7719
8836
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
7720
8837
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
7721
8838
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -7806,11 +8923,11 @@ var ChatHistoryWriter = class {
|
|
|
7806
8923
|
const ws = String(workspace || "").trim();
|
|
7807
8924
|
if (!id || !ws) return;
|
|
7808
8925
|
try {
|
|
7809
|
-
const dir =
|
|
8926
|
+
const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
|
|
7810
8927
|
fs3.mkdirSync(dir, { recursive: true });
|
|
7811
8928
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
7812
8929
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
7813
|
-
const filePath =
|
|
8930
|
+
const filePath = path10.join(dir, fileName);
|
|
7814
8931
|
const record = {
|
|
7815
8932
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7816
8933
|
receivedAt: Date.now(),
|
|
@@ -7856,14 +8973,14 @@ var ChatHistoryWriter = class {
|
|
|
7856
8973
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
7857
8974
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
7858
8975
|
}
|
|
7859
|
-
const dir =
|
|
8976
|
+
const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
|
|
7860
8977
|
if (!fs3.existsSync(dir)) return;
|
|
7861
8978
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
7862
8979
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
7863
8980
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
7864
8981
|
for (const file of files) {
|
|
7865
|
-
const sourcePath =
|
|
7866
|
-
const targetPath =
|
|
8982
|
+
const sourcePath = path10.join(dir, file);
|
|
8983
|
+
const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
7867
8984
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
7868
8985
|
const rewritten = sourceLines.map((line) => {
|
|
7869
8986
|
try {
|
|
@@ -7897,13 +9014,13 @@ var ChatHistoryWriter = class {
|
|
|
7897
9014
|
const sessionId = String(historySessionId || "").trim();
|
|
7898
9015
|
if (!sessionId) return;
|
|
7899
9016
|
try {
|
|
7900
|
-
const dir =
|
|
9017
|
+
const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
|
|
7901
9018
|
if (!fs3.existsSync(dir)) return;
|
|
7902
9019
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
7903
9020
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
7904
9021
|
const seen = /* @__PURE__ */ new Set();
|
|
7905
9022
|
for (const file of files) {
|
|
7906
|
-
const filePath =
|
|
9023
|
+
const filePath = path10.join(dir, file);
|
|
7907
9024
|
const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
7908
9025
|
const next = [];
|
|
7909
9026
|
for (const line of lines) {
|
|
@@ -7957,13 +9074,13 @@ var ChatHistoryWriter = class {
|
|
|
7957
9074
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
7958
9075
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
7959
9076
|
for (const dir of agentDirs) {
|
|
7960
|
-
const dirPath =
|
|
9077
|
+
const dirPath = path10.join(HISTORY_DIR, dir.name);
|
|
7961
9078
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
7962
9079
|
let removedAny = false;
|
|
7963
9080
|
for (const file of files) {
|
|
7964
|
-
const filePath =
|
|
7965
|
-
const
|
|
7966
|
-
if (
|
|
9081
|
+
const filePath = path10.join(dirPath, file);
|
|
9082
|
+
const stat2 = fs3.statSync(filePath);
|
|
9083
|
+
if (stat2.mtimeMs < cutoff) {
|
|
7967
9084
|
fs3.unlinkSync(filePath);
|
|
7968
9085
|
removedAny = true;
|
|
7969
9086
|
}
|
|
@@ -8011,13 +9128,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
8011
9128
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
8012
9129
|
try {
|
|
8013
9130
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8014
|
-
const dir =
|
|
9131
|
+
const dir = path10.join(HISTORY_DIR, sanitized);
|
|
8015
9132
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
8016
9133
|
const files = listHistoryFiles(dir, historySessionId);
|
|
8017
9134
|
const allMessages = [];
|
|
8018
9135
|
const seen = /* @__PURE__ */ new Set();
|
|
8019
9136
|
for (const file of files) {
|
|
8020
|
-
const filePath =
|
|
9137
|
+
const filePath = path10.join(dir, file);
|
|
8021
9138
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8022
9139
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
8023
9140
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -8041,7 +9158,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
8041
9158
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
8042
9159
|
try {
|
|
8043
9160
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8044
|
-
const dir =
|
|
9161
|
+
const dir = path10.join(HISTORY_DIR, sanitized);
|
|
8045
9162
|
if (!fs3.existsSync(dir)) {
|
|
8046
9163
|
savedHistorySessionCache.delete(sanitized);
|
|
8047
9164
|
return { sessions: [], hasMore: false };
|
|
@@ -8102,11 +9219,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
8102
9219
|
}
|
|
8103
9220
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
8104
9221
|
try {
|
|
8105
|
-
const dir =
|
|
9222
|
+
const dir = path10.join(HISTORY_DIR, agentType);
|
|
8106
9223
|
if (!fs3.existsSync(dir)) return null;
|
|
8107
9224
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
8108
9225
|
for (const file of files) {
|
|
8109
|
-
const lines = fs3.readFileSync(
|
|
9226
|
+
const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
8110
9227
|
for (const line of lines) {
|
|
8111
9228
|
try {
|
|
8112
9229
|
const parsed = JSON.parse(line);
|
|
@@ -8126,16 +9243,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
8126
9243
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
8127
9244
|
if (records.length === 0) return false;
|
|
8128
9245
|
try {
|
|
8129
|
-
const dir =
|
|
9246
|
+
const dir = path10.join(HISTORY_DIR, agentType);
|
|
8130
9247
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8131
9248
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
8132
9249
|
for (const file of fs3.readdirSync(dir)) {
|
|
8133
9250
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
8134
|
-
fs3.unlinkSync(
|
|
9251
|
+
fs3.unlinkSync(path10.join(dir, file));
|
|
8135
9252
|
}
|
|
8136
9253
|
}
|
|
8137
9254
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
8138
|
-
const filePath =
|
|
9255
|
+
const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
8139
9256
|
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
8140
9257
|
`, "utf-8");
|
|
8141
9258
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -10007,6 +11124,10 @@ function shouldIncludeSessionMetadata(profile) {
|
|
|
10007
11124
|
function shouldIncludeRuntimeMetadata(profile) {
|
|
10008
11125
|
return true;
|
|
10009
11126
|
}
|
|
11127
|
+
function getGitSummaryForWorkspace(workspace, options) {
|
|
11128
|
+
if (!workspace) return void 0;
|
|
11129
|
+
return options.getGitSummaryForWorkspace?.(workspace) || void 0;
|
|
11130
|
+
}
|
|
10010
11131
|
function findCdpManager(cdpManagers, key) {
|
|
10011
11132
|
const exact = cdpManagers.get(key);
|
|
10012
11133
|
if (exact) return exact.isConnected ? exact : null;
|
|
@@ -10062,6 +11183,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
10062
11183
|
const controlValues = normalizeProviderStateControlValues(state.controlValues);
|
|
10063
11184
|
const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
|
|
10064
11185
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
11186
|
+
const workspace = state.workspace || null;
|
|
11187
|
+
const git = getGitSummaryForWorkspace(workspace, options);
|
|
10065
11188
|
const title = activeChat?.title || state.name;
|
|
10066
11189
|
return {
|
|
10067
11190
|
id: state.instanceId || state.type,
|
|
@@ -10074,7 +11197,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
10074
11197
|
activeModal: activeChat?.activeModal || null
|
|
10075
11198
|
}),
|
|
10076
11199
|
title,
|
|
10077
|
-
workspace
|
|
11200
|
+
workspace,
|
|
11201
|
+
...git && { git },
|
|
10078
11202
|
activeChat,
|
|
10079
11203
|
...summaryMetadata && { summaryMetadata },
|
|
10080
11204
|
...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
|
|
@@ -10095,6 +11219,8 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
10095
11219
|
const controlValues = normalizeProviderStateControlValues(ext.controlValues);
|
|
10096
11220
|
const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
|
|
10097
11221
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
11222
|
+
const workspace = parent.workspace || null;
|
|
11223
|
+
const git = getGitSummaryForWorkspace(workspace, options);
|
|
10098
11224
|
return {
|
|
10099
11225
|
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
10100
11226
|
parentId: parent.instanceId || parent.type,
|
|
@@ -10107,7 +11233,8 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
10107
11233
|
activeModal: activeChat?.activeModal || null
|
|
10108
11234
|
}),
|
|
10109
11235
|
title: activeChat?.title || ext.name,
|
|
10110
|
-
workspace
|
|
11236
|
+
workspace,
|
|
11237
|
+
...git && { git },
|
|
10111
11238
|
activeChat,
|
|
10112
11239
|
...summaryMetadata && { summaryMetadata },
|
|
10113
11240
|
...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
|
|
@@ -10143,6 +11270,8 @@ function buildCliSession(state, options) {
|
|
|
10143
11270
|
const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
|
|
10144
11271
|
const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
|
|
10145
11272
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
11273
|
+
const workspace = state.workspace || null;
|
|
11274
|
+
const git = getGitSummaryForWorkspace(workspace, options);
|
|
10146
11275
|
return {
|
|
10147
11276
|
id: state.instanceId,
|
|
10148
11277
|
parentId: null,
|
|
@@ -10155,7 +11284,8 @@ function buildCliSession(state, options) {
|
|
|
10155
11284
|
activeModal: activeChat?.activeModal || null
|
|
10156
11285
|
}),
|
|
10157
11286
|
title: activeChat?.title || state.name,
|
|
10158
|
-
workspace
|
|
11287
|
+
workspace,
|
|
11288
|
+
...git && { git },
|
|
10159
11289
|
...includeRuntimeMetadata && {
|
|
10160
11290
|
runtimeKey: state.runtime?.runtimeKey,
|
|
10161
11291
|
runtimeDisplayName: state.runtime?.displayName,
|
|
@@ -10190,6 +11320,8 @@ function buildAcpSession(state, options) {
|
|
|
10190
11320
|
const controlValues = normalizeProviderStateControlValues(state.controlValues);
|
|
10191
11321
|
const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
|
|
10192
11322
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
11323
|
+
const workspace = state.workspace || null;
|
|
11324
|
+
const git = getGitSummaryForWorkspace(workspace, options);
|
|
10193
11325
|
return {
|
|
10194
11326
|
id: state.instanceId,
|
|
10195
11327
|
parentId: null,
|
|
@@ -10201,7 +11333,8 @@ function buildAcpSession(state, options) {
|
|
|
10201
11333
|
activeModal: activeChat?.activeModal || null
|
|
10202
11334
|
}),
|
|
10203
11335
|
title: activeChat?.title || state.name,
|
|
10204
|
-
workspace
|
|
11336
|
+
workspace,
|
|
11337
|
+
...git && { git },
|
|
10205
11338
|
activeChat,
|
|
10206
11339
|
...summaryMetadata && { summaryMetadata },
|
|
10207
11340
|
...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
|
|
@@ -10321,7 +11454,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
10321
11454
|
init_contracts();
|
|
10322
11455
|
import * as fs4 from "fs";
|
|
10323
11456
|
import * as os6 from "os";
|
|
10324
|
-
import * as
|
|
11457
|
+
import * as path11 from "path";
|
|
10325
11458
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
10326
11459
|
|
|
10327
11460
|
// src/providers/provider-input-support.ts
|
|
@@ -11013,7 +12146,7 @@ function buildDebugBundleText(bundle) {
|
|
|
11013
12146
|
}
|
|
11014
12147
|
function getChatDebugBundleDir() {
|
|
11015
12148
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
11016
|
-
return override ||
|
|
12149
|
+
return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
11017
12150
|
}
|
|
11018
12151
|
function safeBundleIdSegment(value, fallback) {
|
|
11019
12152
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -11046,7 +12179,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
11046
12179
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
11047
12180
|
const dir = getChatDebugBundleDir();
|
|
11048
12181
|
fs4.mkdirSync(dir, { recursive: true });
|
|
11049
|
-
const savedPath =
|
|
12182
|
+
const savedPath = path11.join(dir, `${bundleId}.json`);
|
|
11050
12183
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
11051
12184
|
`;
|
|
11052
12185
|
fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -11240,7 +12373,7 @@ function getCliVisibleTranscriptCount(adapter) {
|
|
|
11240
12373
|
async function getStableExtensionBaseline(h) {
|
|
11241
12374
|
const first = await readExtensionChatState(h);
|
|
11242
12375
|
if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
|
|
11243
|
-
await new Promise((
|
|
12376
|
+
await new Promise((resolve15) => setTimeout(resolve15, 150));
|
|
11244
12377
|
const second = await readExtensionChatState(h);
|
|
11245
12378
|
return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
|
|
11246
12379
|
}
|
|
@@ -11248,7 +12381,7 @@ async function verifyExtensionSendObserved(h, before) {
|
|
|
11248
12381
|
const beforeCount = getStateMessageCount(before);
|
|
11249
12382
|
const beforeSignature = getStateLastSignature(before);
|
|
11250
12383
|
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
11251
|
-
await new Promise((
|
|
12384
|
+
await new Promise((resolve15) => setTimeout(resolve15, 250));
|
|
11252
12385
|
const state = await readExtensionChatState(h);
|
|
11253
12386
|
if (state?.status === "waiting_approval") return true;
|
|
11254
12387
|
const afterCount = getStateMessageCount(state);
|
|
@@ -12184,7 +13317,7 @@ async function handleResolveAction(h, args) {
|
|
|
12184
13317
|
|
|
12185
13318
|
// src/commands/cdp-commands.ts
|
|
12186
13319
|
import * as fs5 from "fs";
|
|
12187
|
-
import * as
|
|
13320
|
+
import * as path12 from "path";
|
|
12188
13321
|
import * as os7 from "os";
|
|
12189
13322
|
var KEY_TO_VK = {
|
|
12190
13323
|
Backspace: 8,
|
|
@@ -12441,25 +13574,25 @@ function resolveSafePath(requestedPath) {
|
|
|
12441
13574
|
const inputPath = rawPath || ".";
|
|
12442
13575
|
const home = os7.homedir();
|
|
12443
13576
|
if (inputPath.startsWith("~")) {
|
|
12444
|
-
return
|
|
13577
|
+
return path12.resolve(path12.join(home, inputPath.slice(1)));
|
|
12445
13578
|
}
|
|
12446
13579
|
if (process.platform === "win32") {
|
|
12447
13580
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
12448
|
-
if (
|
|
12449
|
-
return
|
|
13581
|
+
if (path12.win32.isAbsolute(normalized)) {
|
|
13582
|
+
return path12.win32.normalize(normalized);
|
|
12450
13583
|
}
|
|
12451
|
-
return
|
|
13584
|
+
return path12.win32.resolve(normalized);
|
|
12452
13585
|
}
|
|
12453
|
-
if (
|
|
12454
|
-
return
|
|
13586
|
+
if (path12.isAbsolute(inputPath)) {
|
|
13587
|
+
return path12.normalize(inputPath);
|
|
12455
13588
|
}
|
|
12456
|
-
return
|
|
13589
|
+
return path12.resolve(inputPath);
|
|
12457
13590
|
}
|
|
12458
13591
|
function listDirectoryEntriesSafe(dirPath) {
|
|
12459
13592
|
const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
|
|
12460
13593
|
const files = [];
|
|
12461
13594
|
for (const entry of entries) {
|
|
12462
|
-
const entryPath =
|
|
13595
|
+
const entryPath = path12.join(dirPath, entry.name);
|
|
12463
13596
|
try {
|
|
12464
13597
|
if (entry.isDirectory()) {
|
|
12465
13598
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -12475,11 +13608,11 @@ function listDirectoryEntriesSafe(dirPath) {
|
|
|
12475
13608
|
files.push({ name: entry.name, type: "file", size });
|
|
12476
13609
|
continue;
|
|
12477
13610
|
}
|
|
12478
|
-
const
|
|
13611
|
+
const stat2 = fs5.statSync(entryPath);
|
|
12479
13612
|
files.push({
|
|
12480
13613
|
name: entry.name,
|
|
12481
|
-
type:
|
|
12482
|
-
size:
|
|
13614
|
+
type: stat2.isDirectory() ? "directory" : "file",
|
|
13615
|
+
size: stat2.isFile() ? stat2.size : void 0
|
|
12483
13616
|
});
|
|
12484
13617
|
} catch {
|
|
12485
13618
|
}
|
|
@@ -12513,7 +13646,7 @@ async function handleFileRead(h, args) {
|
|
|
12513
13646
|
async function handleFileWrite(h, args) {
|
|
12514
13647
|
try {
|
|
12515
13648
|
const filePath = resolveSafePath(args?.path);
|
|
12516
|
-
fs5.mkdirSync(
|
|
13649
|
+
fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
|
|
12517
13650
|
fs5.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
12518
13651
|
return { success: true, path: filePath };
|
|
12519
13652
|
} catch (e) {
|
|
@@ -12862,7 +13995,7 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
12862
13995
|
const enterCount = cliCommand.enterCount || 1;
|
|
12863
13996
|
await adapter.writeRaw(cliCommand.text + "\r");
|
|
12864
13997
|
for (let i = 1; i < enterCount; i += 1) {
|
|
12865
|
-
await new Promise((
|
|
13998
|
+
await new Promise((resolve15) => setTimeout(resolve15, 50));
|
|
12866
13999
|
await adapter.writeRaw("\r");
|
|
12867
14000
|
}
|
|
12868
14001
|
}
|
|
@@ -13356,6 +14489,12 @@ var DaemonCommandHandler = class {
|
|
|
13356
14489
|
this._currentRoute = this.resolveRoute(args);
|
|
13357
14490
|
const startedAt = Date.now();
|
|
13358
14491
|
this.logCommandStart(cmd, args);
|
|
14492
|
+
let result;
|
|
14493
|
+
if (isGitCommandName(cmd)) {
|
|
14494
|
+
result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
|
|
14495
|
+
this.logCommandEnd(cmd, result, startedAt);
|
|
14496
|
+
return result;
|
|
14497
|
+
}
|
|
13359
14498
|
const sessionScopedCommands = /* @__PURE__ */ new Set([
|
|
13360
14499
|
"read_chat",
|
|
13361
14500
|
"get_chat_debug_bundle",
|
|
@@ -13381,7 +14520,6 @@ var DaemonCommandHandler = class {
|
|
|
13381
14520
|
this.logCommandEnd(cmd, result2, startedAt);
|
|
13382
14521
|
return result2;
|
|
13383
14522
|
}
|
|
13384
|
-
let result;
|
|
13385
14523
|
if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
|
|
13386
14524
|
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
13387
14525
|
if (cdpCommands.includes(cmd)) {
|
|
@@ -13532,7 +14670,7 @@ var DaemonCommandHandler = class {
|
|
|
13532
14670
|
try {
|
|
13533
14671
|
const http3 = await import("http");
|
|
13534
14672
|
const postData = JSON.stringify(body);
|
|
13535
|
-
const result = await new Promise((
|
|
14673
|
+
const result = await new Promise((resolve15, reject) => {
|
|
13536
14674
|
const req = http3.request({
|
|
13537
14675
|
hostname: "127.0.0.1",
|
|
13538
14676
|
port: 19280,
|
|
@@ -13544,9 +14682,9 @@ var DaemonCommandHandler = class {
|
|
|
13544
14682
|
res.on("data", (chunk) => data += chunk);
|
|
13545
14683
|
res.on("end", () => {
|
|
13546
14684
|
try {
|
|
13547
|
-
|
|
14685
|
+
resolve15(JSON.parse(data));
|
|
13548
14686
|
} catch {
|
|
13549
|
-
|
|
14687
|
+
resolve15({ raw: data });
|
|
13550
14688
|
}
|
|
13551
14689
|
});
|
|
13552
14690
|
});
|
|
@@ -13564,15 +14702,15 @@ var DaemonCommandHandler = class {
|
|
|
13564
14702
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
13565
14703
|
try {
|
|
13566
14704
|
const http3 = await import("http");
|
|
13567
|
-
const result = await new Promise((
|
|
14705
|
+
const result = await new Promise((resolve15, reject) => {
|
|
13568
14706
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
13569
14707
|
let data = "";
|
|
13570
14708
|
res.on("data", (chunk) => data += chunk);
|
|
13571
14709
|
res.on("end", () => {
|
|
13572
14710
|
try {
|
|
13573
|
-
|
|
14711
|
+
resolve15(JSON.parse(data));
|
|
13574
14712
|
} catch {
|
|
13575
|
-
|
|
14713
|
+
resolve15({ raw: data });
|
|
13576
14714
|
}
|
|
13577
14715
|
});
|
|
13578
14716
|
}).on("error", reject);
|
|
@@ -13586,7 +14724,7 @@ var DaemonCommandHandler = class {
|
|
|
13586
14724
|
try {
|
|
13587
14725
|
const http3 = await import("http");
|
|
13588
14726
|
const postData = JSON.stringify(args || {});
|
|
13589
|
-
const result = await new Promise((
|
|
14727
|
+
const result = await new Promise((resolve15, reject) => {
|
|
13590
14728
|
const req = http3.request({
|
|
13591
14729
|
hostname: "127.0.0.1",
|
|
13592
14730
|
port: 19280,
|
|
@@ -13598,9 +14736,9 @@ var DaemonCommandHandler = class {
|
|
|
13598
14736
|
res.on("data", (chunk) => data += chunk);
|
|
13599
14737
|
res.on("end", () => {
|
|
13600
14738
|
try {
|
|
13601
|
-
|
|
14739
|
+
resolve15(JSON.parse(data));
|
|
13602
14740
|
} catch {
|
|
13603
|
-
|
|
14741
|
+
resolve15({ raw: data });
|
|
13604
14742
|
}
|
|
13605
14743
|
});
|
|
13606
14744
|
});
|
|
@@ -13618,7 +14756,7 @@ var DaemonCommandHandler = class {
|
|
|
13618
14756
|
// src/commands/cli-manager.ts
|
|
13619
14757
|
init_provider_cli_adapter();
|
|
13620
14758
|
import * as os13 from "os";
|
|
13621
|
-
import * as
|
|
14759
|
+
import * as path16 from "path";
|
|
13622
14760
|
import * as crypto4 from "crypto";
|
|
13623
14761
|
import { existsSync as existsSync10 } from "fs";
|
|
13624
14762
|
import { execFileSync } from "child_process";
|
|
@@ -13628,7 +14766,7 @@ init_config();
|
|
|
13628
14766
|
// src/providers/cli-provider-instance.ts
|
|
13629
14767
|
init_contracts();
|
|
13630
14768
|
import * as os12 from "os";
|
|
13631
|
-
import * as
|
|
14769
|
+
import * as path15 from "path";
|
|
13632
14770
|
import * as crypto3 from "crypto";
|
|
13633
14771
|
import * as fs6 from "fs";
|
|
13634
14772
|
import { createRequire } from "module";
|
|
@@ -13688,7 +14826,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
|
|
|
13688
14826
|
var CachedDatabaseSync = null;
|
|
13689
14827
|
function getDatabaseSync() {
|
|
13690
14828
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
13691
|
-
const requireFn = typeof __require === "function" ? __require : createRequire(
|
|
14829
|
+
const requireFn = typeof __require === "function" ? __require : createRequire(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
13692
14830
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
13693
14831
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
13694
14832
|
if (!CachedDatabaseSync) {
|
|
@@ -13726,7 +14864,7 @@ async function waitForCliAdapterReady(adapter, options) {
|
|
|
13726
14864
|
if (status === "stopped") {
|
|
13727
14865
|
throw new Error("CLI runtime stopped before it became ready");
|
|
13728
14866
|
}
|
|
13729
|
-
await new Promise((
|
|
14867
|
+
await new Promise((resolve15) => setTimeout(resolve15, pollMs));
|
|
13730
14868
|
}
|
|
13731
14869
|
throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
|
|
13732
14870
|
}
|
|
@@ -14077,7 +15215,7 @@ var CliProviderInstance = class {
|
|
|
14077
15215
|
const enterCount = cliCommand.enterCount || 1;
|
|
14078
15216
|
await this.adapter.writeRaw(cliCommand.text + "\r");
|
|
14079
15217
|
for (let i = 1; i < enterCount; i += 1) {
|
|
14080
|
-
await new Promise((
|
|
15218
|
+
await new Promise((resolve15) => setTimeout(resolve15, 50));
|
|
14081
15219
|
await this.adapter.writeRaw("\r");
|
|
14082
15220
|
}
|
|
14083
15221
|
}
|
|
@@ -15196,13 +16334,13 @@ var AcpProviderInstance = class {
|
|
|
15196
16334
|
}
|
|
15197
16335
|
this.currentStatus = "waiting_approval";
|
|
15198
16336
|
this.detectStatusTransition();
|
|
15199
|
-
const approved = await new Promise((
|
|
15200
|
-
this.permissionResolvers.push(
|
|
16337
|
+
const approved = await new Promise((resolve15) => {
|
|
16338
|
+
this.permissionResolvers.push(resolve15);
|
|
15201
16339
|
setTimeout(() => {
|
|
15202
|
-
const idx = this.permissionResolvers.indexOf(
|
|
16340
|
+
const idx = this.permissionResolvers.indexOf(resolve15);
|
|
15203
16341
|
if (idx >= 0) {
|
|
15204
16342
|
this.permissionResolvers.splice(idx, 1);
|
|
15205
|
-
|
|
16343
|
+
resolve15(false);
|
|
15206
16344
|
}
|
|
15207
16345
|
}, 3e5);
|
|
15208
16346
|
});
|
|
@@ -15777,11 +16915,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
|
|
|
15777
16915
|
// src/commands/cli-manager.ts
|
|
15778
16916
|
function isExplicitCommand(command) {
|
|
15779
16917
|
const trimmed = command.trim();
|
|
15780
|
-
return
|
|
16918
|
+
return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
15781
16919
|
}
|
|
15782
16920
|
function expandExecutable(command) {
|
|
15783
16921
|
const trimmed = command.trim();
|
|
15784
|
-
return trimmed.startsWith("~") ?
|
|
16922
|
+
return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
|
|
15785
16923
|
}
|
|
15786
16924
|
function commandExists(command) {
|
|
15787
16925
|
const trimmed = command.trim();
|
|
@@ -16062,7 +17200,7 @@ var DaemonCliManager = class {
|
|
|
16062
17200
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
16063
17201
|
const trimmed = (workingDir || "").trim();
|
|
16064
17202
|
if (!trimmed) throw new Error("working directory required");
|
|
16065
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
17203
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
|
|
16066
17204
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
16067
17205
|
const rawProvider = this.providerLoader.getByAlias(cliType);
|
|
16068
17206
|
const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
|
|
@@ -16563,11 +17701,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
16563
17701
|
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
16564
17702
|
import * as net from "net";
|
|
16565
17703
|
import * as os15 from "os";
|
|
16566
|
-
import * as
|
|
17704
|
+
import * as path18 from "path";
|
|
16567
17705
|
|
|
16568
17706
|
// src/providers/provider-loader.ts
|
|
16569
17707
|
import * as fs7 from "fs";
|
|
16570
|
-
import * as
|
|
17708
|
+
import * as path17 from "path";
|
|
16571
17709
|
import * as os14 from "os";
|
|
16572
17710
|
import * as chokidar from "chokidar";
|
|
16573
17711
|
init_logger();
|
|
@@ -16832,7 +17970,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16832
17970
|
try {
|
|
16833
17971
|
if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
|
|
16834
17972
|
return ["ide", "extension", "cli", "acp"].some(
|
|
16835
|
-
(category) => fs7.existsSync(
|
|
17973
|
+
(category) => fs7.existsSync(path17.join(candidate, category))
|
|
16836
17974
|
);
|
|
16837
17975
|
} catch {
|
|
16838
17976
|
return false;
|
|
@@ -16840,20 +17978,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16840
17978
|
}
|
|
16841
17979
|
static hasProviderRootMarker(candidate) {
|
|
16842
17980
|
try {
|
|
16843
|
-
return fs7.existsSync(
|
|
17981
|
+
return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
16844
17982
|
} catch {
|
|
16845
17983
|
return false;
|
|
16846
17984
|
}
|
|
16847
17985
|
}
|
|
16848
17986
|
detectDefaultUserDir() {
|
|
16849
|
-
const fallback =
|
|
17987
|
+
const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
|
|
16850
17988
|
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
16851
17989
|
const visited = /* @__PURE__ */ new Set();
|
|
16852
17990
|
for (const start of this.probeStarts) {
|
|
16853
|
-
let current =
|
|
17991
|
+
let current = path17.resolve(start);
|
|
16854
17992
|
while (!visited.has(current)) {
|
|
16855
17993
|
visited.add(current);
|
|
16856
|
-
const siblingCandidate =
|
|
17994
|
+
const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
16857
17995
|
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
16858
17996
|
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
16859
17997
|
if (envOptIn || hasMarker) {
|
|
@@ -16875,7 +18013,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16875
18013
|
return { path: siblingCandidate, source };
|
|
16876
18014
|
}
|
|
16877
18015
|
}
|
|
16878
|
-
const parent =
|
|
18016
|
+
const parent = path17.dirname(current);
|
|
16879
18017
|
if (parent === current) break;
|
|
16880
18018
|
current = parent;
|
|
16881
18019
|
}
|
|
@@ -16885,11 +18023,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16885
18023
|
constructor(options) {
|
|
16886
18024
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
16887
18025
|
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
16888
|
-
this.defaultProvidersDir =
|
|
18026
|
+
this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
|
|
16889
18027
|
const detected = this.detectDefaultUserDir();
|
|
16890
18028
|
this.userDir = detected.path;
|
|
16891
18029
|
this.userDirSource = detected.source;
|
|
16892
|
-
this.upstreamDir =
|
|
18030
|
+
this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
|
|
16893
18031
|
this.disableUpstream = false;
|
|
16894
18032
|
this.applySourceConfig({
|
|
16895
18033
|
userDir: options?.userDir,
|
|
@@ -16948,7 +18086,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16948
18086
|
this.userDir = detected.path;
|
|
16949
18087
|
this.userDirSource = detected.source;
|
|
16950
18088
|
}
|
|
16951
|
-
this.upstreamDir =
|
|
18089
|
+
this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
|
|
16952
18090
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
16953
18091
|
if (this.explicitProviderDir) {
|
|
16954
18092
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -16962,7 +18100,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16962
18100
|
* Canonical provider directory shape for a given root.
|
|
16963
18101
|
*/
|
|
16964
18102
|
getProviderDir(root, category, type) {
|
|
16965
|
-
return
|
|
18103
|
+
return path17.join(root, category, type);
|
|
16966
18104
|
}
|
|
16967
18105
|
/**
|
|
16968
18106
|
* Canonical user override directory for a provider.
|
|
@@ -16989,7 +18127,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
16989
18127
|
resolveProviderFile(type, ...segments) {
|
|
16990
18128
|
const dir = this.findProviderDirInternal(type);
|
|
16991
18129
|
if (!dir) return null;
|
|
16992
|
-
return
|
|
18130
|
+
return path17.join(dir, ...segments);
|
|
16993
18131
|
}
|
|
16994
18132
|
/**
|
|
16995
18133
|
* Load all providers (3-tier priority)
|
|
@@ -17028,7 +18166,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17028
18166
|
if (!fs7.existsSync(this.upstreamDir)) return false;
|
|
17029
18167
|
try {
|
|
17030
18168
|
return fs7.readdirSync(this.upstreamDir).some(
|
|
17031
|
-
(d) => fs7.statSync(
|
|
18169
|
+
(d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
|
|
17032
18170
|
);
|
|
17033
18171
|
} catch {
|
|
17034
18172
|
return false;
|
|
@@ -17525,8 +18663,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17525
18663
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
17526
18664
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
17527
18665
|
if (providerDir) {
|
|
17528
|
-
const fullDir =
|
|
17529
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18666
|
+
const fullDir = path17.join(providerDir, entry.scriptDir);
|
|
18667
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
|
|
17530
18668
|
}
|
|
17531
18669
|
matched = true;
|
|
17532
18670
|
}
|
|
@@ -17541,8 +18679,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17541
18679
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
17542
18680
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
17543
18681
|
if (providerDir) {
|
|
17544
|
-
const fullDir =
|
|
17545
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18682
|
+
const fullDir = path17.join(providerDir, base.defaultScriptDir);
|
|
18683
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
|
|
17546
18684
|
}
|
|
17547
18685
|
}
|
|
17548
18686
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -17559,8 +18697,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17559
18697
|
resolved._resolvedScriptDir = dirOverride;
|
|
17560
18698
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
17561
18699
|
if (providerDir) {
|
|
17562
|
-
const fullDir =
|
|
17563
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18700
|
+
const fullDir = path17.join(providerDir, dirOverride);
|
|
18701
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
|
|
17564
18702
|
}
|
|
17565
18703
|
}
|
|
17566
18704
|
} else if (override.scripts) {
|
|
@@ -17576,8 +18714,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17576
18714
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
17577
18715
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
17578
18716
|
if (providerDir) {
|
|
17579
|
-
const fullDir =
|
|
17580
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18717
|
+
const fullDir = path17.join(providerDir, base.defaultScriptDir);
|
|
18718
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
|
|
17581
18719
|
}
|
|
17582
18720
|
}
|
|
17583
18721
|
}
|
|
@@ -17609,14 +18747,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17609
18747
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
17610
18748
|
return null;
|
|
17611
18749
|
}
|
|
17612
|
-
const dir =
|
|
18750
|
+
const dir = path17.join(providerDir, scriptDir);
|
|
17613
18751
|
if (!fs7.existsSync(dir)) {
|
|
17614
18752
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
17615
18753
|
return null;
|
|
17616
18754
|
}
|
|
17617
18755
|
const cached = this.scriptsCache.get(dir);
|
|
17618
18756
|
if (cached) return cached;
|
|
17619
|
-
const scriptsJs =
|
|
18757
|
+
const scriptsJs = path17.join(dir, "scripts.js");
|
|
17620
18758
|
if (fs7.existsSync(scriptsJs)) {
|
|
17621
18759
|
try {
|
|
17622
18760
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -17658,7 +18796,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17658
18796
|
return;
|
|
17659
18797
|
}
|
|
17660
18798
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
17661
|
-
this.log(`File changed: ${
|
|
18799
|
+
this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
|
|
17662
18800
|
this.reload();
|
|
17663
18801
|
}
|
|
17664
18802
|
};
|
|
@@ -17713,7 +18851,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17713
18851
|
}
|
|
17714
18852
|
const https = __require("https");
|
|
17715
18853
|
const { execSync: execSync7 } = __require("child_process");
|
|
17716
|
-
const metaPath =
|
|
18854
|
+
const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
17717
18855
|
let prevEtag = "";
|
|
17718
18856
|
let prevTimestamp = 0;
|
|
17719
18857
|
try {
|
|
@@ -17730,7 +18868,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17730
18868
|
return { updated: false };
|
|
17731
18869
|
}
|
|
17732
18870
|
try {
|
|
17733
|
-
const etag = await new Promise((
|
|
18871
|
+
const etag = await new Promise((resolve15, reject) => {
|
|
17734
18872
|
const options = {
|
|
17735
18873
|
method: "HEAD",
|
|
17736
18874
|
hostname: "github.com",
|
|
@@ -17748,7 +18886,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17748
18886
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
17749
18887
|
timeout: 1e4
|
|
17750
18888
|
}, (res2) => {
|
|
17751
|
-
|
|
18889
|
+
resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
17752
18890
|
});
|
|
17753
18891
|
req2.on("error", reject);
|
|
17754
18892
|
req2.on("timeout", () => {
|
|
@@ -17757,7 +18895,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17757
18895
|
});
|
|
17758
18896
|
req2.end();
|
|
17759
18897
|
} else {
|
|
17760
|
-
|
|
18898
|
+
resolve15(res.headers.etag || res.headers["last-modified"] || "");
|
|
17761
18899
|
}
|
|
17762
18900
|
});
|
|
17763
18901
|
req.on("error", reject);
|
|
@@ -17773,17 +18911,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17773
18911
|
return { updated: false };
|
|
17774
18912
|
}
|
|
17775
18913
|
this.log("Downloading latest providers from GitHub...");
|
|
17776
|
-
const tmpTar =
|
|
17777
|
-
const tmpExtract =
|
|
18914
|
+
const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
18915
|
+
const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
17778
18916
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
17779
18917
|
fs7.mkdirSync(tmpExtract, { recursive: true });
|
|
17780
18918
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
17781
18919
|
const extracted = fs7.readdirSync(tmpExtract);
|
|
17782
18920
|
const rootDir = extracted.find(
|
|
17783
|
-
(d) => fs7.statSync(
|
|
18921
|
+
(d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
17784
18922
|
);
|
|
17785
18923
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
17786
|
-
const sourceDir =
|
|
18924
|
+
const sourceDir = path17.join(tmpExtract, rootDir);
|
|
17787
18925
|
const backupDir = this.upstreamDir + ".bak";
|
|
17788
18926
|
if (fs7.existsSync(this.upstreamDir)) {
|
|
17789
18927
|
if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -17821,7 +18959,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17821
18959
|
downloadFile(url, destPath) {
|
|
17822
18960
|
const https = __require("https");
|
|
17823
18961
|
const http3 = __require("http");
|
|
17824
|
-
return new Promise((
|
|
18962
|
+
return new Promise((resolve15, reject) => {
|
|
17825
18963
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
17826
18964
|
if (redirectCount > 5) {
|
|
17827
18965
|
reject(new Error("Too many redirects"));
|
|
@@ -17841,7 +18979,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17841
18979
|
res.pipe(ws);
|
|
17842
18980
|
ws.on("finish", () => {
|
|
17843
18981
|
ws.close();
|
|
17844
|
-
|
|
18982
|
+
resolve15();
|
|
17845
18983
|
});
|
|
17846
18984
|
ws.on("error", reject);
|
|
17847
18985
|
});
|
|
@@ -17858,8 +18996,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17858
18996
|
copyDirRecursive(src, dest) {
|
|
17859
18997
|
fs7.mkdirSync(dest, { recursive: true });
|
|
17860
18998
|
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
17861
|
-
const srcPath =
|
|
17862
|
-
const destPath =
|
|
18999
|
+
const srcPath = path17.join(src, entry.name);
|
|
19000
|
+
const destPath = path17.join(dest, entry.name);
|
|
17863
19001
|
if (entry.isDirectory()) {
|
|
17864
19002
|
this.copyDirRecursive(srcPath, destPath);
|
|
17865
19003
|
} else {
|
|
@@ -17870,7 +19008,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17870
19008
|
/** .meta.json save */
|
|
17871
19009
|
writeMeta(metaPath, etag, timestamp) {
|
|
17872
19010
|
try {
|
|
17873
|
-
fs7.mkdirSync(
|
|
19011
|
+
fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
|
|
17874
19012
|
fs7.writeFileSync(metaPath, JSON.stringify({
|
|
17875
19013
|
etag,
|
|
17876
19014
|
timestamp,
|
|
@@ -17887,7 +19025,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17887
19025
|
const scan = (d) => {
|
|
17888
19026
|
try {
|
|
17889
19027
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
17890
|
-
if (entry.isDirectory()) scan(
|
|
19028
|
+
if (entry.isDirectory()) scan(path17.join(d, entry.name));
|
|
17891
19029
|
else if (entry.name === "provider.json") count++;
|
|
17892
19030
|
}
|
|
17893
19031
|
} catch {
|
|
@@ -18115,17 +19253,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18115
19253
|
for (const root of searchRoots) {
|
|
18116
19254
|
if (!fs7.existsSync(root)) continue;
|
|
18117
19255
|
const candidate = this.getProviderDir(root, cat, type);
|
|
18118
|
-
if (fs7.existsSync(
|
|
18119
|
-
const catDir =
|
|
19256
|
+
if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
|
|
19257
|
+
const catDir = path17.join(root, cat);
|
|
18120
19258
|
if (fs7.existsSync(catDir)) {
|
|
18121
19259
|
try {
|
|
18122
19260
|
for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
|
|
18123
19261
|
if (!entry.isDirectory()) continue;
|
|
18124
|
-
const jsonPath =
|
|
19262
|
+
const jsonPath = path17.join(catDir, entry.name, "provider.json");
|
|
18125
19263
|
if (fs7.existsSync(jsonPath)) {
|
|
18126
19264
|
try {
|
|
18127
19265
|
const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
|
|
18128
|
-
if (data.type === type) return
|
|
19266
|
+
if (data.type === type) return path17.join(catDir, entry.name);
|
|
18129
19267
|
} catch {
|
|
18130
19268
|
}
|
|
18131
19269
|
}
|
|
@@ -18142,7 +19280,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18142
19280
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
18143
19281
|
*/
|
|
18144
19282
|
buildScriptWrappersFromDir(dir) {
|
|
18145
|
-
const scriptsJs =
|
|
19283
|
+
const scriptsJs = path17.join(dir, "scripts.js");
|
|
18146
19284
|
if (fs7.existsSync(scriptsJs)) {
|
|
18147
19285
|
try {
|
|
18148
19286
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -18156,7 +19294,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18156
19294
|
for (const file of fs7.readdirSync(dir)) {
|
|
18157
19295
|
if (!file.endsWith(".js")) continue;
|
|
18158
19296
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
18159
|
-
const filePath =
|
|
19297
|
+
const filePath = path17.join(dir, file);
|
|
18160
19298
|
result[scriptName] = (...args) => {
|
|
18161
19299
|
try {
|
|
18162
19300
|
let content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -18216,7 +19354,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18216
19354
|
}
|
|
18217
19355
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
18218
19356
|
if (hasJson) {
|
|
18219
|
-
const jsonPath =
|
|
19357
|
+
const jsonPath = path17.join(d, "provider.json");
|
|
18220
19358
|
try {
|
|
18221
19359
|
const raw = fs7.readFileSync(jsonPath, "utf-8");
|
|
18222
19360
|
const mod = JSON.parse(raw);
|
|
@@ -18237,7 +19375,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18237
19375
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
18238
19376
|
} else {
|
|
18239
19377
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
18240
|
-
const scriptsPath =
|
|
19378
|
+
const scriptsPath = path17.join(d, "scripts.js");
|
|
18241
19379
|
if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
|
|
18242
19380
|
try {
|
|
18243
19381
|
delete __require.cache[__require.resolve(scriptsPath)];
|
|
@@ -18263,7 +19401,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18263
19401
|
if (!entry.isDirectory()) continue;
|
|
18264
19402
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
18265
19403
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
18266
|
-
scan(
|
|
19404
|
+
scan(path17.join(d, entry.name));
|
|
18267
19405
|
}
|
|
18268
19406
|
}
|
|
18269
19407
|
};
|
|
@@ -18298,9 +19436,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18298
19436
|
}
|
|
18299
19437
|
}
|
|
18300
19438
|
compareVersions(a, b) {
|
|
18301
|
-
const
|
|
18302
|
-
const pa =
|
|
18303
|
-
const pb =
|
|
19439
|
+
const normalize4 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
|
|
19440
|
+
const pa = normalize4(a);
|
|
19441
|
+
const pb = normalize4(b);
|
|
18304
19442
|
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
18305
19443
|
const va = pa[i] || 0;
|
|
18306
19444
|
const vb = pb[i] || 0;
|
|
@@ -18420,17 +19558,17 @@ async function findFreePort(ports) {
|
|
|
18420
19558
|
throw new Error("No free port found");
|
|
18421
19559
|
}
|
|
18422
19560
|
function checkPortFree(port) {
|
|
18423
|
-
return new Promise((
|
|
19561
|
+
return new Promise((resolve15) => {
|
|
18424
19562
|
const server = net.createServer();
|
|
18425
19563
|
server.unref();
|
|
18426
|
-
server.on("error", () =>
|
|
19564
|
+
server.on("error", () => resolve15(false));
|
|
18427
19565
|
server.listen(port, "127.0.0.1", () => {
|
|
18428
|
-
server.close(() =>
|
|
19566
|
+
server.close(() => resolve15(true));
|
|
18429
19567
|
});
|
|
18430
19568
|
});
|
|
18431
19569
|
}
|
|
18432
19570
|
async function isCdpActive(port) {
|
|
18433
|
-
return new Promise((
|
|
19571
|
+
return new Promise((resolve15) => {
|
|
18434
19572
|
const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
18435
19573
|
timeout: 2e3
|
|
18436
19574
|
}, (res) => {
|
|
@@ -18439,16 +19577,16 @@ async function isCdpActive(port) {
|
|
|
18439
19577
|
res.on("end", () => {
|
|
18440
19578
|
try {
|
|
18441
19579
|
const info = JSON.parse(data);
|
|
18442
|
-
|
|
19580
|
+
resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
18443
19581
|
} catch {
|
|
18444
|
-
|
|
19582
|
+
resolve15(false);
|
|
18445
19583
|
}
|
|
18446
19584
|
});
|
|
18447
19585
|
});
|
|
18448
|
-
req.on("error", () =>
|
|
19586
|
+
req.on("error", () => resolve15(false));
|
|
18449
19587
|
req.on("timeout", () => {
|
|
18450
19588
|
req.destroy();
|
|
18451
|
-
|
|
19589
|
+
resolve15(false);
|
|
18452
19590
|
});
|
|
18453
19591
|
});
|
|
18454
19592
|
}
|
|
@@ -18588,8 +19726,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
18588
19726
|
const appNameMap = getMacAppIdentifiers();
|
|
18589
19727
|
const appName = appNameMap[ideId];
|
|
18590
19728
|
if (appName) {
|
|
18591
|
-
const storagePath =
|
|
18592
|
-
process.env.APPDATA ||
|
|
19729
|
+
const storagePath = path18.join(
|
|
19730
|
+
process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
|
|
18593
19731
|
appName,
|
|
18594
19732
|
"storage.json"
|
|
18595
19733
|
);
|
|
@@ -18767,9 +19905,9 @@ init_logger();
|
|
|
18767
19905
|
|
|
18768
19906
|
// src/logging/command-log.ts
|
|
18769
19907
|
import * as fs8 from "fs";
|
|
18770
|
-
import * as
|
|
19908
|
+
import * as path19 from "path";
|
|
18771
19909
|
import * as os16 from "os";
|
|
18772
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
19910
|
+
var LOG_DIR2 = process.platform === "win32" ? path19.join(process.env.LOCALAPPDATA || process.env.APPDATA || path19.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path19.join(os16.homedir(), "Library", "Logs", "adhdev") : path19.join(os16.homedir(), ".local", "share", "adhdev", "logs");
|
|
18773
19911
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
18774
19912
|
var MAX_DAYS = 7;
|
|
18775
19913
|
try {
|
|
@@ -18807,13 +19945,13 @@ function getDateStr2() {
|
|
|
18807
19945
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
18808
19946
|
}
|
|
18809
19947
|
var currentDate2 = getDateStr2();
|
|
18810
|
-
var currentFile =
|
|
19948
|
+
var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
18811
19949
|
var writeCount2 = 0;
|
|
18812
19950
|
function checkRotation() {
|
|
18813
19951
|
const today = getDateStr2();
|
|
18814
19952
|
if (today !== currentDate2) {
|
|
18815
19953
|
currentDate2 = today;
|
|
18816
|
-
currentFile =
|
|
19954
|
+
currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
18817
19955
|
cleanOldFiles();
|
|
18818
19956
|
}
|
|
18819
19957
|
}
|
|
@@ -18827,7 +19965,7 @@ function cleanOldFiles() {
|
|
|
18827
19965
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
18828
19966
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
18829
19967
|
try {
|
|
18830
|
-
fs8.unlinkSync(
|
|
19968
|
+
fs8.unlinkSync(path19.join(LOG_DIR2, file));
|
|
18831
19969
|
} catch {
|
|
18832
19970
|
}
|
|
18833
19971
|
}
|
|
@@ -18837,8 +19975,8 @@ function cleanOldFiles() {
|
|
|
18837
19975
|
}
|
|
18838
19976
|
function checkSize() {
|
|
18839
19977
|
try {
|
|
18840
|
-
const
|
|
18841
|
-
if (
|
|
19978
|
+
const stat2 = fs8.statSync(currentFile);
|
|
19979
|
+
if (stat2.size > MAX_FILE_SIZE) {
|
|
18842
19980
|
const backup = currentFile.replace(".jsonl", ".1.jsonl");
|
|
18843
19981
|
try {
|
|
18844
19982
|
fs8.unlinkSync(backup);
|
|
@@ -19124,12 +20262,18 @@ function buildStatusSnapshot(options) {
|
|
|
19124
20262
|
const unreadSourceSessions = buildSessionEntries(
|
|
19125
20263
|
options.allStates,
|
|
19126
20264
|
options.cdpManagers,
|
|
19127
|
-
{
|
|
20265
|
+
{
|
|
20266
|
+
profile: "full",
|
|
20267
|
+
getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
|
|
20268
|
+
}
|
|
19128
20269
|
);
|
|
19129
20270
|
const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
|
|
19130
20271
|
options.allStates,
|
|
19131
20272
|
options.cdpManagers,
|
|
19132
|
-
{
|
|
20273
|
+
{
|
|
20274
|
+
profile,
|
|
20275
|
+
getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
|
|
20276
|
+
}
|
|
19133
20277
|
);
|
|
19134
20278
|
const sessionsById = new Map(sessions.map((session) => [session.id, session]));
|
|
19135
20279
|
for (const sourceSession of unreadSourceSessions) {
|
|
@@ -19223,13 +20367,13 @@ import { execFileSync as execFileSync2 } from "child_process";
|
|
|
19223
20367
|
import { spawn as spawn3 } from "child_process";
|
|
19224
20368
|
import * as fs9 from "fs";
|
|
19225
20369
|
import * as os18 from "os";
|
|
19226
|
-
import * as
|
|
20370
|
+
import * as path20 from "path";
|
|
19227
20371
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
19228
20372
|
function getUpgradeLogPath() {
|
|
19229
20373
|
const home = os18.homedir();
|
|
19230
|
-
const dir =
|
|
20374
|
+
const dir = path20.join(home, ".adhdev");
|
|
19231
20375
|
fs9.mkdirSync(dir, { recursive: true });
|
|
19232
|
-
return
|
|
20376
|
+
return path20.join(dir, "daemon-upgrade.log");
|
|
19233
20377
|
}
|
|
19234
20378
|
function appendUpgradeLog(message) {
|
|
19235
20379
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -19240,14 +20384,14 @@ function appendUpgradeLog(message) {
|
|
|
19240
20384
|
}
|
|
19241
20385
|
}
|
|
19242
20386
|
function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
|
|
19243
|
-
const binDir =
|
|
20387
|
+
const binDir = path20.dirname(nodeExecutable);
|
|
19244
20388
|
if (platform10 === "win32") {
|
|
19245
|
-
const npmCliPath =
|
|
20389
|
+
const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
19246
20390
|
if (fs9.existsSync(npmCliPath)) {
|
|
19247
20391
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
19248
20392
|
}
|
|
19249
20393
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
19250
|
-
const candidatePath =
|
|
20394
|
+
const candidatePath = path20.join(binDir, candidate);
|
|
19251
20395
|
if (fs9.existsSync(candidatePath)) {
|
|
19252
20396
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
19253
20397
|
}
|
|
@@ -19255,7 +20399,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
19255
20399
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
19256
20400
|
}
|
|
19257
20401
|
for (const candidate of ["npm"]) {
|
|
19258
|
-
const candidatePath =
|
|
20402
|
+
const candidatePath = path20.join(binDir, candidate);
|
|
19259
20403
|
if (fs9.existsSync(candidatePath)) {
|
|
19260
20404
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
19261
20405
|
}
|
|
@@ -19272,13 +20416,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
19272
20416
|
let currentDir = resolvedPath;
|
|
19273
20417
|
try {
|
|
19274
20418
|
if (fs9.statSync(resolvedPath).isFile()) {
|
|
19275
|
-
currentDir =
|
|
20419
|
+
currentDir = path20.dirname(resolvedPath);
|
|
19276
20420
|
}
|
|
19277
20421
|
} catch {
|
|
19278
|
-
currentDir =
|
|
20422
|
+
currentDir = path20.dirname(resolvedPath);
|
|
19279
20423
|
}
|
|
19280
20424
|
while (true) {
|
|
19281
|
-
const packageJsonPath =
|
|
20425
|
+
const packageJsonPath = path20.join(currentDir, "package.json");
|
|
19282
20426
|
try {
|
|
19283
20427
|
if (fs9.existsSync(packageJsonPath)) {
|
|
19284
20428
|
const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -19289,7 +20433,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
19289
20433
|
}
|
|
19290
20434
|
} catch {
|
|
19291
20435
|
}
|
|
19292
|
-
const parentDir =
|
|
20436
|
+
const parentDir = path20.dirname(currentDir);
|
|
19293
20437
|
if (parentDir === currentDir) {
|
|
19294
20438
|
return null;
|
|
19295
20439
|
}
|
|
@@ -19297,13 +20441,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
19297
20441
|
}
|
|
19298
20442
|
}
|
|
19299
20443
|
function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
|
|
19300
|
-
const nodeModulesDir = packageName.startsWith("@") ?
|
|
19301
|
-
if (
|
|
20444
|
+
const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
|
|
20445
|
+
if (path20.basename(nodeModulesDir) !== "node_modules") {
|
|
19302
20446
|
return null;
|
|
19303
20447
|
}
|
|
19304
|
-
const maybeLibDir =
|
|
19305
|
-
if (
|
|
19306
|
-
return
|
|
20448
|
+
const maybeLibDir = path20.dirname(nodeModulesDir);
|
|
20449
|
+
if (path20.basename(maybeLibDir) === "lib") {
|
|
20450
|
+
return path20.dirname(maybeLibDir);
|
|
19307
20451
|
}
|
|
19308
20452
|
return maybeLibDir;
|
|
19309
20453
|
}
|
|
@@ -19411,14 +20555,14 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
19411
20555
|
while (Date.now() - start < timeoutMs) {
|
|
19412
20556
|
try {
|
|
19413
20557
|
process.kill(pid, 0);
|
|
19414
|
-
await new Promise((
|
|
20558
|
+
await new Promise((resolve15) => setTimeout(resolve15, 250));
|
|
19415
20559
|
} catch {
|
|
19416
20560
|
return;
|
|
19417
20561
|
}
|
|
19418
20562
|
}
|
|
19419
20563
|
}
|
|
19420
20564
|
function stopSessionHostProcesses(appName) {
|
|
19421
|
-
const pidFile =
|
|
20565
|
+
const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
19422
20566
|
try {
|
|
19423
20567
|
if (fs9.existsSync(pidFile)) {
|
|
19424
20568
|
const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -19435,7 +20579,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
19435
20579
|
}
|
|
19436
20580
|
}
|
|
19437
20581
|
function removeDaemonPidFile() {
|
|
19438
|
-
const pidFile =
|
|
20582
|
+
const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
|
|
19439
20583
|
try {
|
|
19440
20584
|
fs9.unlinkSync(pidFile);
|
|
19441
20585
|
} catch {
|
|
@@ -19446,7 +20590,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
19446
20590
|
const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
19447
20591
|
if (!npmRoot) return;
|
|
19448
20592
|
const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
19449
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
20593
|
+
const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
|
|
19450
20594
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
19451
20595
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
19452
20596
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -19454,25 +20598,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
19454
20598
|
}
|
|
19455
20599
|
if (pkgName.startsWith("@")) {
|
|
19456
20600
|
const [scope, name] = pkgName.split("/");
|
|
19457
|
-
const scopeDir =
|
|
20601
|
+
const scopeDir = path20.join(npmRoot, scope);
|
|
19458
20602
|
if (!fs9.existsSync(scopeDir)) return;
|
|
19459
20603
|
for (const entry of fs9.readdirSync(scopeDir)) {
|
|
19460
20604
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
19461
|
-
fs9.rmSync(
|
|
19462
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
20605
|
+
fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
|
|
20606
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
|
|
19463
20607
|
}
|
|
19464
20608
|
} else {
|
|
19465
20609
|
for (const entry of fs9.readdirSync(npmRoot)) {
|
|
19466
20610
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
19467
|
-
fs9.rmSync(
|
|
19468
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
20611
|
+
fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
|
|
20612
|
+
appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
|
|
19469
20613
|
}
|
|
19470
20614
|
}
|
|
19471
20615
|
if (fs9.existsSync(binDir)) {
|
|
19472
20616
|
for (const entry of fs9.readdirSync(binDir)) {
|
|
19473
20617
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
19474
|
-
fs9.rmSync(
|
|
19475
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
20618
|
+
fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
|
|
20619
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
|
|
19476
20620
|
}
|
|
19477
20621
|
}
|
|
19478
20622
|
}
|
|
@@ -19522,7 +20666,7 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
19522
20666
|
appendUpgradeLog(installOutput.trim());
|
|
19523
20667
|
}
|
|
19524
20668
|
if (process.platform === "win32") {
|
|
19525
|
-
await new Promise((
|
|
20669
|
+
await new Promise((resolve15) => setTimeout(resolve15, 500));
|
|
19526
20670
|
cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
|
|
19527
20671
|
appendUpgradeLog("Post-install staging cleanup complete");
|
|
19528
20672
|
}
|
|
@@ -20916,7 +22060,7 @@ var ProviderStreamAdapter = class {
|
|
|
20916
22060
|
const beforeCount = this.messageCount(before);
|
|
20917
22061
|
const beforeSignature = this.lastMessageSignature(before);
|
|
20918
22062
|
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
20919
|
-
await new Promise((
|
|
22063
|
+
await new Promise((resolve15) => setTimeout(resolve15, 250));
|
|
20920
22064
|
let state;
|
|
20921
22065
|
try {
|
|
20922
22066
|
state = await this.readChat(evaluate);
|
|
@@ -20938,7 +22082,7 @@ var ProviderStreamAdapter = class {
|
|
|
20938
22082
|
if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
|
|
20939
22083
|
return first;
|
|
20940
22084
|
}
|
|
20941
|
-
await new Promise((
|
|
22085
|
+
await new Promise((resolve15) => setTimeout(resolve15, 150));
|
|
20942
22086
|
const second = await this.readChat(evaluate);
|
|
20943
22087
|
return this.messageCount(second) >= this.messageCount(first) ? second : first;
|
|
20944
22088
|
}
|
|
@@ -21089,7 +22233,7 @@ var ProviderStreamAdapter = class {
|
|
|
21089
22233
|
if (typeof data.error === "string" && data.error.trim()) return false;
|
|
21090
22234
|
}
|
|
21091
22235
|
for (let attempt = 0; attempt < 6; attempt += 1) {
|
|
21092
|
-
await new Promise((
|
|
22236
|
+
await new Promise((resolve15) => setTimeout(resolve15, 250));
|
|
21093
22237
|
const state = await this.readChat(evaluate);
|
|
21094
22238
|
const title = this.getStateTitle(state);
|
|
21095
22239
|
if (this.titlesMatch(title, sessionId)) return true;
|
|
@@ -21950,11 +23094,11 @@ init_chat_message_normalization();
|
|
|
21950
23094
|
|
|
21951
23095
|
// src/providers/version-archive.ts
|
|
21952
23096
|
import * as fs11 from "fs";
|
|
21953
|
-
import * as
|
|
23097
|
+
import * as path21 from "path";
|
|
21954
23098
|
import * as os19 from "os";
|
|
21955
23099
|
import { execSync as execSync5 } from "child_process";
|
|
21956
23100
|
import { platform as platform8 } from "os";
|
|
21957
|
-
var ARCHIVE_PATH =
|
|
23101
|
+
var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
|
|
21958
23102
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
21959
23103
|
var VersionArchive = class {
|
|
21960
23104
|
history = {};
|
|
@@ -22001,7 +23145,7 @@ var VersionArchive = class {
|
|
|
22001
23145
|
}
|
|
22002
23146
|
save() {
|
|
22003
23147
|
try {
|
|
22004
|
-
fs11.mkdirSync(
|
|
23148
|
+
fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
|
|
22005
23149
|
fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
22006
23150
|
} catch {
|
|
22007
23151
|
}
|
|
@@ -22058,7 +23202,7 @@ function checkPathExists2(paths) {
|
|
|
22058
23202
|
for (const p of paths) {
|
|
22059
23203
|
if (p.includes("*")) {
|
|
22060
23204
|
const home = os19.homedir();
|
|
22061
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
23205
|
+
const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
|
|
22062
23206
|
if (fs11.existsSync(resolved)) return resolved;
|
|
22063
23207
|
} else {
|
|
22064
23208
|
if (fs11.existsSync(p)) return p;
|
|
@@ -22068,7 +23212,7 @@ function checkPathExists2(paths) {
|
|
|
22068
23212
|
}
|
|
22069
23213
|
function getMacAppVersion(appPath) {
|
|
22070
23214
|
if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
22071
|
-
const plistPath =
|
|
23215
|
+
const plistPath = path21.join(appPath, "Contents", "Info.plist");
|
|
22072
23216
|
if (!fs11.existsSync(plistPath)) return null;
|
|
22073
23217
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
22074
23218
|
return raw || null;
|
|
@@ -22094,7 +23238,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
22094
23238
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
22095
23239
|
let resolvedBin = cliBin;
|
|
22096
23240
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
22097
|
-
const bundled =
|
|
23241
|
+
const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
22098
23242
|
if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
|
|
22099
23243
|
}
|
|
22100
23244
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -22135,7 +23279,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
22135
23279
|
// src/daemon/dev-server.ts
|
|
22136
23280
|
import * as http2 from "http";
|
|
22137
23281
|
import * as fs15 from "fs";
|
|
22138
|
-
import * as
|
|
23282
|
+
import * as path25 from "path";
|
|
22139
23283
|
init_config();
|
|
22140
23284
|
|
|
22141
23285
|
// src/daemon/scaffold-template.ts
|
|
@@ -22487,7 +23631,7 @@ init_logger();
|
|
|
22487
23631
|
// src/daemon/dev-cdp-handlers.ts
|
|
22488
23632
|
init_logger();
|
|
22489
23633
|
import * as fs12 from "fs";
|
|
22490
|
-
import * as
|
|
23634
|
+
import * as path22 from "path";
|
|
22491
23635
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
22492
23636
|
const body = await ctx.readBody(req);
|
|
22493
23637
|
const { expression, timeout, ideType } = body;
|
|
@@ -22665,17 +23809,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
22665
23809
|
return;
|
|
22666
23810
|
}
|
|
22667
23811
|
let scriptsPath = "";
|
|
22668
|
-
const directScripts =
|
|
23812
|
+
const directScripts = path22.join(dir, "scripts.js");
|
|
22669
23813
|
if (fs12.existsSync(directScripts)) {
|
|
22670
23814
|
scriptsPath = directScripts;
|
|
22671
23815
|
} else {
|
|
22672
|
-
const scriptsDir =
|
|
23816
|
+
const scriptsDir = path22.join(dir, "scripts");
|
|
22673
23817
|
if (fs12.existsSync(scriptsDir)) {
|
|
22674
23818
|
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
22675
|
-
return fs12.statSync(
|
|
23819
|
+
return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
|
|
22676
23820
|
}).sort().reverse();
|
|
22677
23821
|
for (const ver of versions) {
|
|
22678
|
-
const p =
|
|
23822
|
+
const p = path22.join(scriptsDir, ver, "scripts.js");
|
|
22679
23823
|
if (fs12.existsSync(p)) {
|
|
22680
23824
|
scriptsPath = p;
|
|
22681
23825
|
break;
|
|
@@ -23504,7 +24648,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
23504
24648
|
|
|
23505
24649
|
// src/daemon/dev-cli-debug.ts
|
|
23506
24650
|
import * as fs13 from "fs";
|
|
23507
|
-
import * as
|
|
24651
|
+
import * as path23 from "path";
|
|
23508
24652
|
function slugifyFixtureName(value) {
|
|
23509
24653
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
23510
24654
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -23514,11 +24658,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
23514
24658
|
if (!providerDir) {
|
|
23515
24659
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
23516
24660
|
}
|
|
23517
|
-
return
|
|
24661
|
+
return path23.join(providerDir, "fixtures");
|
|
23518
24662
|
}
|
|
23519
24663
|
function readCliFixture(ctx, type, name) {
|
|
23520
24664
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
23521
|
-
const filePath =
|
|
24665
|
+
const filePath = path23.join(fixtureDir, `${name}.json`);
|
|
23522
24666
|
if (!fs13.existsSync(filePath)) {
|
|
23523
24667
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
23524
24668
|
}
|
|
@@ -23687,7 +24831,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
23687
24831
|
return { target, instance, adapter };
|
|
23688
24832
|
}
|
|
23689
24833
|
function sleep(ms) {
|
|
23690
|
-
return new Promise((
|
|
24834
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
23691
24835
|
}
|
|
23692
24836
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
23693
24837
|
const startedAt = Date.now();
|
|
@@ -23985,7 +25129,7 @@ async function runCliAutoImplVerification(ctx, type, verification) {
|
|
|
23985
25129
|
return {
|
|
23986
25130
|
mode: "fixture_replay_suite",
|
|
23987
25131
|
pass: results.every((item) => item.pass),
|
|
23988
|
-
failures: results.flatMap((item) => item.failures.map((
|
|
25132
|
+
failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
|
|
23989
25133
|
result: firstFailure.result,
|
|
23990
25134
|
assertions: firstFailure.assertions,
|
|
23991
25135
|
fixture: firstFailure.fixture,
|
|
@@ -24285,7 +25429,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
24285
25429
|
},
|
|
24286
25430
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
24287
25431
|
};
|
|
24288
|
-
const filePath =
|
|
25432
|
+
const filePath = path23.join(fixtureDir, `${name}.json`);
|
|
24289
25433
|
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
24290
25434
|
ctx.json(res, 200, {
|
|
24291
25435
|
saved: true,
|
|
@@ -24309,7 +25453,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
24309
25453
|
return;
|
|
24310
25454
|
}
|
|
24311
25455
|
const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
24312
|
-
const fullPath =
|
|
25456
|
+
const fullPath = path23.join(fixtureDir, file);
|
|
24313
25457
|
try {
|
|
24314
25458
|
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
24315
25459
|
return {
|
|
@@ -24445,7 +25589,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
24445
25589
|
|
|
24446
25590
|
// src/daemon/dev-auto-implement.ts
|
|
24447
25591
|
import * as fs14 from "fs";
|
|
24448
|
-
import * as
|
|
25592
|
+
import * as path24 from "path";
|
|
24449
25593
|
import * as os20 from "os";
|
|
24450
25594
|
function getAutoImplPid(ctx) {
|
|
24451
25595
|
const pid = ctx.autoImplProcess?.pid;
|
|
@@ -24495,22 +25639,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
24495
25639
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
24496
25640
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
24497
25641
|
try {
|
|
24498
|
-
return fs14.statSync(
|
|
25642
|
+
return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
|
|
24499
25643
|
} catch {
|
|
24500
25644
|
return false;
|
|
24501
25645
|
}
|
|
24502
25646
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
24503
25647
|
if (versions.length === 0) return null;
|
|
24504
|
-
return
|
|
25648
|
+
return path24.join(scriptsDir, versions[0]);
|
|
24505
25649
|
}
|
|
24506
25650
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
24507
|
-
const canonicalUserDir =
|
|
24508
|
-
const desiredDir = requestedDir ?
|
|
24509
|
-
const upstreamRoot =
|
|
24510
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
25651
|
+
const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
25652
|
+
const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
|
|
25653
|
+
const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
|
|
25654
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
|
|
24511
25655
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
24512
25656
|
}
|
|
24513
|
-
if (
|
|
25657
|
+
if (path24.basename(desiredDir) !== type) {
|
|
24514
25658
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
24515
25659
|
}
|
|
24516
25660
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -24518,11 +25662,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
24518
25662
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
24519
25663
|
}
|
|
24520
25664
|
if (!fs14.existsSync(desiredDir)) {
|
|
24521
|
-
fs14.mkdirSync(
|
|
25665
|
+
fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
|
|
24522
25666
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
24523
25667
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
24524
25668
|
}
|
|
24525
|
-
const providerJson =
|
|
25669
|
+
const providerJson = path24.join(desiredDir, "provider.json");
|
|
24526
25670
|
if (!fs14.existsSync(providerJson)) {
|
|
24527
25671
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
24528
25672
|
}
|
|
@@ -24533,13 +25677,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
24533
25677
|
const refDir = ctx.findProviderDir(referenceType);
|
|
24534
25678
|
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
24535
25679
|
const referenceScripts = {};
|
|
24536
|
-
const scriptsDir =
|
|
25680
|
+
const scriptsDir = path24.join(refDir, "scripts");
|
|
24537
25681
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
24538
25682
|
if (!latestDir) return referenceScripts;
|
|
24539
25683
|
for (const file of fs14.readdirSync(latestDir)) {
|
|
24540
25684
|
if (!file.endsWith(".js")) continue;
|
|
24541
25685
|
try {
|
|
24542
|
-
referenceScripts[file] = fs14.readFileSync(
|
|
25686
|
+
referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
|
|
24543
25687
|
} catch {
|
|
24544
25688
|
}
|
|
24545
25689
|
}
|
|
@@ -24647,9 +25791,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
24647
25791
|
});
|
|
24648
25792
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
24649
25793
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
24650
|
-
const tmpDir =
|
|
25794
|
+
const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
|
|
24651
25795
|
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
24652
|
-
const promptFile =
|
|
25796
|
+
const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
24653
25797
|
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
24654
25798
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
24655
25799
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -25081,7 +26225,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
25081
26225
|
setMode: "set_mode.js"
|
|
25082
26226
|
};
|
|
25083
26227
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
25084
|
-
const scriptsDir =
|
|
26228
|
+
const scriptsDir = path24.join(providerDir, "scripts");
|
|
25085
26229
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
25086
26230
|
if (latestScriptsDir) {
|
|
25087
26231
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -25092,7 +26236,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
25092
26236
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
25093
26237
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
25094
26238
|
try {
|
|
25095
|
-
const content = fs14.readFileSync(
|
|
26239
|
+
const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
|
|
25096
26240
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
25097
26241
|
lines.push("```javascript");
|
|
25098
26242
|
lines.push(content);
|
|
@@ -25109,7 +26253,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
25109
26253
|
lines.push("");
|
|
25110
26254
|
for (const file of refFiles) {
|
|
25111
26255
|
try {
|
|
25112
|
-
const content = fs14.readFileSync(
|
|
26256
|
+
const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
|
|
25113
26257
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
25114
26258
|
lines.push("```javascript");
|
|
25115
26259
|
lines.push(content);
|
|
@@ -25150,10 +26294,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
25150
26294
|
lines.push("");
|
|
25151
26295
|
}
|
|
25152
26296
|
}
|
|
25153
|
-
const docsDir =
|
|
26297
|
+
const docsDir = path24.join(providerDir, "../../docs");
|
|
25154
26298
|
const loadGuide = (name) => {
|
|
25155
26299
|
try {
|
|
25156
|
-
const p =
|
|
26300
|
+
const p = path24.join(docsDir, name);
|
|
25157
26301
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
25158
26302
|
} catch {
|
|
25159
26303
|
}
|
|
@@ -25390,7 +26534,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
25390
26534
|
parseApproval: "parse_approval.js"
|
|
25391
26535
|
};
|
|
25392
26536
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
25393
|
-
const scriptsDir =
|
|
26537
|
+
const scriptsDir = path24.join(providerDir, "scripts");
|
|
25394
26538
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
25395
26539
|
if (latestScriptsDir) {
|
|
25396
26540
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -25402,7 +26546,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
25402
26546
|
if (!file.endsWith(".js")) continue;
|
|
25403
26547
|
if (!targetFileNames.has(file)) continue;
|
|
25404
26548
|
try {
|
|
25405
|
-
const content = fs14.readFileSync(
|
|
26549
|
+
const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
|
|
25406
26550
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
25407
26551
|
lines.push("```javascript");
|
|
25408
26552
|
lines.push(content);
|
|
@@ -25418,7 +26562,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
25418
26562
|
lines.push("");
|
|
25419
26563
|
for (const file of refFiles) {
|
|
25420
26564
|
try {
|
|
25421
|
-
const content = fs14.readFileSync(
|
|
26565
|
+
const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
|
|
25422
26566
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
25423
26567
|
lines.push("```javascript");
|
|
25424
26568
|
lines.push(content);
|
|
@@ -25451,10 +26595,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
25451
26595
|
lines.push("");
|
|
25452
26596
|
}
|
|
25453
26597
|
}
|
|
25454
|
-
const docsDir =
|
|
26598
|
+
const docsDir = path24.join(providerDir, "../../docs");
|
|
25455
26599
|
const loadGuide = (name) => {
|
|
25456
26600
|
try {
|
|
25457
|
-
const p =
|
|
26601
|
+
const p = path24.join(docsDir, name);
|
|
25458
26602
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
25459
26603
|
} catch {
|
|
25460
26604
|
}
|
|
@@ -25901,8 +27045,8 @@ var DevServer = class _DevServer {
|
|
|
25901
27045
|
}
|
|
25902
27046
|
getEndpointList() {
|
|
25903
27047
|
return this.routes.map((r) => {
|
|
25904
|
-
const
|
|
25905
|
-
return `${r.method.padEnd(5)} ${
|
|
27048
|
+
const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
27049
|
+
return `${r.method.padEnd(5)} ${path26}`;
|
|
25906
27050
|
});
|
|
25907
27051
|
}
|
|
25908
27052
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -25933,15 +27077,15 @@ var DevServer = class _DevServer {
|
|
|
25933
27077
|
this.json(res, 500, { error: e.message });
|
|
25934
27078
|
}
|
|
25935
27079
|
});
|
|
25936
|
-
return new Promise((
|
|
27080
|
+
return new Promise((resolve15, reject) => {
|
|
25937
27081
|
this.server.listen(port, "127.0.0.1", () => {
|
|
25938
27082
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
25939
|
-
|
|
27083
|
+
resolve15();
|
|
25940
27084
|
});
|
|
25941
27085
|
this.server.on("error", (e) => {
|
|
25942
27086
|
if (e.code === "EADDRINUSE") {
|
|
25943
27087
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
25944
|
-
|
|
27088
|
+
resolve15();
|
|
25945
27089
|
} else {
|
|
25946
27090
|
reject(e);
|
|
25947
27091
|
}
|
|
@@ -26023,20 +27167,20 @@ var DevServer = class _DevServer {
|
|
|
26023
27167
|
child.stderr?.on("data", (d) => {
|
|
26024
27168
|
stderr += d.toString().slice(0, 2e3);
|
|
26025
27169
|
});
|
|
26026
|
-
await new Promise((
|
|
27170
|
+
await new Promise((resolve15) => {
|
|
26027
27171
|
const timer = setTimeout(() => {
|
|
26028
27172
|
child.kill();
|
|
26029
|
-
|
|
27173
|
+
resolve15();
|
|
26030
27174
|
}, 3e3);
|
|
26031
27175
|
child.on("exit", () => {
|
|
26032
27176
|
clearTimeout(timer);
|
|
26033
|
-
|
|
27177
|
+
resolve15();
|
|
26034
27178
|
});
|
|
26035
27179
|
child.stdout?.once("data", () => {
|
|
26036
27180
|
setTimeout(() => {
|
|
26037
27181
|
child.kill();
|
|
26038
27182
|
clearTimeout(timer);
|
|
26039
|
-
|
|
27183
|
+
resolve15();
|
|
26040
27184
|
}, 500);
|
|
26041
27185
|
});
|
|
26042
27186
|
});
|
|
@@ -26190,12 +27334,12 @@ var DevServer = class _DevServer {
|
|
|
26190
27334
|
// ─── DevConsole SPA ───
|
|
26191
27335
|
getConsoleDistDir() {
|
|
26192
27336
|
const candidates = [
|
|
26193
|
-
|
|
26194
|
-
|
|
26195
|
-
|
|
27337
|
+
path25.resolve(__dirname, "../../web-devconsole/dist"),
|
|
27338
|
+
path25.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
27339
|
+
path25.join(process.cwd(), "packages/web-devconsole/dist")
|
|
26196
27340
|
];
|
|
26197
27341
|
for (const dir of candidates) {
|
|
26198
|
-
if (fs15.existsSync(
|
|
27342
|
+
if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
|
|
26199
27343
|
}
|
|
26200
27344
|
return null;
|
|
26201
27345
|
}
|
|
@@ -26205,7 +27349,7 @@ var DevServer = class _DevServer {
|
|
|
26205
27349
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
26206
27350
|
return;
|
|
26207
27351
|
}
|
|
26208
|
-
const htmlPath =
|
|
27352
|
+
const htmlPath = path25.join(distDir, "index.html");
|
|
26209
27353
|
try {
|
|
26210
27354
|
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
26211
27355
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -26230,15 +27374,15 @@ var DevServer = class _DevServer {
|
|
|
26230
27374
|
this.json(res, 404, { error: "Not found" });
|
|
26231
27375
|
return;
|
|
26232
27376
|
}
|
|
26233
|
-
const safePath =
|
|
26234
|
-
const filePath =
|
|
27377
|
+
const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
|
|
27378
|
+
const filePath = path25.join(distDir, safePath);
|
|
26235
27379
|
if (!filePath.startsWith(distDir)) {
|
|
26236
27380
|
this.json(res, 403, { error: "Forbidden" });
|
|
26237
27381
|
return;
|
|
26238
27382
|
}
|
|
26239
27383
|
try {
|
|
26240
27384
|
const content = fs15.readFileSync(filePath);
|
|
26241
|
-
const ext =
|
|
27385
|
+
const ext = path25.extname(filePath);
|
|
26242
27386
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
26243
27387
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
26244
27388
|
res.end(content);
|
|
@@ -26351,10 +27495,10 @@ var DevServer = class _DevServer {
|
|
|
26351
27495
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
26352
27496
|
if (entry.isDirectory()) {
|
|
26353
27497
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
26354
|
-
scan(
|
|
27498
|
+
scan(path25.join(d, entry.name), rel);
|
|
26355
27499
|
} else {
|
|
26356
|
-
const
|
|
26357
|
-
files.push({ path: rel, size:
|
|
27500
|
+
const stat2 = fs15.statSync(path25.join(d, entry.name));
|
|
27501
|
+
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
26358
27502
|
}
|
|
26359
27503
|
}
|
|
26360
27504
|
} catch {
|
|
@@ -26376,7 +27520,7 @@ var DevServer = class _DevServer {
|
|
|
26376
27520
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
26377
27521
|
return;
|
|
26378
27522
|
}
|
|
26379
|
-
const fullPath =
|
|
27523
|
+
const fullPath = path25.resolve(dir, path25.normalize(filePath));
|
|
26380
27524
|
if (!fullPath.startsWith(dir)) {
|
|
26381
27525
|
this.json(res, 403, { error: "Forbidden" });
|
|
26382
27526
|
return;
|
|
@@ -26401,14 +27545,14 @@ var DevServer = class _DevServer {
|
|
|
26401
27545
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
26402
27546
|
return;
|
|
26403
27547
|
}
|
|
26404
|
-
const fullPath =
|
|
27548
|
+
const fullPath = path25.resolve(dir, path25.normalize(filePath));
|
|
26405
27549
|
if (!fullPath.startsWith(dir)) {
|
|
26406
27550
|
this.json(res, 403, { error: "Forbidden" });
|
|
26407
27551
|
return;
|
|
26408
27552
|
}
|
|
26409
27553
|
try {
|
|
26410
27554
|
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
26411
|
-
fs15.mkdirSync(
|
|
27555
|
+
fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
|
|
26412
27556
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
26413
27557
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
26414
27558
|
this.providerLoader.reload();
|
|
@@ -26425,7 +27569,7 @@ var DevServer = class _DevServer {
|
|
|
26425
27569
|
return;
|
|
26426
27570
|
}
|
|
26427
27571
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
26428
|
-
const p =
|
|
27572
|
+
const p = path25.join(dir, name);
|
|
26429
27573
|
if (fs15.existsSync(p)) {
|
|
26430
27574
|
const source = fs15.readFileSync(p, "utf-8");
|
|
26431
27575
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -26446,8 +27590,8 @@ var DevServer = class _DevServer {
|
|
|
26446
27590
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
26447
27591
|
return;
|
|
26448
27592
|
}
|
|
26449
|
-
const target = fs15.existsSync(
|
|
26450
|
-
const targetPath =
|
|
27593
|
+
const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
27594
|
+
const targetPath = path25.join(dir, target);
|
|
26451
27595
|
try {
|
|
26452
27596
|
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
26453
27597
|
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -26539,14 +27683,14 @@ var DevServer = class _DevServer {
|
|
|
26539
27683
|
child.stderr?.on("data", (d) => {
|
|
26540
27684
|
stderr += d.toString();
|
|
26541
27685
|
});
|
|
26542
|
-
await new Promise((
|
|
27686
|
+
await new Promise((resolve15) => {
|
|
26543
27687
|
const timer = setTimeout(() => {
|
|
26544
27688
|
child.kill();
|
|
26545
|
-
|
|
27689
|
+
resolve15();
|
|
26546
27690
|
}, timeout);
|
|
26547
27691
|
child.on("exit", () => {
|
|
26548
27692
|
clearTimeout(timer);
|
|
26549
|
-
|
|
27693
|
+
resolve15();
|
|
26550
27694
|
});
|
|
26551
27695
|
});
|
|
26552
27696
|
const elapsed = Date.now() - start;
|
|
@@ -26594,7 +27738,7 @@ var DevServer = class _DevServer {
|
|
|
26594
27738
|
}
|
|
26595
27739
|
let targetDir;
|
|
26596
27740
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
26597
|
-
const jsonPath =
|
|
27741
|
+
const jsonPath = path25.join(targetDir, "provider.json");
|
|
26598
27742
|
if (fs15.existsSync(jsonPath)) {
|
|
26599
27743
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
26600
27744
|
return;
|
|
@@ -26606,8 +27750,8 @@ var DevServer = class _DevServer {
|
|
|
26606
27750
|
const createdFiles = ["provider.json"];
|
|
26607
27751
|
if (result.files) {
|
|
26608
27752
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
26609
|
-
const fullPath =
|
|
26610
|
-
fs15.mkdirSync(
|
|
27753
|
+
const fullPath = path25.join(targetDir, relPath);
|
|
27754
|
+
fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
|
|
26611
27755
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
26612
27756
|
createdFiles.push(relPath);
|
|
26613
27757
|
}
|
|
@@ -26660,22 +27804,22 @@ var DevServer = class _DevServer {
|
|
|
26660
27804
|
if (!fs15.existsSync(scriptsDir)) return null;
|
|
26661
27805
|
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
26662
27806
|
try {
|
|
26663
|
-
return fs15.statSync(
|
|
27807
|
+
return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
|
|
26664
27808
|
} catch {
|
|
26665
27809
|
return false;
|
|
26666
27810
|
}
|
|
26667
27811
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
26668
27812
|
if (versions.length === 0) return null;
|
|
26669
|
-
return
|
|
27813
|
+
return path25.join(scriptsDir, versions[0]);
|
|
26670
27814
|
}
|
|
26671
27815
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
26672
|
-
const canonicalUserDir =
|
|
26673
|
-
const desiredDir = requestedDir ?
|
|
26674
|
-
const upstreamRoot =
|
|
26675
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
27816
|
+
const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
27817
|
+
const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
|
|
27818
|
+
const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
|
|
27819
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
|
|
26676
27820
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
26677
27821
|
}
|
|
26678
|
-
if (
|
|
27822
|
+
if (path25.basename(desiredDir) !== type) {
|
|
26679
27823
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
26680
27824
|
}
|
|
26681
27825
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -26683,11 +27827,11 @@ var DevServer = class _DevServer {
|
|
|
26683
27827
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
26684
27828
|
}
|
|
26685
27829
|
if (!fs15.existsSync(desiredDir)) {
|
|
26686
|
-
fs15.mkdirSync(
|
|
27830
|
+
fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
|
|
26687
27831
|
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
26688
27832
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
26689
27833
|
}
|
|
26690
|
-
const providerJson =
|
|
27834
|
+
const providerJson = path25.join(desiredDir, "provider.json");
|
|
26691
27835
|
if (!fs15.existsSync(providerJson)) {
|
|
26692
27836
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
26693
27837
|
}
|
|
@@ -26723,7 +27867,7 @@ var DevServer = class _DevServer {
|
|
|
26723
27867
|
setMode: "set_mode.js"
|
|
26724
27868
|
};
|
|
26725
27869
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26726
|
-
const scriptsDir =
|
|
27870
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26727
27871
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
26728
27872
|
if (latestScriptsDir) {
|
|
26729
27873
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26734,7 +27878,7 @@ var DevServer = class _DevServer {
|
|
|
26734
27878
|
for (const file of fs15.readdirSync(latestScriptsDir)) {
|
|
26735
27879
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
26736
27880
|
try {
|
|
26737
|
-
const content = fs15.readFileSync(
|
|
27881
|
+
const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26738
27882
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26739
27883
|
lines.push("```javascript");
|
|
26740
27884
|
lines.push(content);
|
|
@@ -26751,7 +27895,7 @@ var DevServer = class _DevServer {
|
|
|
26751
27895
|
lines.push("");
|
|
26752
27896
|
for (const file of refFiles) {
|
|
26753
27897
|
try {
|
|
26754
|
-
const content = fs15.readFileSync(
|
|
27898
|
+
const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26755
27899
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26756
27900
|
lines.push("```javascript");
|
|
26757
27901
|
lines.push(content);
|
|
@@ -26792,10 +27936,10 @@ var DevServer = class _DevServer {
|
|
|
26792
27936
|
lines.push("");
|
|
26793
27937
|
}
|
|
26794
27938
|
}
|
|
26795
|
-
const docsDir =
|
|
27939
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26796
27940
|
const loadGuide = (name) => {
|
|
26797
27941
|
try {
|
|
26798
|
-
const p =
|
|
27942
|
+
const p = path25.join(docsDir, name);
|
|
26799
27943
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
26800
27944
|
} catch {
|
|
26801
27945
|
}
|
|
@@ -26969,7 +28113,7 @@ var DevServer = class _DevServer {
|
|
|
26969
28113
|
parseApproval: "parse_approval.js"
|
|
26970
28114
|
};
|
|
26971
28115
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26972
|
-
const scriptsDir =
|
|
28116
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26973
28117
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
26974
28118
|
if (latestScriptsDir) {
|
|
26975
28119
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26981,7 +28125,7 @@ var DevServer = class _DevServer {
|
|
|
26981
28125
|
if (!file.endsWith(".js")) continue;
|
|
26982
28126
|
if (!targetFileNames.has(file)) continue;
|
|
26983
28127
|
try {
|
|
26984
|
-
const content = fs15.readFileSync(
|
|
28128
|
+
const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26985
28129
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26986
28130
|
lines.push("```javascript");
|
|
26987
28131
|
lines.push(content);
|
|
@@ -26997,7 +28141,7 @@ var DevServer = class _DevServer {
|
|
|
26997
28141
|
lines.push("");
|
|
26998
28142
|
for (const file of refFiles) {
|
|
26999
28143
|
try {
|
|
27000
|
-
const content = fs15.readFileSync(
|
|
28144
|
+
const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
27001
28145
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
27002
28146
|
lines.push("```javascript");
|
|
27003
28147
|
lines.push(content);
|
|
@@ -27030,10 +28174,10 @@ var DevServer = class _DevServer {
|
|
|
27030
28174
|
lines.push("");
|
|
27031
28175
|
}
|
|
27032
28176
|
}
|
|
27033
|
-
const docsDir =
|
|
28177
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
27034
28178
|
const loadGuide = (name) => {
|
|
27035
28179
|
try {
|
|
27036
|
-
const p =
|
|
28180
|
+
const p = path25.join(docsDir, name);
|
|
27037
28181
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
27038
28182
|
} catch {
|
|
27039
28183
|
}
|
|
@@ -27216,14 +28360,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
27216
28360
|
res.end(JSON.stringify(data, null, 2));
|
|
27217
28361
|
}
|
|
27218
28362
|
async readBody(req) {
|
|
27219
|
-
return new Promise((
|
|
28363
|
+
return new Promise((resolve15) => {
|
|
27220
28364
|
let body = "";
|
|
27221
28365
|
req.on("data", (chunk) => body += chunk);
|
|
27222
28366
|
req.on("end", () => {
|
|
27223
28367
|
try {
|
|
27224
|
-
|
|
28368
|
+
resolve15(JSON.parse(body));
|
|
27225
28369
|
} catch {
|
|
27226
|
-
|
|
28370
|
+
resolve15({});
|
|
27227
28371
|
}
|
|
27228
28372
|
});
|
|
27229
28373
|
});
|
|
@@ -27738,7 +28882,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
27738
28882
|
const deadline = Date.now() + timeoutMs;
|
|
27739
28883
|
while (Date.now() < deadline) {
|
|
27740
28884
|
if (await canConnect(endpoint)) return;
|
|
27741
|
-
await new Promise((
|
|
28885
|
+
await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
|
|
27742
28886
|
}
|
|
27743
28887
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
27744
28888
|
}
|
|
@@ -27916,10 +29060,10 @@ async function installExtension(ide, extension) {
|
|
|
27916
29060
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
27917
29061
|
const fs16 = await import("fs");
|
|
27918
29062
|
fs16.writeFileSync(vsixPath, buffer);
|
|
27919
|
-
return new Promise((
|
|
29063
|
+
return new Promise((resolve15) => {
|
|
27920
29064
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
27921
29065
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
27922
|
-
|
|
29066
|
+
resolve15({
|
|
27923
29067
|
extensionId: extension.id,
|
|
27924
29068
|
marketplaceId: extension.marketplaceId,
|
|
27925
29069
|
success: !error,
|
|
@@ -27932,11 +29076,11 @@ async function installExtension(ide, extension) {
|
|
|
27932
29076
|
} catch (e) {
|
|
27933
29077
|
}
|
|
27934
29078
|
}
|
|
27935
|
-
return new Promise((
|
|
29079
|
+
return new Promise((resolve15) => {
|
|
27936
29080
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
27937
29081
|
exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
27938
29082
|
if (error) {
|
|
27939
|
-
|
|
29083
|
+
resolve15({
|
|
27940
29084
|
extensionId: extension.id,
|
|
27941
29085
|
marketplaceId: extension.marketplaceId,
|
|
27942
29086
|
success: false,
|
|
@@ -27944,7 +29088,7 @@ async function installExtension(ide, extension) {
|
|
|
27944
29088
|
error: stderr || error.message
|
|
27945
29089
|
});
|
|
27946
29090
|
} else {
|
|
27947
|
-
|
|
29091
|
+
resolve15({
|
|
27948
29092
|
extensionId: extension.id,
|
|
27949
29093
|
marketplaceId: extension.marketplaceId,
|
|
27950
29094
|
success: true,
|
|
@@ -28273,6 +29417,7 @@ export {
|
|
|
28273
29417
|
DEFAULT_CDP_SCAN_INTERVAL_MS,
|
|
28274
29418
|
DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
|
|
28275
29419
|
DEFAULT_DAEMON_PORT,
|
|
29420
|
+
DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
28276
29421
|
DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
28277
29422
|
DEFAULT_SESSION_HOST_APP_NAME,
|
|
28278
29423
|
DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
@@ -28291,8 +29436,12 @@ export {
|
|
|
28291
29436
|
DaemonCommandRouter,
|
|
28292
29437
|
DaemonStatusReporter,
|
|
28293
29438
|
DevServer,
|
|
29439
|
+
GitCommandError,
|
|
29440
|
+
GitWorkspaceMonitor,
|
|
28294
29441
|
IdeProviderInstance,
|
|
29442
|
+
InMemoryGitSnapshotStore,
|
|
28295
29443
|
LOG,
|
|
29444
|
+
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
28296
29445
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
28297
29446
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
28298
29447
|
NodePtyTransportFactory,
|
|
@@ -28320,9 +29469,14 @@ export {
|
|
|
28320
29469
|
buildUserChatMessage,
|
|
28321
29470
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
28322
29471
|
clearDebugTrace,
|
|
29472
|
+
compareGitSnapshots,
|
|
28323
29473
|
configureDebugTraceStore,
|
|
28324
29474
|
connectCdpManager,
|
|
28325
29475
|
createDebugTraceStore,
|
|
29476
|
+
createDefaultGitCommandServices,
|
|
29477
|
+
createGitCompactSummary,
|
|
29478
|
+
createGitSnapshotStore,
|
|
29479
|
+
createGitWorkspaceMonitor,
|
|
28326
29480
|
createInteractionId,
|
|
28327
29481
|
detectAllVersions,
|
|
28328
29482
|
detectCLIs,
|
|
@@ -28337,6 +29491,9 @@ export {
|
|
|
28337
29491
|
getCurrentDaemonLogPath,
|
|
28338
29492
|
getDaemonLogDir,
|
|
28339
29493
|
getDebugRuntimeConfig,
|
|
29494
|
+
getGitDiffSummary,
|
|
29495
|
+
getGitFileDiff,
|
|
29496
|
+
getGitRepoStatus,
|
|
28340
29497
|
getHostMemorySnapshot,
|
|
28341
29498
|
getLogLevel,
|
|
28342
29499
|
getNpmExecOptions,
|
|
@@ -28348,6 +29505,7 @@ export {
|
|
|
28348
29505
|
getSessionHostRecoveryLabel,
|
|
28349
29506
|
getSessionHostSurfaceKind,
|
|
28350
29507
|
getWorkspaceState,
|
|
29508
|
+
handleGitCommand,
|
|
28351
29509
|
hasCdpManager,
|
|
28352
29510
|
hashSignatureParts,
|
|
28353
29511
|
initDaemonComponents,
|
|
@@ -28356,9 +29514,11 @@ export {
|
|
|
28356
29514
|
isBuiltinChatMessageKind,
|
|
28357
29515
|
isCdpConnected,
|
|
28358
29516
|
isExtensionInstalled,
|
|
29517
|
+
isGitCommandName,
|
|
28359
29518
|
isIdeRunning,
|
|
28360
29519
|
isManagedStatusWaiting,
|
|
28361
29520
|
isManagedStatusWorking,
|
|
29521
|
+
isPathInside,
|
|
28362
29522
|
isSessionHostLiveRuntime,
|
|
28363
29523
|
isSessionHostRecoverySnapshot,
|
|
28364
29524
|
isSetupComplete,
|
|
@@ -28376,10 +29536,13 @@ export {
|
|
|
28376
29536
|
normalizeChatMessageKind,
|
|
28377
29537
|
normalizeChatMessages,
|
|
28378
29538
|
normalizeChatTailActiveModal,
|
|
29539
|
+
normalizeGitOutput,
|
|
29540
|
+
normalizeGitWorkspaceSubscriptionParams,
|
|
28379
29541
|
normalizeInputEnvelope,
|
|
28380
29542
|
normalizeManagedStatus,
|
|
28381
29543
|
normalizeMessageParts,
|
|
28382
29544
|
normalizeSessionModalFields,
|
|
29545
|
+
parsePorcelainV2Status,
|
|
28383
29546
|
parseProviderSourceConfigUpdate,
|
|
28384
29547
|
partitionSessionHostDiagnosticsSessions,
|
|
28385
29548
|
partitionSessionHostRecords,
|
|
@@ -28395,9 +29558,11 @@ export {
|
|
|
28395
29558
|
resolveChatMessageKind,
|
|
28396
29559
|
resolveCurrentGlobalInstallSurface,
|
|
28397
29560
|
resolveDebugRuntimeConfig,
|
|
29561
|
+
resolveGitRepository,
|
|
28398
29562
|
resolveSessionHostAppName,
|
|
28399
29563
|
resolveSessionHostAppNameResolution,
|
|
28400
29564
|
runAsyncBatch,
|
|
29565
|
+
runGit,
|
|
28401
29566
|
saveConfig,
|
|
28402
29567
|
saveState,
|
|
28403
29568
|
setDebugRuntimeConfig,
|
|
@@ -28408,6 +29573,7 @@ export {
|
|
|
28408
29573
|
shutdownDaemonComponents,
|
|
28409
29574
|
spawnDetachedDaemonUpgradeHelper,
|
|
28410
29575
|
startDaemonDevSupport,
|
|
29576
|
+
summarizeGitStatus,
|
|
28411
29577
|
updateConfig,
|
|
28412
29578
|
upsertSavedProviderSession
|
|
28413
29579
|
};
|