@cortexkit/aft-opencode 0.58.0 → 0.58.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge-bootstrap.d.ts +8 -0
- package/dist/bridge-bootstrap.d.ts.map +1 -1
- package/dist/config-live-reload.d.ts +315 -0
- package/dist/config-live-reload.d.ts.map +1 -0
- package/dist/config.d.ts +46 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/entry/server.js +1068 -278
- package/dist/hooks/auto-update-checker/checker.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1044 -266
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/lsp-npm-table.d.ts +1 -1
- package/dist/lsp-npm-table.d.ts.map +1 -1
- package/dist/shared/read-vision.d.ts +10 -0
- package/dist/shared/read-vision.d.ts.map +1 -0
- package/dist/tool-perf.d.ts +1 -0
- package/dist/tool-perf.d.ts.map +1 -1
- package/dist/tools/bash_watch.d.ts +3 -0
- package/dist/tools/bash_watch.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/permissions.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/entry/server-runtime.mjs +16 -1
- package/src/shared/read-vision.ts +100 -0
package/dist/index.js
CHANGED
|
@@ -7878,6 +7878,9 @@ function isTerminalStatus(status) {
|
|
|
7878
7878
|
function sleep(ms) {
|
|
7879
7879
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7880
7880
|
}
|
|
7881
|
+
function monotonicNowMs() {
|
|
7882
|
+
return performance.now();
|
|
7883
|
+
}
|
|
7881
7884
|
// ../aft-bridge/dist/bash-hints.js
|
|
7882
7885
|
import * as fs from "node:fs";
|
|
7883
7886
|
import * as os from "node:os";
|
|
@@ -7888,6 +7891,10 @@ function resolveWatchTimeoutMs(requestedMs, role, capMs) {
|
|
|
7888
7891
|
const fallback = role === "worker" ? capMs : DEFAULT_PRIMARY_WATCH_TIMEOUT_MS;
|
|
7889
7892
|
return Math.min(requestedMs ?? fallback, capMs);
|
|
7890
7893
|
}
|
|
7894
|
+
function formatWatchWaited(elapsedMs, limitMs, capMs) {
|
|
7895
|
+
const limit = limitMs >= capMs ? `limit ${limitMs}ms, the bash.watch_sync_max_ms cap` : `limit ${limitMs}ms`;
|
|
7896
|
+
return `Waited ${Math.round(elapsedMs)}ms (${limit})`;
|
|
7897
|
+
}
|
|
7891
7898
|
function watchTimeoutSteer(role, capMs, timeoutParam = "timeoutMs") {
|
|
7892
7899
|
if (role === "worker") {
|
|
7893
7900
|
return `The command is still running; this is not a failure. Watch again (${timeoutParam} up to ${capMs}) and don't report a result until it finishes.`;
|
|
@@ -8274,7 +8281,7 @@ import { existsSync } from "node:fs";
|
|
|
8274
8281
|
import { join as join3 } from "node:path";
|
|
8275
8282
|
|
|
8276
8283
|
// ../aft-bridge/dist/child-process.js
|
|
8277
|
-
import { execFileSync as nodeExecFileSync, execSync as nodeExecSync, spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
|
|
8284
|
+
import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as nodeExecSync, spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
|
|
8278
8285
|
var HIDDEN = { windowsHide: true };
|
|
8279
8286
|
function withWindowsHidden(args, takesArgv) {
|
|
8280
8287
|
const out = [...args];
|
|
@@ -8296,6 +8303,7 @@ function hidden(resolve, takesArgv) {
|
|
|
8296
8303
|
}
|
|
8297
8304
|
var spawn = hidden(() => nodeSpawn, true);
|
|
8298
8305
|
var spawnSync = hidden(() => nodeSpawnSync, true);
|
|
8306
|
+
var execFile = hidden(() => nodeExecFile, true);
|
|
8299
8307
|
var execFileSync = hidden(() => nodeExecFileSync, true);
|
|
8300
8308
|
var execSync = hidden(() => nodeExecSync, false);
|
|
8301
8309
|
|
|
@@ -9622,17 +9630,30 @@ class BinaryBridge {
|
|
|
9622
9630
|
}
|
|
9623
9631
|
}
|
|
9624
9632
|
onStderrData(data) {
|
|
9625
|
-
|
|
9626
|
-
let
|
|
9627
|
-
while (
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9633
|
+
const partialLimit = 64 * 1024;
|
|
9634
|
+
let offset = 0;
|
|
9635
|
+
while (offset < data.length) {
|
|
9636
|
+
const newline = data.indexOf(`
|
|
9637
|
+
`, offset);
|
|
9638
|
+
const end = newline < 0 ? data.length : newline;
|
|
9639
|
+
while (offset < end) {
|
|
9640
|
+
const count = Math.min(partialLimit - this.stderrBuffer.length, end - offset);
|
|
9641
|
+
this.stderrBuffer += data.slice(offset, offset + count);
|
|
9642
|
+
offset += count;
|
|
9643
|
+
if (this.stderrBuffer.length === partialLimit) {
|
|
9644
|
+
const last = this.stderrBuffer.charCodeAt(this.stderrBuffer.length - 1);
|
|
9645
|
+
const carry = last >= 55296 && last <= 56319 ? this.stderrBuffer.slice(-1) : "";
|
|
9646
|
+
const fragment = carry ? this.stderrBuffer.slice(0, -1) : this.stderrBuffer;
|
|
9647
|
+
const tagged = tagStderrLine(`${fragment} [stderr record truncated into bounded fragments; ${Buffer.byteLength(fragment)} bytes shown, continuation follows]`);
|
|
9648
|
+
this.stderrBuffer = carry;
|
|
9649
|
+
this.logVia(tagged);
|
|
9650
|
+
this.pushStderrLine(tagged);
|
|
9651
|
+
}
|
|
9652
|
+
}
|
|
9653
|
+
if (newline < 0)
|
|
9654
|
+
break;
|
|
9655
|
+
this.flushStderrBuffer();
|
|
9656
|
+
offset = newline + 1;
|
|
9636
9657
|
}
|
|
9637
9658
|
}
|
|
9638
9659
|
flushStderrBuffer() {
|
|
@@ -10121,9 +10142,366 @@ function formatDroppedKeyWarnings(dropped) {
|
|
|
10121
10142
|
}
|
|
10122
10143
|
return dropped.map((item) => `Ignoring ${item.key} from ${item.tier} config (${item.reason})`);
|
|
10123
10144
|
}
|
|
10145
|
+
// ../aft-bridge/dist/config-watch.js
|
|
10146
|
+
import { readFileSync as readFileSync3, statSync as statSync3, watch } from "node:fs";
|
|
10147
|
+
import { basename, dirname } from "node:path";
|
|
10148
|
+
var CONFIG_WATCH_DEBOUNCE_MS = 150;
|
|
10149
|
+
var CONFIG_LIVE_KEEP_NOTE = "AFT keeps using the last valid configuration until the file is fixed.";
|
|
10150
|
+
function pathKey(name) {
|
|
10151
|
+
const segments = name.split(".");
|
|
10152
|
+
return {
|
|
10153
|
+
name,
|
|
10154
|
+
read(config) {
|
|
10155
|
+
let value = config;
|
|
10156
|
+
for (const segment of segments) {
|
|
10157
|
+
if (value === null || typeof value !== "object")
|
|
10158
|
+
return;
|
|
10159
|
+
value = value[segment];
|
|
10160
|
+
}
|
|
10161
|
+
return value;
|
|
10162
|
+
},
|
|
10163
|
+
write(config, value) {
|
|
10164
|
+
const set = (target, index) => {
|
|
10165
|
+
const copy = target !== null && typeof target === "object" && !Array.isArray(target) ? { ...target } : {};
|
|
10166
|
+
const segment = segments[index];
|
|
10167
|
+
if (index === segments.length - 1) {
|
|
10168
|
+
if (value === undefined)
|
|
10169
|
+
delete copy[segment];
|
|
10170
|
+
else
|
|
10171
|
+
copy[segment] = value;
|
|
10172
|
+
} else {
|
|
10173
|
+
copy[segment] = set(copy[segment], index + 1);
|
|
10174
|
+
}
|
|
10175
|
+
return copy;
|
|
10176
|
+
};
|
|
10177
|
+
return set(config, 0);
|
|
10178
|
+
}
|
|
10179
|
+
};
|
|
10180
|
+
}
|
|
10181
|
+
function bashKey(name, resolveBash) {
|
|
10182
|
+
return {
|
|
10183
|
+
name: `bash.${name}`,
|
|
10184
|
+
read: (config) => resolveBash(config)[name],
|
|
10185
|
+
write(config, value) {
|
|
10186
|
+
const resolved = { ...resolveBash(config), [name]: value };
|
|
10187
|
+
for (const key of Object.keys(resolved)) {
|
|
10188
|
+
if (resolved[key] === undefined)
|
|
10189
|
+
delete resolved[key];
|
|
10190
|
+
}
|
|
10191
|
+
return { ...config, bash: resolved };
|
|
10192
|
+
}
|
|
10193
|
+
};
|
|
10194
|
+
}
|
|
10195
|
+
function aftLiveConfigKeys(resolveBash) {
|
|
10196
|
+
return [
|
|
10197
|
+
pathKey("configure_warnings_delivery"),
|
|
10198
|
+
pathKey("restrict_to_project_root"),
|
|
10199
|
+
pathKey("inspect.diagnostics_timeout_ms"),
|
|
10200
|
+
pathKey("inspect.tier2_idle_minutes"),
|
|
10201
|
+
bashKey("foreground_wait_window_ms", resolveBash),
|
|
10202
|
+
bashKey("host_fallback", resolveBash),
|
|
10203
|
+
bashKey("subagent_background", resolveBash),
|
|
10204
|
+
bashKey("watch_sync_max_ms", resolveBash)
|
|
10205
|
+
];
|
|
10206
|
+
}
|
|
10207
|
+
function sameValue(a, b) {
|
|
10208
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
10209
|
+
}
|
|
10210
|
+
function flattenLeaves(value, prefix, out) {
|
|
10211
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
10212
|
+
const entries = Object.entries(value);
|
|
10213
|
+
if (entries.length === 0 && prefix)
|
|
10214
|
+
out.set(prefix, "{}");
|
|
10215
|
+
for (const [key, child] of entries) {
|
|
10216
|
+
flattenLeaves(child, prefix ? `${prefix}.${key}` : key, out);
|
|
10217
|
+
}
|
|
10218
|
+
return;
|
|
10219
|
+
}
|
|
10220
|
+
if (prefix)
|
|
10221
|
+
out.set(prefix, JSON.stringify(value));
|
|
10222
|
+
}
|
|
10223
|
+
function applyLiveConfigKeys(current, next, keys, baseline = current) {
|
|
10224
|
+
let config = current;
|
|
10225
|
+
const applied = [];
|
|
10226
|
+
for (const key of keys) {
|
|
10227
|
+
const value = key.read(next);
|
|
10228
|
+
if (sameValue(key.read(current), value))
|
|
10229
|
+
continue;
|
|
10230
|
+
config = key.write(config, value);
|
|
10231
|
+
applied.push(key.name);
|
|
10232
|
+
}
|
|
10233
|
+
const before = new Map;
|
|
10234
|
+
const after = new Map;
|
|
10235
|
+
flattenLeaves(baseline, "", before);
|
|
10236
|
+
flattenLeaves(next, "", after);
|
|
10237
|
+
const liveNames = keys.map((key) => key.name);
|
|
10238
|
+
const isLive = (leaf) => liveNames.some((name) => leaf === name || leaf.startsWith(`${name}.`));
|
|
10239
|
+
const deferred = new Set;
|
|
10240
|
+
for (const leaf of new Set([...before.keys(), ...after.keys()])) {
|
|
10241
|
+
if (before.get(leaf) === after.get(leaf) || isLive(leaf))
|
|
10242
|
+
continue;
|
|
10243
|
+
deferred.add(leaf);
|
|
10244
|
+
}
|
|
10245
|
+
return { config, applied, deferred: [...deferred].sort() };
|
|
10246
|
+
}
|
|
10247
|
+
function readTextOrNull(path) {
|
|
10248
|
+
try {
|
|
10249
|
+
return readFileSync3(path, "utf8");
|
|
10250
|
+
} catch {
|
|
10251
|
+
return null;
|
|
10252
|
+
}
|
|
10253
|
+
}
|
|
10254
|
+
var CONFIG_WATCH_REVALIDATE_MS = 2000;
|
|
10255
|
+
var CONFIG_WATCH_REJECTED_RETRIES = 3;
|
|
10256
|
+
var CONFIG_WATCH_MAX_DELAY_MS = 1000;
|
|
10257
|
+
function identityOf(dir) {
|
|
10258
|
+
try {
|
|
10259
|
+
const stat = statSync3(dir, { bigint: true });
|
|
10260
|
+
const base = `${stat.dev}:${stat.ino}`;
|
|
10261
|
+
return process.platform === "win32" ? base : `${base}:${stat.birthtimeNs}`;
|
|
10262
|
+
} catch {
|
|
10263
|
+
return null;
|
|
10264
|
+
}
|
|
10265
|
+
}
|
|
10266
|
+
function watchDirFor(file) {
|
|
10267
|
+
let dir = dirname(file);
|
|
10268
|
+
while (dir !== dirname(dir) && identityOf(dir) === null)
|
|
10269
|
+
dir = dirname(dir);
|
|
10270
|
+
return dir;
|
|
10271
|
+
}
|
|
10272
|
+
function watchAftConfigFiles(options) {
|
|
10273
|
+
const debounceMs = options.debounceMs ?? CONFIG_WATCH_DEBOUNCE_MS;
|
|
10274
|
+
const lastSeen = new Map;
|
|
10275
|
+
for (const path of options.paths) {
|
|
10276
|
+
if (options.initialTexts)
|
|
10277
|
+
lastSeen.set(path, options.initialTexts[path] ?? null);
|
|
10278
|
+
else
|
|
10279
|
+
lastSeen.set(path, options.checkAtStart ? undefined : readTextOrNull(path));
|
|
10280
|
+
}
|
|
10281
|
+
let timer = null;
|
|
10282
|
+
let firstPendingAt = null;
|
|
10283
|
+
let stopped = false;
|
|
10284
|
+
const watchers = new Map;
|
|
10285
|
+
const watchImpl = options.watchImpl ?? watch;
|
|
10286
|
+
let rejectedRetries = 0;
|
|
10287
|
+
const check = () => {
|
|
10288
|
+
timer = null;
|
|
10289
|
+
firstPendingAt = null;
|
|
10290
|
+
if (stopped)
|
|
10291
|
+
return;
|
|
10292
|
+
revalidate();
|
|
10293
|
+
const seen = new Map;
|
|
10294
|
+
for (const path of options.paths) {
|
|
10295
|
+
const text = readTextOrNull(path);
|
|
10296
|
+
if (text !== lastSeen.get(path))
|
|
10297
|
+
seen.set(path, text);
|
|
10298
|
+
}
|
|
10299
|
+
if (seen.size === 0)
|
|
10300
|
+
return;
|
|
10301
|
+
const outcome = options.onChange();
|
|
10302
|
+
if (outcome === false) {
|
|
10303
|
+
if (rejectedRetries < CONFIG_WATCH_REJECTED_RETRIES) {
|
|
10304
|
+
rejectedRetries += 1;
|
|
10305
|
+
retryTimer = setTimeout(check, CONFIG_WATCH_MAX_DELAY_MS);
|
|
10306
|
+
retryTimer.unref?.();
|
|
10307
|
+
}
|
|
10308
|
+
return;
|
|
10309
|
+
}
|
|
10310
|
+
rejectedRetries = 0;
|
|
10311
|
+
if (outcome instanceof Map) {
|
|
10312
|
+
for (const path of options.paths)
|
|
10313
|
+
lastSeen.set(path, outcome.get(path) ?? null);
|
|
10314
|
+
} else {
|
|
10315
|
+
for (const [path, text] of seen)
|
|
10316
|
+
lastSeen.set(path, text);
|
|
10317
|
+
}
|
|
10318
|
+
};
|
|
10319
|
+
let retryTimer = null;
|
|
10320
|
+
const schedule = () => {
|
|
10321
|
+
if (stopped)
|
|
10322
|
+
return;
|
|
10323
|
+
const now = Date.now();
|
|
10324
|
+
firstPendingAt ??= now;
|
|
10325
|
+
if (timer)
|
|
10326
|
+
clearTimeout(timer);
|
|
10327
|
+
const delay = Math.max(0, Math.min(debounceMs, firstPendingAt + CONFIG_WATCH_MAX_DELAY_MS - now));
|
|
10328
|
+
timer = setTimeout(check, delay);
|
|
10329
|
+
timer.unref?.();
|
|
10330
|
+
};
|
|
10331
|
+
function revalidate() {
|
|
10332
|
+
const wanted = new Set(options.paths.map(watchDirFor));
|
|
10333
|
+
let moved = false;
|
|
10334
|
+
for (const [dir, entry] of watchers) {
|
|
10335
|
+
if (!wanted.has(dir) || entry.stale || identityOf(dir) !== entry.identity) {
|
|
10336
|
+
entry.watcher.close();
|
|
10337
|
+
watchers.delete(dir);
|
|
10338
|
+
moved = true;
|
|
10339
|
+
}
|
|
10340
|
+
}
|
|
10341
|
+
for (const dir of wanted) {
|
|
10342
|
+
if (watchers.has(dir))
|
|
10343
|
+
continue;
|
|
10344
|
+
try {
|
|
10345
|
+
const identity = identityOf(dir);
|
|
10346
|
+
options.beforeWatchForTest?.(dir);
|
|
10347
|
+
const name = basename(dir);
|
|
10348
|
+
const watcher = watchImpl(dir, { persistent: false }, (event, filename) => {
|
|
10349
|
+
if (event === "rename" && filename === name) {
|
|
10350
|
+
const current = watchers.get(dir);
|
|
10351
|
+
if (current && current.watcher === watcher)
|
|
10352
|
+
current.stale = true;
|
|
10353
|
+
}
|
|
10354
|
+
schedule();
|
|
10355
|
+
});
|
|
10356
|
+
if (identityOf(dir) !== identity) {
|
|
10357
|
+
watcher.close();
|
|
10358
|
+
moved = true;
|
|
10359
|
+
continue;
|
|
10360
|
+
}
|
|
10361
|
+
const entry = { watcher, identity, stale: false };
|
|
10362
|
+
entry.watcher.on("error", () => {
|
|
10363
|
+
entry.watcher.close();
|
|
10364
|
+
if (watchers.get(dir) === entry)
|
|
10365
|
+
watchers.delete(dir);
|
|
10366
|
+
schedule();
|
|
10367
|
+
});
|
|
10368
|
+
watchers.set(dir, entry);
|
|
10369
|
+
moved = true;
|
|
10370
|
+
} catch {}
|
|
10371
|
+
}
|
|
10372
|
+
return moved;
|
|
10373
|
+
}
|
|
10374
|
+
revalidate();
|
|
10375
|
+
if (options.checkAtStart)
|
|
10376
|
+
check();
|
|
10377
|
+
const revalidateTimer = setInterval(() => {
|
|
10378
|
+
if (!stopped && revalidate())
|
|
10379
|
+
schedule();
|
|
10380
|
+
}, CONFIG_WATCH_REVALIDATE_MS);
|
|
10381
|
+
revalidateTimer.unref?.();
|
|
10382
|
+
return () => {
|
|
10383
|
+
stopped = true;
|
|
10384
|
+
if (timer)
|
|
10385
|
+
clearTimeout(timer);
|
|
10386
|
+
if (retryTimer)
|
|
10387
|
+
clearTimeout(retryTimer);
|
|
10388
|
+
clearInterval(revalidateTimer);
|
|
10389
|
+
for (const entry of watchers.values())
|
|
10390
|
+
entry.watcher.close();
|
|
10391
|
+
watchers.clear();
|
|
10392
|
+
};
|
|
10393
|
+
}
|
|
10394
|
+
function aftLiveSecurityKeys(keys) {
|
|
10395
|
+
const byName = new Map(keys.map((key) => [key.name, key]));
|
|
10396
|
+
const pick = (name) => {
|
|
10397
|
+
const key = byName.get(name);
|
|
10398
|
+
if (!key)
|
|
10399
|
+
throw new Error(`unknown live config key ${name}`);
|
|
10400
|
+
return key;
|
|
10401
|
+
};
|
|
10402
|
+
return [
|
|
10403
|
+
{
|
|
10404
|
+
key: pick("restrict_to_project_root"),
|
|
10405
|
+
loosens: (current, next) => current === true && next !== true
|
|
10406
|
+
},
|
|
10407
|
+
{
|
|
10408
|
+
key: pick("bash.host_fallback"),
|
|
10409
|
+
loosens: (current, next) => current !== true && next === true
|
|
10410
|
+
}
|
|
10411
|
+
];
|
|
10412
|
+
}
|
|
10413
|
+
function liveConfigReloadLogLine(applied, deferred) {
|
|
10414
|
+
let line = "config reload";
|
|
10415
|
+
if (applied.length > 0)
|
|
10416
|
+
line += ` applied=[${applied.join(",")}]`;
|
|
10417
|
+
if (deferred.length > 0) {
|
|
10418
|
+
line += ` deferred=[${deferred.join(",")}] (deferred keys apply on next connect/restart)`;
|
|
10419
|
+
}
|
|
10420
|
+
return line;
|
|
10421
|
+
}
|
|
10422
|
+
function startLiveConfigReload(options) {
|
|
10423
|
+
const baseline = options.getConfig();
|
|
10424
|
+
let lastError = null;
|
|
10425
|
+
let acceptedSources = new Set(options.initialSources);
|
|
10426
|
+
let acceptedProjectText = options.initialProjectText ?? null;
|
|
10427
|
+
let acceptedTexts;
|
|
10428
|
+
const reload = () => {
|
|
10429
|
+
let loaded = options.load();
|
|
10430
|
+
if (loaded.ok) {
|
|
10431
|
+
const read = new Set(loaded.sources);
|
|
10432
|
+
const deleted = [...acceptedSources].find((path) => !read.has(path));
|
|
10433
|
+
if (deleted !== undefined) {
|
|
10434
|
+
loaded = { ok: false, message: `AFT config at ${deleted} was deleted` };
|
|
10435
|
+
} else {
|
|
10436
|
+
acceptedSources = read;
|
|
10437
|
+
}
|
|
10438
|
+
}
|
|
10439
|
+
if (!loaded.ok) {
|
|
10440
|
+
const message = `${loaded.message.trim().replace(/[.!?]?$/, ".")} ${CONFIG_LIVE_KEEP_NOTE}`;
|
|
10441
|
+
if (message !== lastError) {
|
|
10442
|
+
lastError = message;
|
|
10443
|
+
options.reportError(message);
|
|
10444
|
+
}
|
|
10445
|
+
return null;
|
|
10446
|
+
}
|
|
10447
|
+
lastError = null;
|
|
10448
|
+
acceptedTexts = loaded.texts;
|
|
10449
|
+
const current = options.getConfig();
|
|
10450
|
+
let next = loaded.config;
|
|
10451
|
+
const held = [];
|
|
10452
|
+
const projectText = loaded.projectText ?? null;
|
|
10453
|
+
if (loaded.projectText !== undefined && projectText !== acceptedProjectText) {
|
|
10454
|
+
for (const security of options.securityKeys ?? []) {
|
|
10455
|
+
const now = security.key.read(current);
|
|
10456
|
+
if (security.loosens(now, security.key.read(next))) {
|
|
10457
|
+
next = security.key.write(next, now);
|
|
10458
|
+
held.push(security.key.name);
|
|
10459
|
+
}
|
|
10460
|
+
}
|
|
10461
|
+
if (held.length === 0)
|
|
10462
|
+
acceptedProjectText = projectText;
|
|
10463
|
+
}
|
|
10464
|
+
const result = applyLiveConfigKeys(current, next, options.keys, baseline);
|
|
10465
|
+
if (result.applied.length > 0)
|
|
10466
|
+
options.setConfig(result.config);
|
|
10467
|
+
if (result.applied.length > 0 || result.deferred.length > 0 || held.length > 0) {
|
|
10468
|
+
let line = liveConfigReloadLogLine(result.applied, result.deferred);
|
|
10469
|
+
if (held.length > 0) {
|
|
10470
|
+
line += ` held=[${held.join(",")}] (not loosened while the project file differs from the one the published values came from; the next restart applies them)`;
|
|
10471
|
+
}
|
|
10472
|
+
options.log(line);
|
|
10473
|
+
}
|
|
10474
|
+
return { ...result, held };
|
|
10475
|
+
};
|
|
10476
|
+
const safeReload = () => {
|
|
10477
|
+
try {
|
|
10478
|
+
acceptedTexts = undefined;
|
|
10479
|
+
if (reload() === null)
|
|
10480
|
+
return false;
|
|
10481
|
+
const texts = acceptedTexts;
|
|
10482
|
+
if (!texts)
|
|
10483
|
+
return true;
|
|
10484
|
+
return new Map(options.paths.map((path) => [path, texts[path] ?? null]));
|
|
10485
|
+
} catch (err) {
|
|
10486
|
+
options.reportError(`AFT config reload failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10487
|
+
return false;
|
|
10488
|
+
}
|
|
10489
|
+
};
|
|
10490
|
+
if (options.watch === false) {
|
|
10491
|
+
return { reload, stop: () => {} };
|
|
10492
|
+
}
|
|
10493
|
+
const stop = watchAftConfigFiles({
|
|
10494
|
+
paths: options.paths,
|
|
10495
|
+
debounceMs: options.debounceMs,
|
|
10496
|
+
onChange: safeReload,
|
|
10497
|
+
initialTexts: options.initialTexts,
|
|
10498
|
+
checkAtStart: true
|
|
10499
|
+
});
|
|
10500
|
+
return { reload, stop };
|
|
10501
|
+
}
|
|
10124
10502
|
// ../aft-bridge/dist/downloader.js
|
|
10125
10503
|
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
10126
|
-
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as existsSync3, mkdirSync, openSync, readdirSync, readFileSync as
|
|
10504
|
+
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as existsSync3, mkdirSync, openSync, readdirSync, readFileSync as readFileSync4, renameSync as renameSync2, rmSync, statSync as statSync4, unlinkSync as unlinkSync2, writeSync } from "node:fs";
|
|
10127
10505
|
import { hostname } from "node:os";
|
|
10128
10506
|
import { join as join7 } from "node:path";
|
|
10129
10507
|
import { Readable } from "node:stream";
|
|
@@ -10475,7 +10853,7 @@ function isReclaimableDownloadLock(owner, ageMs, staleMs) {
|
|
|
10475
10853
|
}
|
|
10476
10854
|
function reclaimDownloadLock(lockPath, expectedOwner) {
|
|
10477
10855
|
try {
|
|
10478
|
-
if (
|
|
10856
|
+
if (readFileSync4(lockPath, "utf-8") !== expectedOwner)
|
|
10479
10857
|
return false;
|
|
10480
10858
|
rmSync(lockPath, { force: true });
|
|
10481
10859
|
return true;
|
|
@@ -10493,7 +10871,7 @@ function sweepStaleDownloadTemps(versionedCacheDir, binaryName) {
|
|
|
10493
10871
|
continue;
|
|
10494
10872
|
}
|
|
10495
10873
|
const tempPath = join7(versionedCacheDir, entry.name);
|
|
10496
|
-
const ageMs = Date.now() -
|
|
10874
|
+
const ageMs = Date.now() - statSync4(tempPath).mtimeMs;
|
|
10497
10875
|
if (Math.abs(ageMs) > DOWNLOAD_LOCK_STALE_MS)
|
|
10498
10876
|
unlinkSync2(tempPath);
|
|
10499
10877
|
}
|
|
@@ -10515,7 +10893,7 @@ async function acquireDownloadLock(lockPath, timing = {}) {
|
|
|
10515
10893
|
}
|
|
10516
10894
|
return () => {
|
|
10517
10895
|
try {
|
|
10518
|
-
if (
|
|
10896
|
+
if (readFileSync4(lockPath, "utf-8") === owner) {
|
|
10519
10897
|
rmSync(lockPath, { force: true });
|
|
10520
10898
|
}
|
|
10521
10899
|
} catch {}
|
|
@@ -10527,8 +10905,8 @@ async function acquireDownloadLock(lockPath, timing = {}) {
|
|
|
10527
10905
|
let existingOwner;
|
|
10528
10906
|
let ageMs;
|
|
10529
10907
|
try {
|
|
10530
|
-
existingOwner =
|
|
10531
|
-
ageMs = Date.now() -
|
|
10908
|
+
existingOwner = readFileSync4(lockPath, "utf-8");
|
|
10909
|
+
ageMs = Date.now() - statSync4(lockPath).mtimeMs;
|
|
10532
10910
|
} catch (readErr) {
|
|
10533
10911
|
if (readErr.code === "ENOENT")
|
|
10534
10912
|
continue;
|
|
@@ -10578,7 +10956,7 @@ async function fetchLatestTag() {
|
|
|
10578
10956
|
}
|
|
10579
10957
|
// ../aft-bridge/dist/durable-log.js
|
|
10580
10958
|
import { appendFile, chmod, mkdir, rename, rm, stat } from "node:fs/promises";
|
|
10581
|
-
import { dirname } from "node:path";
|
|
10959
|
+
import { dirname as dirname2 } from "node:path";
|
|
10582
10960
|
var DEFAULT_LOG_BYTES = 32 * 1024 * 1024;
|
|
10583
10961
|
var DEFAULT_LOG_GENERATIONS = 1;
|
|
10584
10962
|
var LOG_DIR_MODE = 448;
|
|
@@ -10591,6 +10969,10 @@ class RotatingLogSink {
|
|
|
10591
10969
|
queue = Promise.resolve();
|
|
10592
10970
|
disabled = false;
|
|
10593
10971
|
failureReported = false;
|
|
10972
|
+
queuedBytes = 0;
|
|
10973
|
+
queuedRecords = 0;
|
|
10974
|
+
droppedBytes = 0;
|
|
10975
|
+
overflowQueued = false;
|
|
10594
10976
|
constructor(path, options = {}) {
|
|
10595
10977
|
this.path = path;
|
|
10596
10978
|
this.maxBytes = options.maxBytes ?? DEFAULT_LOG_BYTES;
|
|
@@ -10599,7 +10981,34 @@ class RotatingLogSink {
|
|
|
10599
10981
|
append(data) {
|
|
10600
10982
|
if (this.disabled || data.length === 0)
|
|
10601
10983
|
return;
|
|
10602
|
-
|
|
10984
|
+
const bytes = Buffer.byteLength(data);
|
|
10985
|
+
const overflow = this.queuedBytes + bytes > 1024 * 1024 || this.queuedRecords >= 4096;
|
|
10986
|
+
if (overflow) {
|
|
10987
|
+
this.droppedBytes += bytes;
|
|
10988
|
+
if (this.overflowQueued)
|
|
10989
|
+
return;
|
|
10990
|
+
this.overflowQueued = true;
|
|
10991
|
+
data = "";
|
|
10992
|
+
} else {
|
|
10993
|
+
this.queuedBytes += bytes;
|
|
10994
|
+
this.queuedRecords += 1;
|
|
10995
|
+
}
|
|
10996
|
+
this.queue = this.queue.then(async () => {
|
|
10997
|
+
if (overflow) {
|
|
10998
|
+
const dropped = this.droppedBytes;
|
|
10999
|
+
this.droppedBytes = 0;
|
|
11000
|
+
this.overflowQueued = false;
|
|
11001
|
+
await this.write(`[aft-plugin] durable log queue overflow: dropped ${dropped} bytes (1MiB/4096-record pending limit); reduce diagnostic volume.
|
|
11002
|
+
`);
|
|
11003
|
+
} else {
|
|
11004
|
+
try {
|
|
11005
|
+
await this.write(data);
|
|
11006
|
+
} finally {
|
|
11007
|
+
this.queuedBytes -= bytes;
|
|
11008
|
+
this.queuedRecords -= 1;
|
|
11009
|
+
}
|
|
11010
|
+
}
|
|
11011
|
+
}).catch((error) => {
|
|
10603
11012
|
this.disabled = true;
|
|
10604
11013
|
if (!this.failureReported) {
|
|
10605
11014
|
this.failureReported = true;
|
|
@@ -10614,8 +11023,8 @@ class RotatingLogSink {
|
|
|
10614
11023
|
await this.queue;
|
|
10615
11024
|
}
|
|
10616
11025
|
async write(data) {
|
|
10617
|
-
const dir =
|
|
10618
|
-
await mkdir(
|
|
11026
|
+
const dir = dirname2(this.path);
|
|
11027
|
+
await mkdir(dirname2(dir), { recursive: true });
|
|
10619
11028
|
try {
|
|
10620
11029
|
await mkdir(dir, { mode: LOG_DIR_MODE });
|
|
10621
11030
|
} catch (error) {
|
|
@@ -12403,7 +12812,7 @@ function reverseRequestMethod(body) {
|
|
|
12403
12812
|
}
|
|
12404
12813
|
}
|
|
12405
12814
|
// ../aft-bridge/dist/subc-transport.js
|
|
12406
|
-
import { existsSync as existsSync4, statSync as
|
|
12815
|
+
import { existsSync as existsSync4, statSync as statSync5 } from "node:fs";
|
|
12407
12816
|
|
|
12408
12817
|
// ../aft-bridge/dist/lifecycle-registry.js
|
|
12409
12818
|
import { lstat } from "node:fs/promises";
|
|
@@ -12930,6 +13339,7 @@ var RECONNECT_RETRY_FLOOR_MS = 100;
|
|
|
12930
13339
|
var RECONNECT_RETRY_CAP_MS = 2000;
|
|
12931
13340
|
var SUBC_DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
12932
13341
|
var ROUTE_OPEN_RELOAD_WAIT_CEILING_MS = 45000;
|
|
13342
|
+
var CALL_DEADLINE_EXPIRED = Symbol("call deadline expired");
|
|
12933
13343
|
function reloadWaitExhaustedSuffix(callDeadlineMs) {
|
|
12934
13344
|
if (callDeadlineMs > ROUTE_OPEN_RELOAD_WAIT_CEILING_MS) {
|
|
12935
13345
|
const ceilingSeconds = ROUTE_OPEN_RELOAD_WAIT_CEILING_MS / 1000;
|
|
@@ -13282,7 +13692,16 @@ function absentRootError(root) {
|
|
|
13282
13692
|
return new SubcError(`invalid route project root: project root does not exist: ${root}`, "config_divergence");
|
|
13283
13693
|
}
|
|
13284
13694
|
function reloadWindowExhaustedError(error, callDeadlineMs) {
|
|
13285
|
-
|
|
13695
|
+
return withDeadlineSuffix(error, reloadWaitExhaustedSuffix(callDeadlineMs));
|
|
13696
|
+
}
|
|
13697
|
+
function callDeadlinePassedError(lastError, callDeadlineMs) {
|
|
13698
|
+
const seconds = Math.round(callDeadlineMs / 100) / 10;
|
|
13699
|
+
const suffix = ` The AFT daemon module did not return within this call's ${seconds}s deadline.`;
|
|
13700
|
+
if (lastError !== undefined)
|
|
13701
|
+
return withDeadlineSuffix(lastError, suffix);
|
|
13702
|
+
return new SubcError(`route to module '${AFT_MODULE_ID}' was not ready before the call ran out of time.${suffix}`, REQUEST_DEADLINE_CODE);
|
|
13703
|
+
}
|
|
13704
|
+
function withDeadlineSuffix(error, suffix) {
|
|
13286
13705
|
if (error instanceof Error) {
|
|
13287
13706
|
try {
|
|
13288
13707
|
error.message += suffix;
|
|
@@ -13521,7 +13940,7 @@ class SubcTransportPool {
|
|
|
13521
13940
|
rootCanAttach(root) {
|
|
13522
13941
|
let directoryExists = false;
|
|
13523
13942
|
try {
|
|
13524
|
-
directoryExists =
|
|
13943
|
+
directoryExists = statSync5(root).isDirectory();
|
|
13525
13944
|
} catch {}
|
|
13526
13945
|
if (directoryExists) {
|
|
13527
13946
|
this.dormantRoots.delete(root);
|
|
@@ -13861,6 +14280,7 @@ class SubcTransportPool {
|
|
|
13861
14280
|
return this.rootReapedError(record);
|
|
13862
14281
|
}
|
|
13863
14282
|
async routeRequest(identity, body, timeoutMs, onProgress, expectedGeneration, abortSignal) {
|
|
14283
|
+
const callStartedAt = performance.now();
|
|
13864
14284
|
const root = asCanonicalRootPath(identity.project_root);
|
|
13865
14285
|
let generation = expectedGeneration;
|
|
13866
14286
|
if (this.lifecycleEnabled()) {
|
|
@@ -13913,19 +14333,41 @@ class SubcTransportPool {
|
|
|
13913
14333
|
};
|
|
13914
14334
|
const callDeadlineMs = timeoutMs ?? SUBC_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
13915
14335
|
const reloadWaitBudgetMs = Math.min(callDeadlineMs, ROUTE_OPEN_RELOAD_WAIT_CEILING_MS);
|
|
13916
|
-
let
|
|
14336
|
+
let scheduledDelayMs = 0;
|
|
14337
|
+
let lastRefusal;
|
|
14338
|
+
const spentMs = () => Math.max(performance.now() - callStartedAt, scheduledDelayMs);
|
|
14339
|
+
const remainingMs = () => callDeadlineMs - spentMs();
|
|
14340
|
+
const openRouteWithinDeadline = async () => {
|
|
14341
|
+
const remaining = remainingMs();
|
|
14342
|
+
if (remaining <= 0)
|
|
14343
|
+
throw callDeadlinePassedError(lastRefusal, callDeadlineMs);
|
|
14344
|
+
let timer;
|
|
14345
|
+
const expired = new Promise((resolve) => {
|
|
14346
|
+
timer = setTimeout(() => resolve(CALL_DEADLINE_EXPIRED), remaining);
|
|
14347
|
+
});
|
|
14348
|
+
try {
|
|
14349
|
+
const opened = await Promise.race([openRoute(), expired]);
|
|
14350
|
+
if (opened === CALL_DEADLINE_EXPIRED) {
|
|
14351
|
+
throw callDeadlinePassedError(lastRefusal, callDeadlineMs);
|
|
14352
|
+
}
|
|
14353
|
+
return opened;
|
|
14354
|
+
} finally {
|
|
14355
|
+
clearTimeout(timer);
|
|
14356
|
+
}
|
|
14357
|
+
};
|
|
13917
14358
|
const openRouteAfterReloadWindow = async () => {
|
|
13918
14359
|
while (true) {
|
|
13919
14360
|
try {
|
|
13920
|
-
return await
|
|
14361
|
+
return await openRouteWithinDeadline();
|
|
13921
14362
|
} catch (error) {
|
|
13922
14363
|
if (!isRouteOpenReloadWindowError(error))
|
|
13923
14364
|
throw error;
|
|
13924
|
-
|
|
14365
|
+
lastRefusal = error;
|
|
14366
|
+
if (spentMs() + this.nextRouteReopenDelayMs() >= reloadWaitBudgetMs) {
|
|
13925
14367
|
throw reloadWindowExhaustedError(error, callDeadlineMs);
|
|
13926
14368
|
}
|
|
13927
14369
|
const { delayMs, wait } = this.waitForRouteReopenBackoff();
|
|
13928
|
-
|
|
14370
|
+
scheduledDelayMs = spentMs() + delayMs;
|
|
13929
14371
|
await wait;
|
|
13930
14372
|
}
|
|
13931
14373
|
}
|
|
@@ -13961,7 +14403,7 @@ class SubcTransportPool {
|
|
|
13961
14403
|
route: routeLabel(entry.handle)
|
|
13962
14404
|
});
|
|
13963
14405
|
};
|
|
13964
|
-
const requestOnRoute = async (route, entry) => {
|
|
14406
|
+
const requestOnRoute = async (route, entry, requestTimeoutMs) => {
|
|
13965
14407
|
this.assertRecordLive(record);
|
|
13966
14408
|
if (abortSignal?.aborted) {
|
|
13967
14409
|
clearRouteEntry(entry);
|
|
@@ -13977,8 +14419,10 @@ class SubcTransportPool {
|
|
|
13977
14419
|
};
|
|
13978
14420
|
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
13979
14421
|
try {
|
|
13980
|
-
const
|
|
13981
|
-
|
|
14422
|
+
const request = client.request(route, body, {
|
|
14423
|
+
timeoutMs: Math.ceil(requestTimeoutMs),
|
|
14424
|
+
onProgress
|
|
14425
|
+
});
|
|
13982
14426
|
const reply = abortSignal ? await Promise.race([request, aborted]) : await request;
|
|
13983
14427
|
if (!this.isCurrentSession(key, record)) {
|
|
13984
14428
|
if (this.isReapInduced(record))
|
|
@@ -13999,8 +14443,11 @@ class SubcTransportPool {
|
|
|
13999
14443
|
let reopened = false;
|
|
14000
14444
|
let retriedAbsentRoute = false;
|
|
14001
14445
|
while (true) {
|
|
14446
|
+
const requestTimeoutMs = remainingMs();
|
|
14447
|
+
if (requestTimeoutMs <= 0)
|
|
14448
|
+
throw callDeadlinePassedError(lastRefusal, callDeadlineMs);
|
|
14002
14449
|
try {
|
|
14003
|
-
const reply = await requestOnRoute(routeAndEntry.route, routeAndEntry.entry);
|
|
14450
|
+
const reply = await requestOnRoute(routeAndEntry.route, routeAndEntry.entry, requestTimeoutMs);
|
|
14004
14451
|
if (reopened)
|
|
14005
14452
|
this.resetRouteReopenBackoff();
|
|
14006
14453
|
return reply;
|
|
@@ -14010,11 +14457,12 @@ class SubcTransportPool {
|
|
|
14010
14457
|
const ownsRoute = this.isCurrentSession(key, record) && this.client === client;
|
|
14011
14458
|
if (ownsRoute && isRouteRequestReloadRefusal(error)) {
|
|
14012
14459
|
clearRouteEntry(routeAndEntry.entry);
|
|
14013
|
-
|
|
14460
|
+
lastRefusal = error;
|
|
14461
|
+
if (spentMs() + this.nextRouteReopenDelayMs() >= reloadWaitBudgetMs) {
|
|
14014
14462
|
throw reloadWindowExhaustedError(error, callDeadlineMs);
|
|
14015
14463
|
}
|
|
14016
14464
|
const { delayMs, wait } = this.waitForRouteReopenBackoff();
|
|
14017
|
-
|
|
14465
|
+
scheduledDelayMs = spentMs() + delayMs;
|
|
14018
14466
|
await wait;
|
|
14019
14467
|
routeAndEntry = await openRouteAfterReloadWindow();
|
|
14020
14468
|
reopened = true;
|
|
@@ -14023,7 +14471,12 @@ class SubcTransportPool {
|
|
|
14023
14471
|
if (ownsRoute && !retriedAbsentRoute && isRouteProvenAbsentError(error)) {
|
|
14024
14472
|
retriedAbsentRoute = true;
|
|
14025
14473
|
clearRouteEntry(routeAndEntry.entry);
|
|
14026
|
-
|
|
14474
|
+
if (spentMs() + this.nextRouteReopenDelayMs() >= callDeadlineMs) {
|
|
14475
|
+
throw callDeadlinePassedError(error, callDeadlineMs);
|
|
14476
|
+
}
|
|
14477
|
+
const { delayMs, wait } = this.waitForRouteReopenBackoff();
|
|
14478
|
+
scheduledDelayMs = spentMs() + delayMs;
|
|
14479
|
+
await wait;
|
|
14027
14480
|
routeAndEntry = await openRouteAfterReloadWindow();
|
|
14028
14481
|
reopened = true;
|
|
14029
14482
|
continue;
|
|
@@ -15846,14 +16299,14 @@ function shouldInterruptWaitsForMessage(detachOnUserMessage, operatorText) {
|
|
|
15846
16299
|
return detachOnUserMessage || containsStandaloneDetachKeyword(operatorText);
|
|
15847
16300
|
}
|
|
15848
16301
|
// ../aft-bridge/dist/migration.js
|
|
15849
|
-
import { closeSync as closeSync3, existsSync as existsSync8, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as
|
|
16302
|
+
import { closeSync as closeSync3, existsSync as existsSync8, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync2, statSync as statSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
15850
16303
|
import { homedir as homedir8, tmpdir as tmpdir2 } from "node:os";
|
|
15851
|
-
import { basename, dirname as
|
|
16304
|
+
import { basename as basename2, dirname as dirname5, join as join10, resolve as resolve6 } from "node:path";
|
|
15852
16305
|
|
|
15853
16306
|
// ../aft-bridge/dist/paths.js
|
|
15854
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as
|
|
16307
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
15855
16308
|
import { homedir as homedir6 } from "node:os";
|
|
15856
|
-
import { dirname as
|
|
16309
|
+
import { dirname as dirname3, isAbsolute as isAbsolute3, join as join8, resolve as resolve5 } from "node:path";
|
|
15857
16310
|
function homeDir3() {
|
|
15858
16311
|
if (process.platform === "win32")
|
|
15859
16312
|
return process.env.USERPROFILE || process.env.HOME || homedir6();
|
|
@@ -15913,7 +16366,7 @@ function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
|
15913
16366
|
if (existsSync6(harnessPath) || !existsSync6(rootPath))
|
|
15914
16367
|
return harnessPath;
|
|
15915
16368
|
try {
|
|
15916
|
-
mkdirSync2(
|
|
16369
|
+
mkdirSync2(dirname3(harnessPath), { recursive: true });
|
|
15917
16370
|
renameSync3(rootPath, harnessPath);
|
|
15918
16371
|
} catch {}
|
|
15919
16372
|
return harnessPath;
|
|
@@ -15925,7 +16378,7 @@ function shouldShowAnnouncement(storageRoot, harness, currentVersion) {
|
|
|
15925
16378
|
let lastVersion = "";
|
|
15926
16379
|
try {
|
|
15927
16380
|
if (existsSync6(versionFile)) {
|
|
15928
|
-
lastVersion =
|
|
16381
|
+
lastVersion = readFileSync5(versionFile, "utf-8").trim();
|
|
15929
16382
|
}
|
|
15930
16383
|
} catch {
|
|
15931
16384
|
return false;
|
|
@@ -15934,7 +16387,7 @@ function shouldShowAnnouncement(storageRoot, harness, currentVersion) {
|
|
|
15934
16387
|
return false;
|
|
15935
16388
|
if (!lastVersion) {
|
|
15936
16389
|
try {
|
|
15937
|
-
mkdirSync2(
|
|
16390
|
+
mkdirSync2(dirname3(versionFile), { recursive: true });
|
|
15938
16391
|
writeFileSync2(versionFile, currentVersion);
|
|
15939
16392
|
} catch {}
|
|
15940
16393
|
return false;
|
|
@@ -15946,7 +16399,7 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
15946
16399
|
return;
|
|
15947
16400
|
const versionFile = repairRootScopedStorageFile(storageRoot, harness, "last_announced_version");
|
|
15948
16401
|
try {
|
|
15949
|
-
mkdirSync2(
|
|
16402
|
+
mkdirSync2(dirname3(versionFile), { recursive: true });
|
|
15950
16403
|
writeFileSync2(versionFile, currentVersion);
|
|
15951
16404
|
} catch {}
|
|
15952
16405
|
}
|
|
@@ -15995,10 +16448,10 @@ function decodeFileUrl(target) {
|
|
|
15995
16448
|
}
|
|
15996
16449
|
|
|
15997
16450
|
// ../aft-bridge/dist/resolver.js
|
|
15998
|
-
import { closeSync as closeSync2, existsSync as existsSync7, promises as fsPromises, openSync as openSync2, readFileSync as
|
|
16451
|
+
import { closeSync as closeSync2, existsSync as existsSync7, promises as fsPromises, openSync as openSync2, readFileSync as readFileSync6, readSync } from "node:fs";
|
|
15999
16452
|
import { createRequire } from "node:module";
|
|
16000
16453
|
import { homedir as homedir7 } from "node:os";
|
|
16001
|
-
import { delimiter, dirname as
|
|
16454
|
+
import { delimiter, dirname as dirname4, isAbsolute as isAbsolute4, join as join9 } from "node:path";
|
|
16002
16455
|
var ensureBinaryForResolver = ensureBinary;
|
|
16003
16456
|
var npmPlatformPackageReader = null;
|
|
16004
16457
|
var cacheCopiesInFlight = new Map;
|
|
@@ -16151,8 +16604,8 @@ function npmPlatformPackage(ext) {
|
|
|
16151
16604
|
try {
|
|
16152
16605
|
const req = createRequire(import.meta.url);
|
|
16153
16606
|
const manifestPath = req.resolve(`@cortexkit/aft-${platformKey()}/package.json`);
|
|
16154
|
-
const manifest = JSON.parse(
|
|
16155
|
-
const binaryPath = join9(
|
|
16607
|
+
const manifest = JSON.parse(readFileSync6(manifestPath, "utf8"));
|
|
16608
|
+
const binaryPath = join9(dirname4(manifestPath), "bin", `aft${ext}`);
|
|
16156
16609
|
if (typeof manifest.version !== "string" || !existsSync7(binaryPath))
|
|
16157
16610
|
return null;
|
|
16158
16611
|
return { binaryPath, version: normalizeBareVersion(manifest.version) };
|
|
@@ -16406,7 +16859,7 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
16406
16859
|
if (code !== "EEXIST")
|
|
16407
16860
|
throw err;
|
|
16408
16861
|
try {
|
|
16409
|
-
const ageMs = Date.now() -
|
|
16862
|
+
const ageMs = Date.now() - statSync6(lockDir).mtimeMs;
|
|
16410
16863
|
if (ageMs > 60000) {
|
|
16411
16864
|
rmSync2(lockDir, { recursive: true, force: true });
|
|
16412
16865
|
continue;
|
|
@@ -16420,12 +16873,12 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
16420
16873
|
}
|
|
16421
16874
|
}
|
|
16422
16875
|
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
16423
|
-
mkdirSync3(
|
|
16424
|
-
const tmpPath = join10(
|
|
16876
|
+
mkdirSync3(dirname5(targetPath), { recursive: true });
|
|
16877
|
+
const tmpPath = join10(dirname5(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
16425
16878
|
let fd = null;
|
|
16426
16879
|
try {
|
|
16427
16880
|
fd = openSync3(tmpPath, "wx", 384);
|
|
16428
|
-
writeFileSync3(fd,
|
|
16881
|
+
writeFileSync3(fd, readFileSync7(sourcePath));
|
|
16429
16882
|
closeSync3(fd);
|
|
16430
16883
|
fd = null;
|
|
16431
16884
|
renameSync4(tmpPath, targetPath);
|
|
@@ -16442,8 +16895,8 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
16442
16895
|
}
|
|
16443
16896
|
}
|
|
16444
16897
|
function atomicWriteConfigFile(targetPath, content) {
|
|
16445
|
-
mkdirSync3(
|
|
16446
|
-
const tmpPath = join10(
|
|
16898
|
+
mkdirSync3(dirname5(targetPath), { recursive: true });
|
|
16899
|
+
const tmpPath = join10(dirname5(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
16447
16900
|
let fd = null;
|
|
16448
16901
|
try {
|
|
16449
16902
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -16504,11 +16957,11 @@ function markLegacySourcesMovedAside(sources, targetPath, logger) {
|
|
|
16504
16957
|
const desiredMarkerPath = `${source.path}${MOVED_MARKER_SUFFIX}`;
|
|
16505
16958
|
const markerPath = nonClobberingSidecarPath(desiredMarkerPath);
|
|
16506
16959
|
try {
|
|
16507
|
-
const original =
|
|
16960
|
+
const original = readFileSync7(source.path, "utf-8");
|
|
16508
16961
|
if (markerPath !== desiredMarkerPath) {
|
|
16509
16962
|
logger?.warn?.(`Preserving existing legacy AFT marker ${desiredMarkerPath}; writing new marker to ${markerPath}`);
|
|
16510
16963
|
}
|
|
16511
|
-
atomicWriteConfigFile(markerPath, movedMarkerContent(targetPath,
|
|
16964
|
+
atomicWriteConfigFile(markerPath, movedMarkerContent(targetPath, basename2(source.path), original));
|
|
16512
16965
|
unlinkSync3(source.path);
|
|
16513
16966
|
info?.(`Moved legacy AFT config ${source.path} aside to ${markerPath}; AFT now reads ${targetPath}`);
|
|
16514
16967
|
} catch (err) {
|
|
@@ -16568,15 +17021,15 @@ function migrateAftConfigFile(opts) {
|
|
|
16568
17021
|
if (existingSources.length === 0) {
|
|
16569
17022
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
16570
17023
|
}
|
|
16571
|
-
mkdirSync3(
|
|
17024
|
+
mkdirSync3(dirname5(opts.targetPath), { recursive: true });
|
|
16572
17025
|
const release = acquireConfigMigrationLock(`${opts.targetPath}.lock`);
|
|
16573
17026
|
try {
|
|
16574
17027
|
const sources = existingSources.map((source) => ({
|
|
16575
17028
|
...source,
|
|
16576
|
-
content:
|
|
17029
|
+
content: readFileSync7(source.path, "utf-8")
|
|
16577
17030
|
}));
|
|
16578
17031
|
if (existsSync8(opts.targetPath)) {
|
|
16579
|
-
const targetContent =
|
|
17032
|
+
const targetContent = readFileSync7(opts.targetPath, "utf-8");
|
|
16580
17033
|
for (const source of sources) {
|
|
16581
17034
|
if (fileSemanticsMatch(source.content, targetContent))
|
|
16582
17035
|
continue;
|
|
@@ -16627,11 +17080,11 @@ function spawnErrorLabel(error) {
|
|
|
16627
17080
|
function migrationLogPath(newRoot, harness, logger) {
|
|
16628
17081
|
const desired = join10(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
16629
17082
|
try {
|
|
16630
|
-
mkdirSync3(
|
|
17083
|
+
mkdirSync3(dirname5(desired), { recursive: true });
|
|
16631
17084
|
return desired;
|
|
16632
17085
|
} catch (err) {
|
|
16633
17086
|
const fallback = join10(tmpdir2(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
16634
|
-
logger?.warn?.(`Failed to create AFT migration log directory ${
|
|
17087
|
+
logger?.warn?.(`Failed to create AFT migration log directory ${dirname5(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
16635
17088
|
return fallback;
|
|
16636
17089
|
}
|
|
16637
17090
|
}
|
|
@@ -16692,9 +17145,9 @@ async function ensureStorageMigrated(opts) {
|
|
|
16692
17145
|
throw new Error(`AFT storage migration failed (${detail}). ` + `Harness: ${opts.harness}. Legacy: ${legacyRoot}. Target: ${newRoot}. ` + `See log: ${logPath}. ` + `Plugin load aborted to prevent legacy/new state divergence.` + (stderrTail ? ` Stderr tail: ${stderrTail}` : "") + (stdoutTail ? ` Stdout tail: ${stdoutTail}` : ""));
|
|
16693
17146
|
}
|
|
16694
17147
|
// ../aft-bridge/dist/migration-notices.js
|
|
16695
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
17148
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync as renameSync5, rmdirSync, statSync as statSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
16696
17149
|
import { homedir as homedir9 } from "node:os";
|
|
16697
|
-
import { dirname as
|
|
17150
|
+
import { dirname as dirname6, join as join11, resolve as resolve7 } from "node:path";
|
|
16698
17151
|
function migrationNoticeStorePath(env = process.env) {
|
|
16699
17152
|
const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME : join11(homedir9(), ".local", "state");
|
|
16700
17153
|
return join11(stateHome, "cortexkit", "aft", "migration-notices.json");
|
|
@@ -16704,7 +17157,7 @@ function noticeKey(configPath, digest) {
|
|
|
16704
17157
|
}
|
|
16705
17158
|
function readRecords(storePath) {
|
|
16706
17159
|
try {
|
|
16707
|
-
const parsed = JSON.parse(
|
|
17160
|
+
const parsed = JSON.parse(readFileSync8(storePath, "utf8"));
|
|
16708
17161
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
16709
17162
|
} catch {
|
|
16710
17163
|
return {};
|
|
@@ -16713,7 +17166,7 @@ function readRecords(storePath) {
|
|
|
16713
17166
|
var LOCK_STALE_MS = 1e4;
|
|
16714
17167
|
function withStoreLock(storePath, action) {
|
|
16715
17168
|
const lockPath = `${storePath}.lock`;
|
|
16716
|
-
mkdirSync4(
|
|
17169
|
+
mkdirSync4(dirname6(storePath), { recursive: true });
|
|
16717
17170
|
const deadline = Date.now() + 2000;
|
|
16718
17171
|
for (;; ) {
|
|
16719
17172
|
try {
|
|
@@ -16723,7 +17176,7 @@ function withStoreLock(storePath, action) {
|
|
|
16723
17176
|
if (error.code !== "EEXIST")
|
|
16724
17177
|
throw error;
|
|
16725
17178
|
try {
|
|
16726
|
-
if (Date.now() -
|
|
17179
|
+
if (Date.now() - statSync7(lockPath).mtimeMs > LOCK_STALE_MS)
|
|
16727
17180
|
rmdirSync(lockPath);
|
|
16728
17181
|
} catch {}
|
|
16729
17182
|
if (Date.now() > deadline)
|
|
@@ -16764,9 +17217,9 @@ function deliverMigrationNoticeOnce(options) {
|
|
|
16764
17217
|
}
|
|
16765
17218
|
}
|
|
16766
17219
|
// ../aft-bridge/dist/npm-resolver.js
|
|
16767
|
-
import { readdirSync as readdirSync2, statSync as
|
|
17220
|
+
import { readdirSync as readdirSync2, statSync as statSync8 } from "node:fs";
|
|
16768
17221
|
import { homedir as homedir10 } from "node:os";
|
|
16769
|
-
import { dirname as
|
|
17222
|
+
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join12 } from "node:path";
|
|
16770
17223
|
function defaultDeps() {
|
|
16771
17224
|
return {
|
|
16772
17225
|
platform: process.platform,
|
|
@@ -16780,7 +17233,7 @@ function npmBinaryName(platform) {
|
|
|
16780
17233
|
}
|
|
16781
17234
|
function isFile(p) {
|
|
16782
17235
|
try {
|
|
16783
|
-
return
|
|
17236
|
+
return statSync8(p).isFile();
|
|
16784
17237
|
} catch {
|
|
16785
17238
|
return false;
|
|
16786
17239
|
}
|
|
@@ -16801,7 +17254,7 @@ function npmFromPath(deps) {
|
|
|
16801
17254
|
return null;
|
|
16802
17255
|
}
|
|
16803
17256
|
function npmAdjacentToNode(deps) {
|
|
16804
|
-
const dir =
|
|
17257
|
+
const dir = dirname7(deps.execPath);
|
|
16805
17258
|
return isFile(join12(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
16806
17259
|
}
|
|
16807
17260
|
function highestVersionedNodeBin(installsDir, name) {
|
|
@@ -17189,8 +17642,8 @@ function probeOnnxRuntimeLoadable(libPath, arch = process.arch) {
|
|
|
17189
17642
|
}
|
|
17190
17643
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
17191
17644
|
import { createHash as createHash5, randomBytes as randomBytes2 } from "node:crypto";
|
|
17192
|
-
import { chmodSync as chmodSync2, closeSync as closeSync5, copyFileSync as copyFileSync2, createWriteStream as createWriteStream2, existsSync as existsSync11, lstatSync, mkdirSync as mkdirSync5, openSync as openSync5, readdirSync as readdirSync3, readFileSync as
|
|
17193
|
-
import { basename as
|
|
17645
|
+
import { chmodSync as chmodSync2, closeSync as closeSync5, copyFileSync as copyFileSync2, createWriteStream as createWriteStream2, existsSync as existsSync11, lstatSync, mkdirSync as mkdirSync5, openSync as openSync5, readdirSync as readdirSync3, readFileSync as readFileSync9, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync6, rmSync as rmSync3, statSync as statSync9, symlinkSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
17646
|
+
import { basename as basename3, dirname as dirname8, isAbsolute as isAbsolute6, join as join14, relative as relative2, resolve as resolve8, win32 } from "node:path";
|
|
17194
17647
|
import { Readable as Readable2 } from "node:stream";
|
|
17195
17648
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
17196
17649
|
|
|
@@ -17397,7 +17850,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
17397
17850
|
abandoned = true;
|
|
17398
17851
|
} else {
|
|
17399
17852
|
try {
|
|
17400
|
-
const ageMs = Date.now() -
|
|
17853
|
+
const ageMs = Date.now() - statSync9(stagingDir).mtimeMs;
|
|
17401
17854
|
abandoned = ageMs > STALE_LOCK_MS;
|
|
17402
17855
|
} catch {
|
|
17403
17856
|
abandoned = true;
|
|
@@ -17434,7 +17887,7 @@ var REQUIRED_ORT_MAJOR = 1;
|
|
|
17434
17887
|
var REQUIRED_ORT_MIN_MINOR = 20;
|
|
17435
17888
|
var INVALID_ORT_VERSION = "<invalid>";
|
|
17436
17889
|
function parseOnnxVersionFromPath(value) {
|
|
17437
|
-
const name =
|
|
17890
|
+
const name = basename3(value);
|
|
17438
17891
|
const semverish = name.match(/(?:^|[._-])(\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?)(?:\.(?:dylib|dll))?$/);
|
|
17439
17892
|
if (semverish)
|
|
17440
17893
|
return semverish[1].split(/[-+]/, 1)[0];
|
|
@@ -17639,7 +18092,7 @@ async function downloadFileWithCap(url, destPath) {
|
|
|
17639
18092
|
if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES2) {
|
|
17640
18093
|
throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES2}`);
|
|
17641
18094
|
}
|
|
17642
|
-
mkdirSync5(
|
|
18095
|
+
mkdirSync5(dirname8(destPath), { recursive: true });
|
|
17643
18096
|
let bytesWritten = 0;
|
|
17644
18097
|
const guard = new TransformStream({
|
|
17645
18098
|
transform(chunk, transformController) {
|
|
@@ -17673,7 +18126,7 @@ function validateExtractedTree(stagingRoot) {
|
|
|
17673
18126
|
const lst = lstatSync(fullPath);
|
|
17674
18127
|
if (lst.isSymbolicLink()) {
|
|
17675
18128
|
const linkTarget = readlinkSync(fullPath);
|
|
17676
|
-
const resolvedTarget = resolve8(
|
|
18129
|
+
const resolvedTarget = resolve8(dirname8(fullPath), linkTarget);
|
|
17677
18130
|
const rel = relative2(realRoot, resolvedTarget);
|
|
17678
18131
|
if (rel.startsWith("..") || isAbsolute6(rel) || win32.isAbsolute(rel)) {
|
|
17679
18132
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
@@ -17809,7 +18262,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
17809
18262
|
unlinkSync4(dst);
|
|
17810
18263
|
} catch {}
|
|
17811
18264
|
const dstForContainment = join14(targetRoot, link.name);
|
|
17812
|
-
const resolvedTarget = resolve8(
|
|
18265
|
+
const resolvedTarget = resolve8(dirname8(dstForContainment), link.target);
|
|
17813
18266
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
17814
18267
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
17815
18268
|
if (requiredLibs.has(link.name)) {
|
|
@@ -17861,9 +18314,9 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
17861
18314
|
function readOnnxInstalledMeta(installDir) {
|
|
17862
18315
|
const path = join14(installDir, ONNX_INSTALLED_META_FILE);
|
|
17863
18316
|
try {
|
|
17864
|
-
if (!
|
|
18317
|
+
if (!statSync9(path).isFile())
|
|
17865
18318
|
return null;
|
|
17866
|
-
const raw =
|
|
18319
|
+
const raw = readFileSync9(path, "utf8");
|
|
17867
18320
|
const parsed = JSON.parse(raw);
|
|
17868
18321
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
17869
18322
|
return null;
|
|
@@ -17879,7 +18332,7 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
17879
18332
|
}
|
|
17880
18333
|
function sha256File2(path) {
|
|
17881
18334
|
const hash = createHash5("sha256");
|
|
17882
|
-
hash.update(
|
|
18335
|
+
hash.update(readFileSync9(path));
|
|
17883
18336
|
return hash.digest("hex");
|
|
17884
18337
|
}
|
|
17885
18338
|
function acquireLock(lockPath) {
|
|
@@ -17907,12 +18360,12 @@ ${new Date().toISOString()}
|
|
|
17907
18360
|
let owningPid = null;
|
|
17908
18361
|
let lockMtimeMs = 0;
|
|
17909
18362
|
try {
|
|
17910
|
-
const raw =
|
|
18363
|
+
const raw = readFileSync9(lockPath, "utf8");
|
|
17911
18364
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
17912
18365
|
const parsed = Number.parseInt(firstLine, 10);
|
|
17913
18366
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
17914
18367
|
owningPid = parsed;
|
|
17915
|
-
lockMtimeMs =
|
|
18368
|
+
lockMtimeMs = statSync9(lockPath).mtimeMs;
|
|
17916
18369
|
} catch {
|
|
17917
18370
|
return tryClaim();
|
|
17918
18371
|
}
|
|
@@ -17932,7 +18385,7 @@ function releaseLock(lockPath) {
|
|
|
17932
18385
|
try {
|
|
17933
18386
|
let owningPid = null;
|
|
17934
18387
|
try {
|
|
17935
|
-
const raw =
|
|
18388
|
+
const raw = readFileSync9(lockPath, "utf8");
|
|
17936
18389
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
17937
18390
|
const parsed = Number.parseInt(firstLine, 10);
|
|
17938
18391
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -18623,7 +19076,7 @@ function formatSemanticIndexStatus(status, stage, error, backend) {
|
|
|
18623
19076
|
return status;
|
|
18624
19077
|
}
|
|
18625
19078
|
// src/config.ts
|
|
18626
|
-
import { existsSync as existsSync12, readFileSync as
|
|
19079
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, renameSync as renameSync7, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
18627
19080
|
import { homedir as homedir11 } from "node:os";
|
|
18628
19081
|
import { isAbsolute as isAbsolute7, parse as parsePath, resolve as resolvePath } from "node:path";
|
|
18629
19082
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
@@ -23466,6 +23919,17 @@ var SemanticConfigSchema = object({
|
|
|
23466
23919
|
max_input_tokens: number2().int().positive().optional(),
|
|
23467
23920
|
max_files: number2().int().positive().optional()
|
|
23468
23921
|
});
|
|
23922
|
+
var RerankConfigSchema = object({
|
|
23923
|
+
backend: _enum(["off", "onnx", "remote", "synapse"]).optional(),
|
|
23924
|
+
model: string2().trim().min(1).optional(),
|
|
23925
|
+
endpoint: string2().trim().min(1).optional(),
|
|
23926
|
+
api_key_env: string2().trim().min(1).optional(),
|
|
23927
|
+
top_n: number2().int().positive().optional(),
|
|
23928
|
+
timeout_ms: number2().int().positive().optional()
|
|
23929
|
+
});
|
|
23930
|
+
var SearchConfigSchema = object({
|
|
23931
|
+
rerank: RerankConfigSchema.optional()
|
|
23932
|
+
});
|
|
23469
23933
|
var LspExtensionSchema = string2().trim().min(1).refine((value) => value.replace(/^\.+/, "").length > 0, {
|
|
23470
23934
|
message: "Extension must include characters other than leading dots"
|
|
23471
23935
|
});
|
|
@@ -23611,6 +24075,7 @@ var AftConfigFieldsSchema = object({
|
|
|
23611
24075
|
lsp: LspConfigSchema.optional(),
|
|
23612
24076
|
url_fetch_allow_private: boolean2().optional(),
|
|
23613
24077
|
semantic: SemanticConfigSchema.optional(),
|
|
24078
|
+
search: SearchConfigSchema.optional(),
|
|
23614
24079
|
auto_update: boolean2().optional(),
|
|
23615
24080
|
bridge: BridgeConfigSchema.optional(),
|
|
23616
24081
|
subc: SubcConfigSchema.optional(),
|
|
@@ -23855,7 +24320,7 @@ function migrateAftConfigFile2(configPath, logger = { log: log2, warn: warn2 })
|
|
|
23855
24320
|
let tmpPath = null;
|
|
23856
24321
|
let oldKeys = [];
|
|
23857
24322
|
try {
|
|
23858
|
-
const content =
|
|
24323
|
+
const content = readFileSync10(configPath, "utf-8");
|
|
23859
24324
|
const rawConfig = import_comment_json.parse(content);
|
|
23860
24325
|
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
23861
24326
|
return { migrated: false, oldKeys: [] };
|
|
@@ -23922,6 +24387,18 @@ function parseConfigPartially(rawConfig) {
|
|
|
23922
24387
|
return partialConfig;
|
|
23923
24388
|
}
|
|
23924
24389
|
var configLoadErrors = [];
|
|
24390
|
+
var configValidationErrors = [];
|
|
24391
|
+
var configLoadSources = [];
|
|
24392
|
+
var configLoadTexts = new Map;
|
|
24393
|
+
function getConfigLoadSources() {
|
|
24394
|
+
return configLoadSources;
|
|
24395
|
+
}
|
|
24396
|
+
function getConfigLoadTexts() {
|
|
24397
|
+
return configLoadTexts;
|
|
24398
|
+
}
|
|
24399
|
+
function getConfigValidationErrors() {
|
|
24400
|
+
return configValidationErrors;
|
|
24401
|
+
}
|
|
23925
24402
|
function getConfigLoadErrors() {
|
|
23926
24403
|
return configLoadErrors;
|
|
23927
24404
|
}
|
|
@@ -23954,7 +24431,9 @@ function loadConfigFromPath(configPath, tier) {
|
|
|
23954
24431
|
if (!existsSync12(configPath)) {
|
|
23955
24432
|
return null;
|
|
23956
24433
|
}
|
|
23957
|
-
const content =
|
|
24434
|
+
const content = readFileSync10(configPath, "utf-8");
|
|
24435
|
+
configLoadSources.push(configPath);
|
|
24436
|
+
configLoadTexts.set(configPath, content);
|
|
23958
24437
|
const rawConfig = import_comment_json.parse(content);
|
|
23959
24438
|
migrateRawConfig(rawConfig, configPath, { log: log2, warn: warn2 });
|
|
23960
24439
|
cleanConfig = stripJsoncSymbols(rawConfig);
|
|
@@ -23999,6 +24478,7 @@ function loadConfigFromPath(configPath, tier) {
|
|
|
23999
24478
|
} else {
|
|
24000
24479
|
const errorMsg = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ");
|
|
24001
24480
|
warn2(`Config validation error in ${configPath}: ${errorMsg}`);
|
|
24481
|
+
configValidationErrors.push({ path: configPath, message: errorMsg });
|
|
24002
24482
|
parsed = parseConfigPartially(cleanConfig);
|
|
24003
24483
|
}
|
|
24004
24484
|
if (!parsed)
|
|
@@ -24195,14 +24675,33 @@ function getStrippedTopLevelKeys(override) {
|
|
|
24195
24675
|
for (const tool of partitionProjectDisables(override.disabled_tools).ignored) {
|
|
24196
24676
|
stripped.push(`disabled_tools.${tool}`);
|
|
24197
24677
|
}
|
|
24678
|
+
stripped.push(...projectRerankStrippedKeys(override.search?.rerank));
|
|
24198
24679
|
return stripped;
|
|
24199
24680
|
}
|
|
24681
|
+
function projectRerankStrippedKeys(rerank) {
|
|
24682
|
+
if (rerank === undefined)
|
|
24683
|
+
return [];
|
|
24684
|
+
const stripped = [];
|
|
24685
|
+
if (rerank.backend !== undefined && rerank.backend !== "off")
|
|
24686
|
+
stripped.push("search.rerank.backend");
|
|
24687
|
+
for (const key of ["model", "endpoint", "api_key_env", "top_n", "timeout_ms"]) {
|
|
24688
|
+
if (rerank[key] !== undefined)
|
|
24689
|
+
stripped.push(`search.rerank.${key}`);
|
|
24690
|
+
}
|
|
24691
|
+
return stripped;
|
|
24692
|
+
}
|
|
24693
|
+
function mergeProjectSearchConfig(base, project) {
|
|
24694
|
+
if (project?.rerank?.backend !== "off")
|
|
24695
|
+
return base;
|
|
24696
|
+
return { ...base, rerank: { ...base?.rerank, backend: "off" } };
|
|
24697
|
+
}
|
|
24200
24698
|
function mergeConfigs(base, override) {
|
|
24201
24699
|
const disabledTools = unionDisabledTools(base.disabled_tools, partitionProjectDisables(override.disabled_tools).accepted);
|
|
24202
24700
|
const indexes = mergeIndexes(base.indexes, override.indexes, true);
|
|
24203
24701
|
const formatter = { ...base.formatter, ...override.formatter };
|
|
24204
24702
|
const checker = { ...base.checker, ...override.checker };
|
|
24205
24703
|
const semantic = mergeSemanticConfig(base.semantic, override.semantic);
|
|
24704
|
+
const search = mergeProjectSearchConfig(base.search, override.search);
|
|
24206
24705
|
const lsp = mergeLspConfig(base.lsp, override.lsp);
|
|
24207
24706
|
const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
|
|
24208
24707
|
const bash = mergeBashConfig(base.bash, override.bash);
|
|
@@ -24232,6 +24731,7 @@ function mergeConfigs(base, override) {
|
|
|
24232
24731
|
...pi !== undefined ? { pi } : {},
|
|
24233
24732
|
experimental,
|
|
24234
24733
|
semantic,
|
|
24734
|
+
search,
|
|
24235
24735
|
...bridge !== undefined ? { bridge } : {},
|
|
24236
24736
|
...indexes !== undefined ? { indexes } : {},
|
|
24237
24737
|
...disabledTools !== undefined ? { disabled_tools: disabledTools } : {}
|
|
@@ -24296,6 +24796,9 @@ function buildConfigTierConfigureParams(projectDirectory, processState = {}) {
|
|
|
24296
24796
|
}
|
|
24297
24797
|
function loadAftConfig(projectDirectory) {
|
|
24298
24798
|
configLoadErrors = [];
|
|
24799
|
+
configValidationErrors = [];
|
|
24800
|
+
configLoadSources = [];
|
|
24801
|
+
configLoadTexts = new Map;
|
|
24299
24802
|
configLoadNotices = [];
|
|
24300
24803
|
semanticInputSupplied = false;
|
|
24301
24804
|
const { userConfigPath, projectConfigPath } = resolveAftConfigPaths(projectDirectory);
|
|
@@ -38128,16 +38631,29 @@ function markBridgeEnd() {
|
|
|
38128
38631
|
slot.bridgeEnd = performance.now();
|
|
38129
38632
|
}
|
|
38130
38633
|
}
|
|
38634
|
+
async function measurePreStage(stage, operation) {
|
|
38635
|
+
const start = performance.now();
|
|
38636
|
+
try {
|
|
38637
|
+
return await operation();
|
|
38638
|
+
} finally {
|
|
38639
|
+
const slot = perfStore.getStore();
|
|
38640
|
+
if (slot) {
|
|
38641
|
+
slot.stages ??= {};
|
|
38642
|
+
slot.stages[stage] = (slot.stages[stage] ?? 0) + performance.now() - start;
|
|
38643
|
+
}
|
|
38644
|
+
}
|
|
38645
|
+
}
|
|
38131
38646
|
function emit(slot) {
|
|
38647
|
+
const stages = slot.stages ? ` directory=${Math.round(slot.stages.directory ?? 0)}ms permission=${Math.round(slot.stages.permission ?? 0)}ms capability=${Math.round(slot.stages.capability ?? 0)}ms` : "";
|
|
38132
38648
|
const t3 = performance.now();
|
|
38133
38649
|
const total = Math.round(t3 - slot.t0);
|
|
38134
38650
|
if (slot.bridgeStart !== undefined && slot.bridgeEnd !== undefined) {
|
|
38135
38651
|
const pre = Math.round(slot.bridgeStart - slot.t0);
|
|
38136
38652
|
const bridge = Math.round(slot.bridgeEnd - slot.bridgeStart);
|
|
38137
38653
|
const post = Math.round(t3 - slot.bridgeEnd);
|
|
38138
|
-
sessionLog(slot.sessionID, `perf tool=${slot.tool} total=${total}ms pre=${pre}ms bridge=${bridge}ms post=${post}ms`);
|
|
38654
|
+
sessionLog(slot.sessionID, `perf tool=${slot.tool} total=${total}ms pre=${pre}ms bridge=${bridge}ms post=${post}ms${stages}`);
|
|
38139
38655
|
} else {
|
|
38140
|
-
sessionLog(slot.sessionID, `perf tool=${slot.tool} total=${total}ms (no bridge call)`);
|
|
38656
|
+
sessionLog(slot.sessionID, `perf tool=${slot.tool} total=${total}ms (no bridge call)${stages}`);
|
|
38141
38657
|
}
|
|
38142
38658
|
}
|
|
38143
38659
|
function instrumentToolMap(tools) {
|
|
@@ -38367,10 +38883,10 @@ import {
|
|
|
38367
38883
|
createReadStream as createReadStream2,
|
|
38368
38884
|
existsSync as existsSync15,
|
|
38369
38885
|
mkdirSync as mkdirSync7,
|
|
38370
|
-
readFileSync as
|
|
38886
|
+
readFileSync as readFileSync13,
|
|
38371
38887
|
renameSync as renameSync9,
|
|
38372
38888
|
rmSync as rmSync5,
|
|
38373
|
-
statSync as
|
|
38889
|
+
statSync as statSync11,
|
|
38374
38890
|
writeFileSync as writeFileSync8
|
|
38375
38891
|
} from "node:fs";
|
|
38376
38892
|
import { join as join17 } from "node:path";
|
|
@@ -38381,10 +38897,10 @@ import {
|
|
|
38381
38897
|
closeSync as closeSync6,
|
|
38382
38898
|
mkdirSync as mkdirSync6,
|
|
38383
38899
|
openSync as openSync6,
|
|
38384
|
-
readFileSync as
|
|
38900
|
+
readFileSync as readFileSync11,
|
|
38385
38901
|
renameSync as renameSync8,
|
|
38386
38902
|
rmSync as rmSync4,
|
|
38387
|
-
statSync as
|
|
38903
|
+
statSync as statSync10,
|
|
38388
38904
|
unlinkSync as unlinkSync6,
|
|
38389
38905
|
writeFileSync as writeFileSync7
|
|
38390
38906
|
} from "node:fs";
|
|
@@ -38407,7 +38923,7 @@ function lspBinDir(npmPackage) {
|
|
|
38407
38923
|
function isInstalled(npmPackage, binary) {
|
|
38408
38924
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
38409
38925
|
try {
|
|
38410
|
-
if (
|
|
38926
|
+
if (statSync10(join15(lspBinDir(npmPackage), candidate)).isFile())
|
|
38411
38927
|
return true;
|
|
38412
38928
|
} catch {}
|
|
38413
38929
|
}
|
|
@@ -38435,9 +38951,9 @@ function writeInstalledMetaIn(installDir, version, sha256) {
|
|
|
38435
38951
|
function readInstalledMetaIn(installDir) {
|
|
38436
38952
|
const path = join15(installDir, INSTALLED_META_FILE);
|
|
38437
38953
|
try {
|
|
38438
|
-
if (!
|
|
38954
|
+
if (!statSync10(path).isFile())
|
|
38439
38955
|
return null;
|
|
38440
|
-
const raw =
|
|
38956
|
+
const raw = readFileSync11(path, "utf8");
|
|
38441
38957
|
const parsed = JSON.parse(raw);
|
|
38442
38958
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
38443
38959
|
return null;
|
|
@@ -38506,12 +39022,12 @@ ${token}
|
|
|
38506
39022
|
let owningPid = null;
|
|
38507
39023
|
let lockMtimeMs = 0;
|
|
38508
39024
|
try {
|
|
38509
|
-
const raw =
|
|
39025
|
+
const raw = readFileSync11(lock, "utf8");
|
|
38510
39026
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
38511
39027
|
const parsed = Number.parseInt(firstLine, 10);
|
|
38512
39028
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
38513
39029
|
owningPid = parsed;
|
|
38514
|
-
lockMtimeMs =
|
|
39030
|
+
lockMtimeMs = statSync10(lock).mtimeMs;
|
|
38515
39031
|
} catch {
|
|
38516
39032
|
return tryClaim();
|
|
38517
39033
|
}
|
|
@@ -38545,7 +39061,7 @@ function releaseInstallLock(lockKey, acquisitionToken) {
|
|
|
38545
39061
|
let owningPid = null;
|
|
38546
39062
|
let owningToken = "";
|
|
38547
39063
|
try {
|
|
38548
|
-
const raw =
|
|
39064
|
+
const raw = readFileSync11(lock, "utf8");
|
|
38549
39065
|
const lines = raw.split(/\r?\n/);
|
|
38550
39066
|
const parsed = Number.parseInt(lines[0]?.trim() ?? "", 10);
|
|
38551
39067
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -38592,7 +39108,7 @@ function autoInstallStampPath() {
|
|
|
38592
39108
|
}
|
|
38593
39109
|
function hasRecentAutoInstallStamp(path) {
|
|
38594
39110
|
try {
|
|
38595
|
-
const parsed = JSON.parse(
|
|
39111
|
+
const parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
38596
39112
|
return typeof parsed.lastRunMs === "number" && Number.isFinite(parsed.lastRunMs) && Math.abs(Date.now() - parsed.lastRunMs) < AUTO_INSTALL_WINDOW_MS;
|
|
38597
39113
|
} catch {
|
|
38598
39114
|
return false;
|
|
@@ -38600,7 +39116,7 @@ function hasRecentAutoInstallStamp(path) {
|
|
|
38600
39116
|
}
|
|
38601
39117
|
function readAutoInstallLockOwner(path) {
|
|
38602
39118
|
try {
|
|
38603
|
-
const parsed = JSON.parse(
|
|
39119
|
+
const parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
38604
39120
|
if (typeof parsed.pid !== "number" || typeof parsed.startedMs !== "number" || typeof parsed.token !== "string") {
|
|
38605
39121
|
return null;
|
|
38606
39122
|
}
|
|
@@ -38613,7 +39129,7 @@ function autoInstallLockIsStale(path) {
|
|
|
38613
39129
|
const owner = readAutoInstallLockOwner(path);
|
|
38614
39130
|
let age = Number.POSITIVE_INFINITY;
|
|
38615
39131
|
try {
|
|
38616
|
-
age = Math.abs(Date.now() -
|
|
39132
|
+
age = Math.abs(Date.now() - statSync10(path).mtimeMs);
|
|
38617
39133
|
} catch {
|
|
38618
39134
|
return true;
|
|
38619
39135
|
}
|
|
@@ -38691,7 +39207,7 @@ var VERSION_CHECK_FILE = ".aft-version-check";
|
|
|
38691
39207
|
function readVersionCheck(npmPackage) {
|
|
38692
39208
|
const file = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
38693
39209
|
try {
|
|
38694
|
-
const raw =
|
|
39210
|
+
const raw = readFileSync11(file, "utf8");
|
|
38695
39211
|
const parsed = JSON.parse(raw);
|
|
38696
39212
|
if (typeof parsed.last_checked === "string") {
|
|
38697
39213
|
return {
|
|
@@ -38794,6 +39310,13 @@ var NPM_LSP_TABLE = [
|
|
|
38794
39310
|
extensions: ["ts", "tsx", "js", "jsx", "mjs", "cjs", "mts", "cts"],
|
|
38795
39311
|
rootMarkers: ["tsconfig.json", "jsconfig.json", "package.json"]
|
|
38796
39312
|
},
|
|
39313
|
+
{
|
|
39314
|
+
id: "typescript-sdk",
|
|
39315
|
+
npm: "typescript",
|
|
39316
|
+
binary: "tsserver",
|
|
39317
|
+
extensions: ["ts", "tsx", "js", "jsx", "mjs", "cjs", "mts", "cts"],
|
|
39318
|
+
rootMarkers: ["tsconfig.json", "jsconfig.json", "package.json"]
|
|
39319
|
+
},
|
|
38797
39320
|
{
|
|
38798
39321
|
id: "python",
|
|
38799
39322
|
npm: "pyright",
|
|
@@ -38868,7 +39391,7 @@ var NPM_LSP_TABLE = [
|
|
|
38868
39391
|
];
|
|
38869
39392
|
|
|
38870
39393
|
// src/lsp-project-relevance.ts
|
|
38871
|
-
import { existsSync as existsSync14, readdirSync as readdirSync4, readFileSync as
|
|
39394
|
+
import { existsSync as existsSync14, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "node:fs";
|
|
38872
39395
|
import { join as join16 } from "node:path";
|
|
38873
39396
|
var MAX_WALK_DIRS = 200;
|
|
38874
39397
|
var MAX_WALK_DEPTH = 4;
|
|
@@ -38910,7 +39433,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
38910
39433
|
}
|
|
38911
39434
|
function readPackageJson(projectRoot) {
|
|
38912
39435
|
try {
|
|
38913
|
-
const raw =
|
|
39436
|
+
const raw = readFileSync12(join16(projectRoot, "package.json"), "utf8");
|
|
38914
39437
|
const parsed = JSON.parse(raw);
|
|
38915
39438
|
if (typeof parsed !== "object" || parsed === null)
|
|
38916
39439
|
return null;
|
|
@@ -39258,7 +39781,7 @@ function hashInstalledBinary(spec) {
|
|
|
39258
39781
|
let pathToHash = null;
|
|
39259
39782
|
for (const p of candidates) {
|
|
39260
39783
|
try {
|
|
39261
|
-
if (
|
|
39784
|
+
if (statSync11(p).isFile()) {
|
|
39262
39785
|
pathToHash = p;
|
|
39263
39786
|
break;
|
|
39264
39787
|
}
|
|
@@ -39284,14 +39807,14 @@ function installedBinaryPath(spec) {
|
|
|
39284
39807
|
] : [lspBinaryPath(spec.npm, spec.binary)];
|
|
39285
39808
|
for (const candidate of candidates) {
|
|
39286
39809
|
try {
|
|
39287
|
-
if (
|
|
39810
|
+
if (statSync11(candidate).isFile())
|
|
39288
39811
|
return candidate;
|
|
39289
39812
|
} catch {}
|
|
39290
39813
|
}
|
|
39291
39814
|
return null;
|
|
39292
39815
|
}
|
|
39293
39816
|
function sha256OfFileSync(path) {
|
|
39294
|
-
return createHash7("sha256").update(
|
|
39817
|
+
return createHash7("sha256").update(readFileSync13(path)).digest("hex");
|
|
39295
39818
|
}
|
|
39296
39819
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
39297
39820
|
const packageDir = lspPackageDir(spec.npm);
|
|
@@ -39334,7 +39857,7 @@ function runAutoInstall(projectRoot, config, fetchImpl = fetch) {
|
|
|
39334
39857
|
if (isInstalled(spec.npm, spec.binary) && validateCachedNpmInstall(spec)) {
|
|
39335
39858
|
cachedBinDirs.push(lspBinDir(spec.npm));
|
|
39336
39859
|
}
|
|
39337
|
-
if (config.disabled.has(spec.id)) {
|
|
39860
|
+
if (config.disabled.has(spec.id) || spec.id === "typescript-sdk" && config.disabled.has("typescript")) {
|
|
39338
39861
|
skipped.push({ id: spec.id, reason: "disabled by config" });
|
|
39339
39862
|
continue;
|
|
39340
39863
|
}
|
|
@@ -39390,16 +39913,16 @@ import {
|
|
|
39390
39913
|
lstatSync as lstatSync2,
|
|
39391
39914
|
mkdirSync as mkdirSync8,
|
|
39392
39915
|
readdirSync as readdirSync5,
|
|
39393
|
-
readFileSync as
|
|
39916
|
+
readFileSync as readFileSync14,
|
|
39394
39917
|
readlinkSync as readlinkSync2,
|
|
39395
39918
|
realpathSync as realpathSync4,
|
|
39396
39919
|
renameSync as renameSync10,
|
|
39397
39920
|
rmSync as rmSync6,
|
|
39398
|
-
statSync as
|
|
39921
|
+
statSync as statSync12,
|
|
39399
39922
|
unlinkSync as unlinkSync7,
|
|
39400
39923
|
writeFileSync as writeFileSync9
|
|
39401
39924
|
} from "node:fs";
|
|
39402
|
-
import { dirname as
|
|
39925
|
+
import { dirname as dirname9, join as join18, relative as relative3, resolve as resolve10 } from "node:path";
|
|
39403
39926
|
import { Readable as Readable3 } from "node:stream";
|
|
39404
39927
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
39405
39928
|
|
|
@@ -39508,7 +40031,7 @@ function installFailureMarkerPath(spec) {
|
|
|
39508
40031
|
}
|
|
39509
40032
|
function readInstallFailureMarker(spec) {
|
|
39510
40033
|
try {
|
|
39511
|
-
const marker = JSON.parse(
|
|
40034
|
+
const marker = JSON.parse(readFileSync14(installFailureMarkerPath(spec), "utf8"));
|
|
39512
40035
|
if (typeof marker.release !== "string" || typeof marker.sha256 !== "string" || typeof marker.error !== "string" || typeof marker.at !== "string" || !Number.isFinite(Date.parse(marker.at))) {
|
|
39513
40036
|
return null;
|
|
39514
40037
|
}
|
|
@@ -39522,7 +40045,7 @@ function writeInstallFailureMarker(spec, release, sha256, installError) {
|
|
|
39522
40045
|
const markerError = installError.replace(/\s+/g, " ").trim();
|
|
39523
40046
|
const tempPath = `${path}.tmp-${process.pid}-${randomBytes4(6).toString("hex")}`;
|
|
39524
40047
|
try {
|
|
39525
|
-
mkdirSync8(
|
|
40048
|
+
mkdirSync8(dirname9(path), { recursive: true });
|
|
39526
40049
|
writeFileSync9(tempPath, `${JSON.stringify({ release, sha256, error: markerError, at: new Date().toISOString() })}
|
|
39527
40050
|
`, { encoding: "utf8", mode: 384 });
|
|
39528
40051
|
renameSync10(tempPath, path);
|
|
@@ -39551,7 +40074,7 @@ function ghBinaryPath(spec, platform) {
|
|
|
39551
40074
|
function isGithubInstalled(spec, platform) {
|
|
39552
40075
|
for (const candidate of ghBinaryCandidates(spec, platform)) {
|
|
39553
40076
|
try {
|
|
39554
|
-
if (
|
|
40077
|
+
if (statSync12(join18(ghBinDir(spec), candidate)).isFile())
|
|
39555
40078
|
return true;
|
|
39556
40079
|
} catch {}
|
|
39557
40080
|
}
|
|
@@ -39565,9 +40088,9 @@ function ghBinaryCandidates(spec, platform) {
|
|
|
39565
40088
|
function readGithubInstalledMetaIn(installDir) {
|
|
39566
40089
|
try {
|
|
39567
40090
|
const path = join18(installDir, INSTALLED_META_FILE2);
|
|
39568
|
-
if (!
|
|
40091
|
+
if (!statSync12(path).isFile())
|
|
39569
40092
|
return null;
|
|
39570
|
-
const parsed = JSON.parse(
|
|
40093
|
+
const parsed = JSON.parse(readFileSync14(path, "utf8"));
|
|
39571
40094
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
39572
40095
|
return null;
|
|
39573
40096
|
return {
|
|
@@ -39608,7 +40131,7 @@ function sha256OfFile(path) {
|
|
|
39608
40131
|
});
|
|
39609
40132
|
}
|
|
39610
40133
|
function sha256OfFileSync2(path) {
|
|
39611
|
-
return createHash8("sha256").update(
|
|
40134
|
+
return createHash8("sha256").update(readFileSync14(path)).digest("hex");
|
|
39612
40135
|
}
|
|
39613
40136
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
39614
40137
|
const candidates = [];
|
|
@@ -39784,7 +40307,7 @@ async function downloadFile(url, destPath, fetchImpl, assetSize, signal) {
|
|
|
39784
40307
|
if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES3) {
|
|
39785
40308
|
throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES3}`);
|
|
39786
40309
|
}
|
|
39787
|
-
mkdirSync8(
|
|
40310
|
+
mkdirSync8(dirname9(destPath), { recursive: true });
|
|
39788
40311
|
let bytesWritten = 0;
|
|
39789
40312
|
const guard = new TransformStream({
|
|
39790
40313
|
transform(chunk, controller) {
|
|
@@ -39954,7 +40477,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
39954
40477
|
const dest = join18(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
39955
40478
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
39956
40479
|
try {
|
|
39957
|
-
mkdirSync8(
|
|
40480
|
+
mkdirSync8(dirname9(dest), { recursive: true });
|
|
39958
40481
|
rmSync6(dest, { recursive: true, force: true });
|
|
39959
40482
|
renameSync10(packageDir, dest);
|
|
39960
40483
|
} catch (err) {
|
|
@@ -39966,7 +40489,7 @@ function validateCachedGithubInstall(spec, platform) {
|
|
|
39966
40489
|
const meta = readGithubInstalledMetaIn(packageDir);
|
|
39967
40490
|
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join18(ghBinDir(spec), candidate)).find((candidate) => {
|
|
39968
40491
|
try {
|
|
39969
|
-
return
|
|
40492
|
+
return statSync12(candidate).isFile();
|
|
39970
40493
|
} catch {
|
|
39971
40494
|
return false;
|
|
39972
40495
|
}
|
|
@@ -40084,7 +40607,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
40084
40607
|
return { ok: false, sha256: archiveSha256, error: message };
|
|
40085
40608
|
}
|
|
40086
40609
|
const targetBinary = ghBinaryPath(spec, platform);
|
|
40087
|
-
mkdirSync8(
|
|
40610
|
+
mkdirSync8(dirname9(targetBinary), { recursive: true });
|
|
40088
40611
|
try {
|
|
40089
40612
|
copyFileSync3(innerBinaryPath, targetBinary);
|
|
40090
40613
|
if (platform !== "win32") {
|
|
@@ -40613,14 +41136,16 @@ async function assertExternalDirectoryPermission(ctx, context, target, options)
|
|
|
40613
41136
|
const directory = root ? normalizePath(root) : root;
|
|
40614
41137
|
const rawWorktree = context.worktree;
|
|
40615
41138
|
const worktree = rawWorktree && rawWorktree !== "/" ? normalizePath(rawWorktree) : rawWorktree;
|
|
41139
|
+
const restrictToProjectRoot = ctx.config.restrict_to_project_root === true;
|
|
40616
41140
|
if (directory && containsPath(directory, absoluteTarget))
|
|
40617
41141
|
return;
|
|
40618
|
-
if (worktree && worktree !== "/" && worktree !== directory && containsPath(worktree, absoluteTarget)) {
|
|
41142
|
+
if (!restrictToProjectRoot && worktree && worktree !== "/" && worktree !== directory && containsPath(worktree, absoluteTarget)) {
|
|
40619
41143
|
return;
|
|
40620
41144
|
}
|
|
40621
|
-
if (
|
|
40622
|
-
if (options?.serverValidatedRead === true)
|
|
41145
|
+
if (restrictToProjectRoot) {
|
|
41146
|
+
if (options?.serverValidatedRead === true && await isSessionOwnedBashArtifact(ctx, context, absoluteTarget)) {
|
|
40623
41147
|
return;
|
|
41148
|
+
}
|
|
40624
41149
|
notifyRestrictBlocked(ctx, context, absoluteTarget);
|
|
40625
41150
|
return restrictDenialMessage(absoluteTarget);
|
|
40626
41151
|
}
|
|
@@ -41150,8 +41675,87 @@ function projectV2Tool(name, definition, location, consumers = {}) {
|
|
|
41150
41675
|
}
|
|
41151
41676
|
|
|
41152
41677
|
// src/tools/hoisted.ts
|
|
41678
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
41153
41679
|
import * as path4 from "node:path";
|
|
41154
41680
|
|
|
41681
|
+
// src/shared/read-vision.ts
|
|
41682
|
+
var VISION_HOST_TIMEOUT_MS = 1500;
|
|
41683
|
+
var states = new WeakMap;
|
|
41684
|
+
function stateFor2(client) {
|
|
41685
|
+
let state = states.get(client);
|
|
41686
|
+
if (!state) {
|
|
41687
|
+
state = { models: new Map, history: new Map, capabilities: new Map };
|
|
41688
|
+
states.set(client, state);
|
|
41689
|
+
}
|
|
41690
|
+
return state;
|
|
41691
|
+
}
|
|
41692
|
+
function rememberReadModel(client, sessionID, model) {
|
|
41693
|
+
stateFor2(client).models.set(sessionID, model);
|
|
41694
|
+
}
|
|
41695
|
+
async function bounded(call) {
|
|
41696
|
+
let timer;
|
|
41697
|
+
try {
|
|
41698
|
+
return await Promise.race([
|
|
41699
|
+
Promise.resolve().then(call),
|
|
41700
|
+
new Promise((resolve) => {
|
|
41701
|
+
timer = setTimeout(() => resolve(undefined), VISION_HOST_TIMEOUT_MS);
|
|
41702
|
+
})
|
|
41703
|
+
]);
|
|
41704
|
+
} catch {
|
|
41705
|
+
return;
|
|
41706
|
+
} finally {
|
|
41707
|
+
clearTimeout(timer);
|
|
41708
|
+
}
|
|
41709
|
+
}
|
|
41710
|
+
function record3(value) {
|
|
41711
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
41712
|
+
}
|
|
41713
|
+
async function currentSessionVisionCapability(client, sessionID) {
|
|
41714
|
+
if (!sessionID)
|
|
41715
|
+
return;
|
|
41716
|
+
const state = stateFor2(client);
|
|
41717
|
+
let model = state.models.get(sessionID);
|
|
41718
|
+
if (!model) {
|
|
41719
|
+
let pending = state.history.get(sessionID);
|
|
41720
|
+
if (!pending) {
|
|
41721
|
+
pending = bounded(() => resolvePromptContext(client, sessionID)).then((context) => context?.model);
|
|
41722
|
+
state.history.set(sessionID, pending);
|
|
41723
|
+
pending.finally(() => state.history.delete(sessionID));
|
|
41724
|
+
}
|
|
41725
|
+
const historical = await pending;
|
|
41726
|
+
model = state.models.get(sessionID) ?? historical;
|
|
41727
|
+
}
|
|
41728
|
+
if (!model)
|
|
41729
|
+
return;
|
|
41730
|
+
const currentModel = model;
|
|
41731
|
+
const key = JSON.stringify([model.providerID, model.modelID]);
|
|
41732
|
+
let capability = state.capabilities.get(key);
|
|
41733
|
+
if (!capability) {
|
|
41734
|
+
capability = (async () => {
|
|
41735
|
+
const api = client.provider;
|
|
41736
|
+
if (!api?.list)
|
|
41737
|
+
return;
|
|
41738
|
+
const list = api.list.bind(api);
|
|
41739
|
+
const listed = record3(await bounded(list));
|
|
41740
|
+
const catalog = record3(listed?.data) ?? listed;
|
|
41741
|
+
const providers = catalog?.all ?? catalog?.providers;
|
|
41742
|
+
if (!Array.isArray(providers))
|
|
41743
|
+
return;
|
|
41744
|
+
const provider = providers.map(record3).find((entry) => entry?.id === currentModel.providerID);
|
|
41745
|
+
const models = provider?.models;
|
|
41746
|
+
const entry = record3(Array.isArray(models) ? models.find((entry) => record3(entry)?.id === currentModel.modelID) : record3(models)?.[currentModel.modelID]);
|
|
41747
|
+
const inputs = record3(entry?.modalities)?.input;
|
|
41748
|
+
return Array.isArray(inputs) ? inputs.includes("image") : typeof entry?.attachment === "boolean" ? entry.attachment : undefined;
|
|
41749
|
+
})();
|
|
41750
|
+
state.capabilities.set(key, capability);
|
|
41751
|
+
capability.then((value) => {
|
|
41752
|
+
if (value === undefined)
|
|
41753
|
+
state.capabilities.delete(key);
|
|
41754
|
+
});
|
|
41755
|
+
}
|
|
41756
|
+
return capability;
|
|
41757
|
+
}
|
|
41758
|
+
|
|
41155
41759
|
// src/shared/subagent-detect.ts
|
|
41156
41760
|
import { Effect as Effect2 } from "effect";
|
|
41157
41761
|
var CACHE_MAX_ENTRIES2 = 200;
|
|
@@ -41738,7 +42342,7 @@ A notification will fire when the pattern matches or the task exits.`;
|
|
|
41738
42342
|
const data = await waitForBashStatus(ctx, context, taskId, undefined, waitFor, effectiveWaitMs);
|
|
41739
42343
|
const waited = data.waited;
|
|
41740
42344
|
if (waited?.reason === "user_message") {
|
|
41741
|
-
const convertedText = await convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, coerceBoolean(args.once, true));
|
|
42345
|
+
const convertedText = await convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, coerceBoolean(args.once, true), waited.elapsed_ms);
|
|
41742
42346
|
const metadata = context.metadata;
|
|
41743
42347
|
metadata?.({ taskId, status: data.status, waited, convertedToAsync: true });
|
|
41744
42348
|
return convertedText;
|
|
@@ -41750,9 +42354,10 @@ A notification will fire when the pattern matches or the task exits.`;
|
|
|
41750
42354
|
}
|
|
41751
42355
|
};
|
|
41752
42356
|
}
|
|
41753
|
-
async function convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, once) {
|
|
42357
|
+
async function convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, once, elapsedMs) {
|
|
42358
|
+
const interrupted = `Sync watch for task ${taskId} was interrupted because you sent a message after ${elapsedMs}ms of waiting. `;
|
|
41754
42359
|
if (!waitFor) {
|
|
41755
|
-
return
|
|
42360
|
+
return interrupted + `The task is still running in the background. A completion reminder will be ` + `delivered automatically when the task exits; don't poll bash_status.`;
|
|
41756
42361
|
}
|
|
41757
42362
|
const notifyParams = {
|
|
41758
42363
|
task_id: taskId,
|
|
@@ -41767,12 +42372,12 @@ async function convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, once) {
|
|
|
41767
42372
|
const registered = await callBashBridge(ctx, context, "bash_notify", notifyParams);
|
|
41768
42373
|
if (registered.success === false) {
|
|
41769
42374
|
unmarkExplicitControl(context.sessionID, taskId);
|
|
41770
|
-
return
|
|
42375
|
+
return interrupted + `Auto-registering an async watch failed (${String(registered.message ?? "unknown error")}). ` + `The task is still running in the background. A completion reminder will be ` + `delivered automatically when the task exits.`;
|
|
41771
42376
|
}
|
|
41772
|
-
return
|
|
42377
|
+
return interrupted + `The wait has been converted to an async watch (${registered.watch_id}). ` + `A notification will fire when the pattern matches or the task exits.`;
|
|
41773
42378
|
} catch (err) {
|
|
41774
42379
|
unmarkExplicitControl(context.sessionID, taskId);
|
|
41775
|
-
return
|
|
42380
|
+
return interrupted + `Auto-registering an async watch failed (${err instanceof Error ? err.message : String(err)}). ` + `The task is still running in the background. A completion reminder will be ` + `delivered automatically when the task exits.`;
|
|
41776
42381
|
}
|
|
41777
42382
|
}
|
|
41778
42383
|
function formatWatchResultText(taskId, data, waited, role, syncWaitCap) {
|
|
@@ -41781,21 +42386,22 @@ function formatWatchResultText(taskId, data, waited, role, syncWaitCap) {
|
|
|
41781
42386
|
const dur = typeof data.duration_ms === "number" ? ` ${Math.round(data.duration_ms / 1000)}s` : "";
|
|
41782
42387
|
let text = `Task ${taskId}: ${status}${exit}${dur}`;
|
|
41783
42388
|
if (waited) {
|
|
42389
|
+
const waitedText = formatWatchWaited(waited.elapsed_ms, waited.limit_ms, syncWaitCap);
|
|
41784
42390
|
if (waited.reason === "matched") {
|
|
41785
42391
|
const stream = waited.match_stream ? ` in ${waited.match_stream}` : "";
|
|
41786
42392
|
text += `
|
|
41787
|
-
|
|
42393
|
+
${waitedText}; matched ${JSON.stringify(waited.match ?? "")}${stream} at offset ${waited.match_offset ?? 0}.`;
|
|
41788
42394
|
} else if (waited.reason === "timeout") {
|
|
41789
42395
|
text += `
|
|
41790
|
-
|
|
42396
|
+
${waitedText}; timeout reached without match. ${watchTimeoutSteer(role, syncWaitCap)}`;
|
|
41791
42397
|
} else if (waited.reason === "unavailable") {
|
|
41792
42398
|
text += `
|
|
41793
|
-
|
|
42399
|
+
${waitedText}; the bridge was busy, so task state is unknown. Do not poll; let the task's completion notification wake the session, or use one bash_status snapshot on the next normal tool call.`;
|
|
41794
42400
|
} else {
|
|
41795
42401
|
const stat = String(data.status ?? "unknown");
|
|
41796
42402
|
const e = typeof data.exit_code === "number" ? `, exit ${data.exit_code}` : "";
|
|
41797
42403
|
text += `
|
|
41798
|
-
|
|
42404
|
+
${waitedText}; task exited (${stat}${e}).`;
|
|
41799
42405
|
}
|
|
41800
42406
|
}
|
|
41801
42407
|
const preview = data.output_preview;
|
|
@@ -41817,8 +42423,9 @@ async function bashStatusSnapshot2(ctx, runtime, taskId, outputMode, cursor, opt
|
|
|
41817
42423
|
return data;
|
|
41818
42424
|
}
|
|
41819
42425
|
async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effectiveWaitMs) {
|
|
41820
|
-
const startedAt =
|
|
42426
|
+
const startedAt = monotonicNowMs();
|
|
41821
42427
|
const deadline = startedAt + effectiveWaitMs;
|
|
42428
|
+
const elapsedMs = () => Math.round(monotonicNowMs() - startedAt);
|
|
41822
42429
|
let spillCursor = { output: 0, stderr: 0 };
|
|
41823
42430
|
const scanState = {
|
|
41824
42431
|
output: { text: "", baseOffset: 0 },
|
|
@@ -41843,16 +42450,18 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
41843
42450
|
if (isSyncWatchAborted(runtime.sessionID)) {
|
|
41844
42451
|
return withWaited(lastData ?? unavailableSnapshot(), {
|
|
41845
42452
|
reason: "user_message",
|
|
41846
|
-
elapsed_ms:
|
|
42453
|
+
elapsed_ms: elapsedMs(),
|
|
42454
|
+
limit_ms: effectiveWaitMs
|
|
41847
42455
|
});
|
|
41848
42456
|
}
|
|
41849
|
-
if (
|
|
42457
|
+
if (monotonicNowMs() >= deadline) {
|
|
41850
42458
|
return withWaited(lastData ?? unavailableSnapshot(), {
|
|
41851
42459
|
reason: "unavailable",
|
|
41852
|
-
elapsed_ms:
|
|
42460
|
+
elapsed_ms: elapsedMs(),
|
|
42461
|
+
limit_ms: effectiveWaitMs
|
|
41853
42462
|
});
|
|
41854
42463
|
}
|
|
41855
|
-
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline -
|
|
42464
|
+
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - monotonicNowMs())));
|
|
41856
42465
|
continue;
|
|
41857
42466
|
}
|
|
41858
42467
|
lastData = data;
|
|
@@ -41881,7 +42490,8 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
41881
42490
|
const matchStream = data.mode === "pty" ? undefined : chunk.stream === "output" ? "stdout" : "stderr";
|
|
41882
42491
|
return withWaited(data, {
|
|
41883
42492
|
reason: "matched",
|
|
41884
|
-
elapsed_ms:
|
|
42493
|
+
elapsed_ms: elapsedMs(),
|
|
42494
|
+
limit_ms: effectiveWaitMs,
|
|
41885
42495
|
match: match.text,
|
|
41886
42496
|
match_offset: state.baseOffset + match.byteOffset,
|
|
41887
42497
|
match_stream: matchStream
|
|
@@ -41899,15 +42509,27 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
41899
42509
|
sawTerminal = true;
|
|
41900
42510
|
consumeBgCompletion(runtime.sessionID, taskId);
|
|
41901
42511
|
await markBgCompletionDelivered({ ctx, directory: projectRootFor(runtime), sessionID: runtime.sessionID }, taskId);
|
|
41902
|
-
return withWaited(data, {
|
|
42512
|
+
return withWaited(data, {
|
|
42513
|
+
reason: "exited",
|
|
42514
|
+
elapsed_ms: elapsedMs(),
|
|
42515
|
+
limit_ms: effectiveWaitMs
|
|
42516
|
+
});
|
|
41903
42517
|
}
|
|
41904
42518
|
if (isSyncWatchAborted(runtime.sessionID)) {
|
|
41905
|
-
return withWaited(data, {
|
|
42519
|
+
return withWaited(data, {
|
|
42520
|
+
reason: "user_message",
|
|
42521
|
+
elapsed_ms: elapsedMs(),
|
|
42522
|
+
limit_ms: effectiveWaitMs
|
|
42523
|
+
});
|
|
41906
42524
|
}
|
|
41907
|
-
if (
|
|
41908
|
-
return withWaited(data, {
|
|
42525
|
+
if (monotonicNowMs() >= deadline) {
|
|
42526
|
+
return withWaited(data, {
|
|
42527
|
+
reason: "timeout",
|
|
42528
|
+
elapsed_ms: elapsedMs(),
|
|
42529
|
+
limit_ms: effectiveWaitMs
|
|
42530
|
+
});
|
|
41909
42531
|
}
|
|
41910
|
-
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline -
|
|
42532
|
+
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - monotonicNowMs())));
|
|
41911
42533
|
}
|
|
41912
42534
|
} finally {
|
|
41913
42535
|
if (!sawTerminal)
|
|
@@ -42055,47 +42677,6 @@ var ISSUE_AND_PR_READ_DESCRIPTION = "GitHub issues and pull requests can be read
|
|
|
42055
42677
|
function whenGhReadEnabled(enabled, description) {
|
|
42056
42678
|
return enabled ? description : "";
|
|
42057
42679
|
}
|
|
42058
|
-
function asRecord(value) {
|
|
42059
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
42060
|
-
}
|
|
42061
|
-
function visionCapabilityForOpenCodeModel(model) {
|
|
42062
|
-
const entry = model;
|
|
42063
|
-
if (Array.isArray(entry?.modalities?.input)) {
|
|
42064
|
-
return entry.modalities.input.includes("image");
|
|
42065
|
-
}
|
|
42066
|
-
return typeof entry?.attachment === "boolean" ? entry.attachment : undefined;
|
|
42067
|
-
}
|
|
42068
|
-
function modelFromOpenCodeProvider(provider, modelID) {
|
|
42069
|
-
const models = provider.models;
|
|
42070
|
-
if (Array.isArray(models)) {
|
|
42071
|
-
return models.find((model) => asRecord(model)?.id === modelID);
|
|
42072
|
-
}
|
|
42073
|
-
return asRecord(models)?.[modelID];
|
|
42074
|
-
}
|
|
42075
|
-
async function currentSessionVisionCapability(client, sessionID) {
|
|
42076
|
-
if (!sessionID)
|
|
42077
|
-
return;
|
|
42078
|
-
const promptContext = await resolvePromptContext(client, sessionID);
|
|
42079
|
-
const currentModel = promptContext?.model;
|
|
42080
|
-
if (!currentModel)
|
|
42081
|
-
return;
|
|
42082
|
-
const providerApi = client.provider;
|
|
42083
|
-
if (typeof providerApi?.list !== "function")
|
|
42084
|
-
return;
|
|
42085
|
-
let listed;
|
|
42086
|
-
try {
|
|
42087
|
-
listed = await providerApi.list();
|
|
42088
|
-
} catch {
|
|
42089
|
-
return;
|
|
42090
|
-
}
|
|
42091
|
-
const result = asRecord(listed);
|
|
42092
|
-
const catalog = asRecord(result?.data) ?? result;
|
|
42093
|
-
const providers = Array.isArray(catalog?.all) ? catalog.all : Array.isArray(catalog?.providers) ? catalog.providers : [];
|
|
42094
|
-
const provider = providers.map(asRecord).find((entry) => entry?.id === currentModel.providerID);
|
|
42095
|
-
if (!provider)
|
|
42096
|
-
return;
|
|
42097
|
-
return visionCapabilityForOpenCodeModel(modelFromOpenCodeProvider(provider, currentModel.modelID));
|
|
42098
|
-
}
|
|
42099
42680
|
function persistFilePathAlias(args, context) {
|
|
42100
42681
|
if (typeof args.path === "string" && !Object.hasOwn(args, "filePath")) {
|
|
42101
42682
|
args.filePath = args.path;
|
|
@@ -42267,7 +42848,7 @@ function inferBeforeStart(ops, from, beforeLen) {
|
|
|
42267
42848
|
var z7 = tool.schema;
|
|
42268
42849
|
var READ_DESCRIPTION = `Read file contents or list directory entries.
|
|
42269
42850
|
|
|
42270
|
-
Use either startLine/endLine OR offset/limit to read a section of a file.
|
|
42851
|
+
Use either startLine/endLine OR offset/limit to read a section of a file or sorted directory listing.
|
|
42271
42852
|
|
|
42272
42853
|
Behavior:
|
|
42273
42854
|
- Returns line-numbered content (e.g., "1: const x = 1")
|
|
@@ -42275,7 +42856,7 @@ Behavior:
|
|
|
42275
42856
|
- Output capped at 50KB
|
|
42276
42857
|
- Binary files are auto-detected and return a size-only message
|
|
42277
42858
|
- Supported images (PNG, JPEG, GIF, WebP) and PDFs are returned as tool attachments; range arguments are ignored for media
|
|
42278
|
-
- Directories return sorted entries with trailing / for subdirectories
|
|
42859
|
+
- Directories return sorted entries with trailing / for subdirectories; offset is 1-based, limit defaults to and is capped at 1000 entries. Enumeration stops at 10,000 entries; partial listings carry a shown/total trailer.
|
|
42279
42860
|
|
|
42280
42861
|
Examples:
|
|
42281
42862
|
Read full file: { "path": "src/app.ts" }
|
|
@@ -42299,30 +42880,30 @@ function createReadTool(ctx) {
|
|
|
42299
42880
|
description: readDescription(resolveGithubConfig(ctx.config).read),
|
|
42300
42881
|
args: {
|
|
42301
42882
|
filePath: z7.string().describe("Path to file or directory (absolute or relative to project root)"),
|
|
42302
|
-
startLine: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("1-based line to start reading from"),
|
|
42303
|
-
endLine: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("1-based line to stop reading at (inclusive)"),
|
|
42304
|
-
limit: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("Max lines
|
|
42305
|
-
offset: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("1-based line
|
|
42883
|
+
startLine: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("1-based line or directory entry to start reading from"),
|
|
42884
|
+
endLine: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("1-based line or directory entry to stop reading at (inclusive)"),
|
|
42885
|
+
limit: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("Max lines (default: 2000) or directory entries (default and cap: 1000) to return"),
|
|
42886
|
+
offset: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("1-based line or directory entry to start reading from (use with limit). Ignored if startLine is provided")
|
|
42306
42887
|
},
|
|
42307
42888
|
execute: async (args, context) => {
|
|
42308
42889
|
const file = args.path;
|
|
42309
|
-
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
42890
|
+
const projectRoot = await measurePreStage("directory", () => resolveProjectRoot(ctx, context));
|
|
42310
42891
|
const filePath = resolvePathFromProjectRoot(projectRoot, file);
|
|
42311
42892
|
persistFilePathAlias(args, context);
|
|
42312
42893
|
{
|
|
42313
|
-
const denial = await assertExternalDirectoryPermission(ctx, context, filePath, {
|
|
42894
|
+
const denial = await measurePreStage("permission", () => assertExternalDirectoryPermission(ctx, context, filePath, {
|
|
42314
42895
|
serverValidatedRead: true
|
|
42315
|
-
});
|
|
42896
|
+
}));
|
|
42316
42897
|
if (denial)
|
|
42317
42898
|
return permissionDeniedResponse(denial);
|
|
42318
42899
|
}
|
|
42319
42900
|
try {
|
|
42320
|
-
await runAsk(context.ask({
|
|
42901
|
+
await measurePreStage("permission", () => runAsk(context.ask({
|
|
42321
42902
|
permission: "read",
|
|
42322
42903
|
patterns: [permissionPath(context, filePath)],
|
|
42323
42904
|
always: ["*"],
|
|
42324
42905
|
metadata: {}
|
|
42325
|
-
}));
|
|
42906
|
+
})));
|
|
42326
42907
|
} catch (error) {
|
|
42327
42908
|
const failure = classifyPermissionError(error);
|
|
42328
42909
|
return permissionDeniedResponse(failure.kind === "rule_denied" ? permissionRuleDenial("read") : failure.message);
|
|
@@ -42346,7 +42927,8 @@ function createReadTool(ctx) {
|
|
|
42346
42927
|
rawArgs.endLine = endLine;
|
|
42347
42928
|
if (rawLimit !== undefined && rawOffset === undefined)
|
|
42348
42929
|
rawArgs.limit = rawLimit;
|
|
42349
|
-
const
|
|
42930
|
+
const mediaCandidate = isGithubResourcePath(file) || /\.(png|jpe?g|gif|webp|pdf)$/i.test(filePath) && await stat2(filePath).then((info) => info.isFile(), () => false);
|
|
42931
|
+
const visionCapability = mediaCandidate ? await measurePreStage("capability", () => currentSessionVisionCapability(ctx.client, context.sessionID)) : undefined;
|
|
42350
42932
|
if (visionCapability !== undefined)
|
|
42351
42933
|
rawArgs.vision_capability = visionCapability;
|
|
42352
42934
|
const response = await callToolCall(ctx, context, "read", rawArgs);
|
|
@@ -42790,7 +43372,7 @@ function createApplyPatchTool(ctx) {
|
|
|
42790
43372
|
};
|
|
42791
43373
|
}
|
|
42792
43374
|
function deleteDescription(ctx) {
|
|
42793
|
-
const backupText = ctx.config.backup?.enabled === false ? "Backup capture is disabled by user config, so this tool does not create undo snapshots. " : "Each file is backed up before deletion — use aft_safety undo to recover any of them.
|
|
43375
|
+
const backupText = ctx.config.backup?.enabled === false ? "Backup capture is disabled by user config, so this tool does not create undo snapshots. A directory tree containing a mount point of another filesystem is still refused. " : "Each file is backed up before deletion — use aft_safety undo to recover any of them. A recursive delete backs up the whole tree: directories (empty ones too, with their permissions), file contents, hard links (relinked by undo) and symlinks (the link itself, never its target; restored exactly, even when dangling). Sockets are deleted but undo does not restore them, and a file hard-linked to paths outside the tree comes back as an independent copy; both are reported as warnings. Refused before anything is deleted: mount points of another filesystem, named pipes, device nodes, and symlinks undo cannot recreate exactly (non-UTF-8 target, or on Windows). Paths under the system temp directory are never backed up, so only mount points are refused there. The deleted file's contents stay in the undo store until its retention expires. A recursive delete whose backup would record more than 2,000 entries (files, directories and links) or copy 100 MiB in one call is refused before anything is deleted; delete such a tree in smaller pieces, or use bash `rm -rf` when no undo is needed. ";
|
|
42794
43376
|
return `Delete one or more files (or directories).
|
|
42795
43377
|
|
|
42796
43378
|
` + backupText + `Directory deletion requires recursive: true. Without it, passing a directory returns an error.
|
|
@@ -43006,7 +43588,7 @@ async function resolveAndGateScope(ctx, context, scope) {
|
|
|
43006
43588
|
}
|
|
43007
43589
|
return { scope: Array.isArray(scope) ? resolved : resolved[0] };
|
|
43008
43590
|
}
|
|
43009
|
-
function
|
|
43591
|
+
function asRecord(value) {
|
|
43010
43592
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
43011
43593
|
}
|
|
43012
43594
|
function asString(value) {
|
|
@@ -43014,7 +43596,7 @@ function asString(value) {
|
|
|
43014
43596
|
}
|
|
43015
43597
|
function firstRecord(...values) {
|
|
43016
43598
|
for (const value of values) {
|
|
43017
|
-
const record =
|
|
43599
|
+
const record = asRecord(value);
|
|
43018
43600
|
if (record)
|
|
43019
43601
|
return record;
|
|
43020
43602
|
}
|
|
@@ -43049,7 +43631,7 @@ function parseInspectPhaseEntries(value) {
|
|
|
43049
43631
|
if (!Array.isArray(value))
|
|
43050
43632
|
return [];
|
|
43051
43633
|
return value.flatMap((candidate) => {
|
|
43052
|
-
const entry =
|
|
43634
|
+
const entry = asRecord(candidate);
|
|
43053
43635
|
const id = asString(entry?.id);
|
|
43054
43636
|
if (!id)
|
|
43055
43637
|
return [];
|
|
@@ -43065,7 +43647,7 @@ function parseInspectPhaseEntries(value) {
|
|
|
43065
43647
|
});
|
|
43066
43648
|
}
|
|
43067
43649
|
function parseInspectTerminal(payload) {
|
|
43068
|
-
const response =
|
|
43650
|
+
const response = asRecord(payload);
|
|
43069
43651
|
if (!response)
|
|
43070
43652
|
return;
|
|
43071
43653
|
const kind = terminalKind(response);
|
|
@@ -43080,7 +43662,7 @@ function parseInspectTerminal(payload) {
|
|
|
43080
43662
|
waitStampText: kind === "FRESH" ? firstString(waitStamp?.text, waitStamp?.human_text) : undefined
|
|
43081
43663
|
};
|
|
43082
43664
|
}
|
|
43083
|
-
const failedPhaseRecord =
|
|
43665
|
+
const failedPhaseRecord = asRecord(response.failed_phase);
|
|
43084
43666
|
const failedPhaseId = firstString(failedPhaseRecord?.id, response.failed_phase);
|
|
43085
43667
|
const failedPhase = failedPhaseId ? parseInspectPhaseEntries([
|
|
43086
43668
|
{
|
|
@@ -43853,7 +44435,7 @@ function hasMeaningfulProjectSearchFallback(query, pathArg, externalRoot) {
|
|
|
43853
44435
|
return trimmedQuery.length > 0 && trimmedQuery !== pathArg && trimmedQuery !== externalRoot;
|
|
43854
44436
|
}
|
|
43855
44437
|
var GENERATION_CHANGED_DISCLOSURE = "index changed - order re-derived";
|
|
43856
|
-
function
|
|
44438
|
+
function asRecord2(value) {
|
|
43857
44439
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
43858
44440
|
}
|
|
43859
44441
|
function normalizeContinuityQuery(query) {
|
|
@@ -43868,14 +44450,14 @@ function continuityKey(projectRoot, query, includeTests, topK) {
|
|
|
43868
44450
|
]);
|
|
43869
44451
|
}
|
|
43870
44452
|
function responseGeneration(response) {
|
|
43871
|
-
const envelope =
|
|
43872
|
-
const structured =
|
|
43873
|
-
const plan =
|
|
44453
|
+
const envelope = asRecord2(response);
|
|
44454
|
+
const structured = asRecord2(envelope?.structuredContent) ?? asRecord2(envelope?.structured_content);
|
|
44455
|
+
const plan = asRecord2(envelope?.plan) ?? asRecord2(structured?.plan);
|
|
43874
44456
|
const generation = plan?.snapshot_generation ?? envelope?.snapshot_generation;
|
|
43875
44457
|
return typeof generation === "string" ? generation : undefined;
|
|
43876
44458
|
}
|
|
43877
44459
|
function surfaceSearchText(response, continuity, sessionId, key) {
|
|
43878
|
-
const envelope =
|
|
44460
|
+
const envelope = asRecord2(response);
|
|
43879
44461
|
const text = typeof envelope?.text === "string" ? envelope.text : "";
|
|
43880
44462
|
const generation = responseGeneration(response);
|
|
43881
44463
|
if (generation === undefined)
|
|
@@ -44153,6 +44735,8 @@ var defaultBridgeBootstrapDependencies = {
|
|
|
44153
44735
|
loadConfig: loadAftConfig,
|
|
44154
44736
|
deliverLoadNotices: (notify) => deliverConfigLoadNotices(notify, getConfigLoadNotices()),
|
|
44155
44737
|
configLoadErrors: getConfigLoadErrors,
|
|
44738
|
+
configLoadSources: getConfigLoadSources,
|
|
44739
|
+
configLoadTexts: getConfigLoadTexts,
|
|
44156
44740
|
subcConnectionFileError,
|
|
44157
44741
|
migrateConfigLocations: (directory) => migrateAftConfigLocations(directory, bridgeLogger).flatMap((result) => result.warnings),
|
|
44158
44742
|
resolveBinary: resolveBinaryWithWarmup,
|
|
@@ -44194,8 +44778,12 @@ function loadBootstrapConfig(directory, notify, dependencies = defaultBridgeBoot
|
|
|
44194
44778
|
const failure = parseFailure(dependencies);
|
|
44195
44779
|
if (failure)
|
|
44196
44780
|
return configErrorState(failure, notify);
|
|
44781
|
+
const provenance = dependencies.configLoadSources ? {
|
|
44782
|
+
sources: [...dependencies.configLoadSources()],
|
|
44783
|
+
sourceTexts: Object.fromEntries(dependencies.configLoadTexts?.() ?? [])
|
|
44784
|
+
} : {};
|
|
44197
44785
|
dependencies.deliverLoadNotices?.(notify);
|
|
44198
|
-
return { ok: true, config };
|
|
44786
|
+
return { ok: true, config, ...provenance };
|
|
44199
44787
|
} catch (err) {
|
|
44200
44788
|
return configErrorState(err instanceof Error ? err.message : String(err), notify);
|
|
44201
44789
|
}
|
|
@@ -44387,8 +44975,60 @@ function buildConfigErrorToolMap(config, message, client, buildToolMap = buildAf
|
|
|
44387
44975
|
return failEveryToolCall(buildToolMap(ctx, config), message);
|
|
44388
44976
|
}
|
|
44389
44977
|
|
|
44978
|
+
// src/config-live-reload.ts
|
|
44979
|
+
var OPENCODE_LIVE_CONFIG_KEYS = aftLiveConfigKeys((config) => resolveBashConfig(config));
|
|
44980
|
+
function projectTextOf(directory) {
|
|
44981
|
+
const { projectConfigPath } = resolveCortexKitConfigPaths(directory);
|
|
44982
|
+
return getConfigLoadTexts().get(projectConfigPath) ?? null;
|
|
44983
|
+
}
|
|
44984
|
+
function loadOpenCodeConfigForLiveReload(directory) {
|
|
44985
|
+
try {
|
|
44986
|
+
const config = loadAftConfig(directory);
|
|
44987
|
+
const [failure] = getConfigLoadErrors();
|
|
44988
|
+
if (failure) {
|
|
44989
|
+
return { ok: false, message: formatConfigParseErrorMessage(failure.path, failure.message) };
|
|
44990
|
+
}
|
|
44991
|
+
const [invalid] = getConfigValidationErrors();
|
|
44992
|
+
if (invalid) {
|
|
44993
|
+
return {
|
|
44994
|
+
ok: false,
|
|
44995
|
+
message: `AFT config at ${invalid.path} has an invalid setting: ${invalid.message}`
|
|
44996
|
+
};
|
|
44997
|
+
}
|
|
44998
|
+
return {
|
|
44999
|
+
ok: true,
|
|
45000
|
+
config,
|
|
45001
|
+
sources: [...getConfigLoadSources()],
|
|
45002
|
+
projectText: projectTextOf(directory),
|
|
45003
|
+
texts: Object.fromEntries(getConfigLoadTexts())
|
|
45004
|
+
};
|
|
45005
|
+
} catch (err) {
|
|
45006
|
+
return { ok: false, message: err instanceof Error ? err.message : String(err) };
|
|
45007
|
+
}
|
|
45008
|
+
}
|
|
45009
|
+
function startOpenCodeLiveConfigReload(options) {
|
|
45010
|
+
const { userConfigPath, projectConfigPath } = resolveCortexKitConfigPaths(options.directory);
|
|
45011
|
+
return startLiveConfigReload({
|
|
45012
|
+
paths: [userConfigPath, projectConfigPath],
|
|
45013
|
+
load: () => loadOpenCodeConfigForLiveReload(options.directory),
|
|
45014
|
+
initialSources: options.initialSources,
|
|
45015
|
+
initialProjectText: options.initialSourceTexts?.[projectConfigPath] ?? null,
|
|
45016
|
+
initialTexts: options.initialSourceTexts,
|
|
45017
|
+
securityKeys: aftLiveSecurityKeys(OPENCODE_LIVE_CONFIG_KEYS),
|
|
45018
|
+
keys: OPENCODE_LIVE_CONFIG_KEYS,
|
|
45019
|
+
getConfig: options.getConfig,
|
|
45020
|
+
setConfig: options.setConfig,
|
|
45021
|
+
log: (message) => log2(`${message} (${options.directory})`),
|
|
45022
|
+
reportError: (message) => {
|
|
45023
|
+
error2(message);
|
|
45024
|
+
options.notify(message);
|
|
45025
|
+
},
|
|
45026
|
+
watch: options.watch
|
|
45027
|
+
});
|
|
45028
|
+
}
|
|
45029
|
+
|
|
44390
45030
|
// src/notifications.ts
|
|
44391
|
-
import { existsSync as existsSync18, readFileSync as
|
|
45031
|
+
import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
|
|
44392
45032
|
import { homedir as homedir13, platform } from "node:os";
|
|
44393
45033
|
import { join as join20 } from "node:path";
|
|
44394
45034
|
function isTuiMode() {
|
|
@@ -44430,7 +45070,7 @@ function readDesktopState() {
|
|
|
44430
45070
|
return { serverUrl: null };
|
|
44431
45071
|
}
|
|
44432
45072
|
try {
|
|
44433
|
-
const raw =
|
|
45073
|
+
const raw = readFileSync15(statePath, "utf-8");
|
|
44434
45074
|
const state = JSON.parse(raw);
|
|
44435
45075
|
let serverUrl = null;
|
|
44436
45076
|
const serverStr = state.server;
|
|
@@ -44929,23 +45569,25 @@ import {
|
|
|
44929
45569
|
existsSync as existsSync21,
|
|
44930
45570
|
mkdirSync as mkdirSync9,
|
|
44931
45571
|
openSync as openSync7,
|
|
44932
|
-
readFileSync as
|
|
45572
|
+
readFileSync as readFileSync18,
|
|
44933
45573
|
renameSync as renameSync11,
|
|
44934
45574
|
rmSync as rmSync8,
|
|
44935
|
-
statSync as
|
|
45575
|
+
statSync as statSync15,
|
|
44936
45576
|
writeFileSync as writeFileSync12
|
|
44937
45577
|
} from "node:fs";
|
|
44938
|
-
import { dirname as
|
|
45578
|
+
import { dirname as dirname15 } from "node:path";
|
|
44939
45579
|
|
|
44940
45580
|
// src/hooks/auto-update-checker/cache.ts
|
|
44941
|
-
import { cpSync, existsSync as existsSync20, mkdtempSync, readFileSync as
|
|
45581
|
+
import { cpSync, existsSync as existsSync20, mkdtempSync, readFileSync as readFileSync17, rmSync as rmSync7, writeFileSync as writeFileSync11 } from "node:fs";
|
|
44942
45582
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
44943
|
-
import { basename as
|
|
45583
|
+
import { basename as basename6, dirname as dirname14, join as join23 } from "node:path";
|
|
44944
45584
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
44945
45585
|
|
|
44946
45586
|
// src/hooks/auto-update-checker/checker.ts
|
|
44947
|
-
import { existsSync as existsSync19, readFileSync as
|
|
44948
|
-
import {
|
|
45587
|
+
import { existsSync as existsSync19, readFileSync as readFileSync16, statSync as statSync14, writeFileSync as writeFileSync10 } from "node:fs";
|
|
45588
|
+
import { readFile } from "node:fs/promises";
|
|
45589
|
+
import { homedir as homedir14 } from "node:os";
|
|
45590
|
+
import { dirname as dirname13, isAbsolute as isAbsolute11, join as join22, resolve as resolve13 } from "node:path";
|
|
44949
45591
|
import { fileURLToPath } from "node:url";
|
|
44950
45592
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
44951
45593
|
|
|
@@ -45036,14 +45678,14 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
45036
45678
|
}
|
|
45037
45679
|
if (isAbsolute11(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
45038
45680
|
return spec;
|
|
45039
|
-
return resolve13(
|
|
45681
|
+
return resolve13(dirname13(configPath), spec);
|
|
45040
45682
|
}
|
|
45041
45683
|
function getLocalDevPath(directory) {
|
|
45042
45684
|
for (const configPath of getConfigPaths(directory)) {
|
|
45043
45685
|
try {
|
|
45044
45686
|
if (!existsSync19(configPath))
|
|
45045
45687
|
continue;
|
|
45046
|
-
const rawConfig = parseJsonConfig(
|
|
45688
|
+
const rawConfig = parseJsonConfig(readFileSync16(configPath, "utf-8"));
|
|
45047
45689
|
const plugins = getPluginEntries(rawConfig);
|
|
45048
45690
|
for (const entry of plugins) {
|
|
45049
45691
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
@@ -45053,7 +45695,7 @@ function getLocalDevPath(directory) {
|
|
|
45053
45695
|
const pkgPath = findPackageJsonUp(localPath);
|
|
45054
45696
|
if (!pkgPath)
|
|
45055
45697
|
continue;
|
|
45056
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
45698
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync16(pkgPath, "utf-8")));
|
|
45057
45699
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
45058
45700
|
return localPath;
|
|
45059
45701
|
}
|
|
@@ -45064,18 +45706,18 @@ function getLocalDevPath(directory) {
|
|
|
45064
45706
|
}
|
|
45065
45707
|
function findPackageJsonUp(startPath) {
|
|
45066
45708
|
try {
|
|
45067
|
-
const stat =
|
|
45068
|
-
let dir = stat.isDirectory() ? startPath :
|
|
45709
|
+
const stat = statSync14(startPath);
|
|
45710
|
+
let dir = stat.isDirectory() ? startPath : dirname13(startPath);
|
|
45069
45711
|
for (let i = 0;i < 10; i++) {
|
|
45070
45712
|
const pkgPath = join22(dir, "package.json");
|
|
45071
45713
|
if (existsSync19(pkgPath)) {
|
|
45072
45714
|
try {
|
|
45073
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
45715
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync16(pkgPath, "utf-8")));
|
|
45074
45716
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
45075
45717
|
return pkgPath;
|
|
45076
45718
|
} catch {}
|
|
45077
45719
|
}
|
|
45078
|
-
const parent =
|
|
45720
|
+
const parent = dirname13(dir);
|
|
45079
45721
|
if (parent === dir)
|
|
45080
45722
|
break;
|
|
45081
45723
|
dir = parent;
|
|
@@ -45091,7 +45733,7 @@ function getLocalDevVersion(directory) {
|
|
|
45091
45733
|
const pkgPath = findPackageJsonUp(localPath);
|
|
45092
45734
|
if (!pkgPath)
|
|
45093
45735
|
return null;
|
|
45094
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
45736
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync16(pkgPath, "utf-8")));
|
|
45095
45737
|
return pkg.success ? pkg.data.version ?? null : null;
|
|
45096
45738
|
} catch {
|
|
45097
45739
|
return null;
|
|
@@ -45099,7 +45741,7 @@ function getLocalDevVersion(directory) {
|
|
|
45099
45741
|
}
|
|
45100
45742
|
function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
|
|
45101
45743
|
try {
|
|
45102
|
-
return findPackageJsonUp(
|
|
45744
|
+
return findPackageJsonUp(dirname13(fileURLToPath(currentModuleUrl)));
|
|
45103
45745
|
} catch (err) {
|
|
45104
45746
|
warn2(`[auto-update-checker] Failed to resolve runtime package path: ${String(err)}`);
|
|
45105
45747
|
return null;
|
|
@@ -45110,7 +45752,7 @@ function findPluginEntry(directory) {
|
|
|
45110
45752
|
try {
|
|
45111
45753
|
if (!existsSync19(configPath))
|
|
45112
45754
|
continue;
|
|
45113
|
-
const rawConfig = parseJsonConfig(
|
|
45755
|
+
const rawConfig = parseJsonConfig(readFileSync16(configPath, "utf-8"));
|
|
45114
45756
|
const plugins = getPluginEntries(rawConfig);
|
|
45115
45757
|
for (const entry of plugins) {
|
|
45116
45758
|
if (entry === PACKAGE_NAME) {
|
|
@@ -45143,7 +45785,7 @@ function getCachedVersion(spec) {
|
|
|
45143
45785
|
try {
|
|
45144
45786
|
if (!existsSync19(packageJsonPath))
|
|
45145
45787
|
continue;
|
|
45146
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
45788
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync16(packageJsonPath, "utf-8")));
|
|
45147
45789
|
if (pkg.success && pkg.data.version) {
|
|
45148
45790
|
if (!spec)
|
|
45149
45791
|
cachedPackageVersion = pkg.data.version;
|
|
@@ -45153,6 +45795,117 @@ function getCachedVersion(spec) {
|
|
|
45153
45795
|
}
|
|
45154
45796
|
return null;
|
|
45155
45797
|
}
|
|
45798
|
+
var registryCache = new Map;
|
|
45799
|
+
function npmConfigGet(key, directory) {
|
|
45800
|
+
return new Promise((resolve, reject) => {
|
|
45801
|
+
execFile(process.platform === "win32" ? "npm.cmd" : "npm", ["config", "get", key], {
|
|
45802
|
+
cwd: directory,
|
|
45803
|
+
timeout: NPM_FETCH_TIMEOUT,
|
|
45804
|
+
windowsHide: true,
|
|
45805
|
+
shell: process.platform === "win32"
|
|
45806
|
+
}, (error, stdout) => {
|
|
45807
|
+
if (error)
|
|
45808
|
+
reject(error);
|
|
45809
|
+
else
|
|
45810
|
+
resolve(stdout.trim());
|
|
45811
|
+
});
|
|
45812
|
+
});
|
|
45813
|
+
}
|
|
45814
|
+
function configuredRegistry(value) {
|
|
45815
|
+
return value && value !== "undefined" && value !== "null" ? value : undefined;
|
|
45816
|
+
}
|
|
45817
|
+
async function readRegistrySettings(path, required = false) {
|
|
45818
|
+
let text;
|
|
45819
|
+
try {
|
|
45820
|
+
text = await readFile(path, "utf8");
|
|
45821
|
+
} catch (error) {
|
|
45822
|
+
if (!required && error.code === "ENOENT")
|
|
45823
|
+
return {};
|
|
45824
|
+
throw error;
|
|
45825
|
+
}
|
|
45826
|
+
const settings = {};
|
|
45827
|
+
for (const line of text.split(/\r?\n/)) {
|
|
45828
|
+
const trimmed = line.trim();
|
|
45829
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith(";"))
|
|
45830
|
+
continue;
|
|
45831
|
+
const separator = trimmed.indexOf("=");
|
|
45832
|
+
if (separator < 0)
|
|
45833
|
+
continue;
|
|
45834
|
+
const key = trimmed.slice(0, separator).trim();
|
|
45835
|
+
if (key === "registry" || key === "@cortexkit:registry") {
|
|
45836
|
+
settings[key] = configuredRegistry(trimmed.slice(separator + 1).trim());
|
|
45837
|
+
}
|
|
45838
|
+
}
|
|
45839
|
+
return settings;
|
|
45840
|
+
}
|
|
45841
|
+
function registryEnvironment(key) {
|
|
45842
|
+
const variable = `npm_config_${key}`;
|
|
45843
|
+
const value = process.env[variable] ?? Object.entries(process.env).find(([name]) => name.toLowerCase() === variable)?.[1];
|
|
45844
|
+
return configuredRegistry(value ?? "");
|
|
45845
|
+
}
|
|
45846
|
+
async function registryWithoutNpm(directory) {
|
|
45847
|
+
let scoped = registryEnvironment("@cortexkit:registry");
|
|
45848
|
+
let registry = registryEnvironment("registry");
|
|
45849
|
+
const visited = new Set;
|
|
45850
|
+
for (let current = directory;; current = dirname13(current)) {
|
|
45851
|
+
if (scoped)
|
|
45852
|
+
break;
|
|
45853
|
+
const path = join22(current, ".npmrc");
|
|
45854
|
+
visited.add(path);
|
|
45855
|
+
const settings = await readRegistrySettings(path);
|
|
45856
|
+
scoped ??= settings["@cortexkit:registry"];
|
|
45857
|
+
registry ??= settings.registry;
|
|
45858
|
+
if (dirname13(current) === current)
|
|
45859
|
+
break;
|
|
45860
|
+
}
|
|
45861
|
+
const explicitUserConfig = process.env.npm_config_userconfig ?? process.env.NPM_CONFIG_USERCONFIG;
|
|
45862
|
+
const home = (process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME) ?? homedir14();
|
|
45863
|
+
const userConfig = explicitUserConfig ?? join22(home, ".npmrc");
|
|
45864
|
+
if (!scoped && !visited.has(userConfig)) {
|
|
45865
|
+
const settings = await readRegistrySettings(userConfig, explicitUserConfig !== undefined);
|
|
45866
|
+
scoped = settings["@cortexkit:registry"];
|
|
45867
|
+
registry ??= settings.registry;
|
|
45868
|
+
}
|
|
45869
|
+
const selected = scoped ?? registry ?? NPM_REGISTRY_URL;
|
|
45870
|
+
return selected.replace(/\$\{([^}]+)\}/g, (_match, name) => {
|
|
45871
|
+
const value = process.env[name];
|
|
45872
|
+
if (value === undefined)
|
|
45873
|
+
throw new Error("Unresolved registry environment variable");
|
|
45874
|
+
return value;
|
|
45875
|
+
});
|
|
45876
|
+
}
|
|
45877
|
+
function validateRegistry(registry) {
|
|
45878
|
+
const url = new URL(registry);
|
|
45879
|
+
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
45880
|
+
throw new Error("Unsupported registry protocol");
|
|
45881
|
+
return registry;
|
|
45882
|
+
}
|
|
45883
|
+
var reportedRegistryFailures = new Set;
|
|
45884
|
+
function reportRegistryFailure(directory) {
|
|
45885
|
+
const key = resolve13(directory);
|
|
45886
|
+
if (reportedRegistryFailures.has(key))
|
|
45887
|
+
return;
|
|
45888
|
+
reportedRegistryFailures.add(key);
|
|
45889
|
+
debug2("[auto-update-checker] Configured npm registry could not be resolved or used; skipping update check.");
|
|
45890
|
+
}
|
|
45891
|
+
function resolveRegistry(directory) {
|
|
45892
|
+
const key = resolve13(directory);
|
|
45893
|
+
let pending = registryCache.get(key);
|
|
45894
|
+
if (!pending) {
|
|
45895
|
+
pending = (async () => {
|
|
45896
|
+
let registry;
|
|
45897
|
+
try {
|
|
45898
|
+
const scoped = configuredRegistry(await npmConfigGet("@cortexkit:registry", key));
|
|
45899
|
+
registry = scoped ?? configuredRegistry(await npmConfigGet("registry", key)) ?? NPM_REGISTRY_URL;
|
|
45900
|
+
} catch {
|
|
45901
|
+
registry = await registryWithoutNpm(key);
|
|
45902
|
+
}
|
|
45903
|
+
return validateRegistry(registry);
|
|
45904
|
+
})();
|
|
45905
|
+
registryCache.set(key, pending);
|
|
45906
|
+
}
|
|
45907
|
+
return pending;
|
|
45908
|
+
}
|
|
45156
45909
|
function buildRegistryUrl(registryUrl) {
|
|
45157
45910
|
return `${registryUrl.replace(/\/+$/, "")}/${encodeURIComponent(PACKAGE_NAME).replace("%2F", "/")}`;
|
|
45158
45911
|
}
|
|
@@ -45164,17 +45917,24 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
45164
45917
|
try {
|
|
45165
45918
|
if (options.signal?.aborted)
|
|
45166
45919
|
return null;
|
|
45167
|
-
const
|
|
45920
|
+
const registry = validateRegistry(options.registryUrl ?? await resolveRegistry(options.directory ?? process.cwd()));
|
|
45921
|
+
if (controller.signal.aborted)
|
|
45922
|
+
return null;
|
|
45923
|
+
const response = await fetch(buildRegistryUrl(registry), {
|
|
45168
45924
|
signal: controller.signal,
|
|
45169
45925
|
headers: { Accept: "application/json" }
|
|
45170
45926
|
});
|
|
45171
|
-
if (!response.ok)
|
|
45927
|
+
if (!response.ok) {
|
|
45928
|
+
reportRegistryFailure(options.directory ?? process.cwd());
|
|
45172
45929
|
return null;
|
|
45930
|
+
}
|
|
45173
45931
|
const data = NpmPackageEnvelopeSchema.safeParse(await response.json());
|
|
45174
45932
|
if (!data.success)
|
|
45175
45933
|
return null;
|
|
45176
45934
|
return data.data["dist-tags"][channel] ?? data.data["dist-tags"].latest ?? null;
|
|
45177
45935
|
} catch {
|
|
45936
|
+
if (!controller.signal.aborted)
|
|
45937
|
+
reportRegistryFailure(options.directory ?? process.cwd());
|
|
45178
45938
|
return null;
|
|
45179
45939
|
} finally {
|
|
45180
45940
|
options.signal?.removeEventListener("abort", abortHandler);
|
|
@@ -45194,9 +45954,9 @@ function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
|
45194
45954
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
45195
45955
|
return {
|
|
45196
45956
|
packageJsonPath,
|
|
45197
|
-
packageJson: existsSync20(packageJsonPath) ?
|
|
45957
|
+
packageJson: existsSync20(packageJsonPath) ? readFileSync17(packageJsonPath, "utf-8") : null,
|
|
45198
45958
|
lockfilePath,
|
|
45199
|
-
lockfile: existsSync20(lockfilePath) ?
|
|
45959
|
+
lockfile: existsSync20(lockfilePath) ? readFileSync17(lockfilePath, "utf-8") : null,
|
|
45200
45960
|
packageDir,
|
|
45201
45961
|
stagedPackageDir,
|
|
45202
45962
|
tempDir
|
|
@@ -45223,9 +45983,9 @@ function restoreAutoUpdateSnapshot(snapshot) {
|
|
|
45223
45983
|
function stripPackageNameFromPath(pathValue, packageName) {
|
|
45224
45984
|
let current = pathValue;
|
|
45225
45985
|
for (const segment of [...packageName.split("/")].reverse()) {
|
|
45226
|
-
if (
|
|
45986
|
+
if (basename6(current) !== segment)
|
|
45227
45987
|
return null;
|
|
45228
|
-
current =
|
|
45988
|
+
current = dirname14(current);
|
|
45229
45989
|
}
|
|
45230
45990
|
return current;
|
|
45231
45991
|
}
|
|
@@ -45234,7 +45994,7 @@ function removeFromPackageLock(installDir, packageName) {
|
|
|
45234
45994
|
if (!existsSync20(lockPath))
|
|
45235
45995
|
return false;
|
|
45236
45996
|
try {
|
|
45237
|
-
const lock = import_comment_json3.parse(
|
|
45997
|
+
const lock = import_comment_json3.parse(readFileSync17(lockPath, "utf-8"));
|
|
45238
45998
|
let modified = false;
|
|
45239
45999
|
if (lock.packages) {
|
|
45240
46000
|
const key = `node_modules/${packageName}`;
|
|
@@ -45260,7 +46020,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version) {
|
|
|
45260
46020
|
if (!existsSync20(packageJsonPath))
|
|
45261
46021
|
return false;
|
|
45262
46022
|
try {
|
|
45263
|
-
const raw = import_comment_json3.parse(
|
|
46023
|
+
const raw = import_comment_json3.parse(readFileSync17(packageJsonPath, "utf-8"));
|
|
45264
46024
|
const pkgJson = PackageJsonSchema.safeParse(raw);
|
|
45265
46025
|
if (!pkgJson.success)
|
|
45266
46026
|
return false;
|
|
@@ -45295,17 +46055,17 @@ function removeInstalledPackage(installDir, packageName) {
|
|
|
45295
46055
|
}
|
|
45296
46056
|
function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackageJsonPath()) {
|
|
45297
46057
|
if (runtimePackageJsonPath) {
|
|
45298
|
-
const packageDir =
|
|
46058
|
+
const packageDir = dirname14(runtimePackageJsonPath);
|
|
45299
46059
|
const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
|
|
45300
|
-
if (nodeModulesDir &&
|
|
45301
|
-
const installDir =
|
|
46060
|
+
if (nodeModulesDir && basename6(nodeModulesDir) === "node_modules") {
|
|
46061
|
+
const installDir = dirname14(nodeModulesDir);
|
|
45302
46062
|
const packageJsonPath = join23(installDir, "package.json");
|
|
45303
46063
|
if (existsSync20(packageJsonPath))
|
|
45304
46064
|
return { installDir, packageJsonPath };
|
|
45305
46065
|
}
|
|
45306
46066
|
return null;
|
|
45307
46067
|
}
|
|
45308
|
-
const cacheRoot =
|
|
46068
|
+
const cacheRoot = dirname14(cacheDir());
|
|
45309
46069
|
const legacyPackageJsonPath = join23(cacheRoot, "package.json");
|
|
45310
46070
|
if (existsSync20(legacyPackageJsonPath)) {
|
|
45311
46071
|
return { installDir: cacheRoot, packageJsonPath: legacyPackageJsonPath };
|
|
@@ -45508,7 +46268,7 @@ function claimCheckSlot(storageDir, intervalMs) {
|
|
|
45508
46268
|
try {
|
|
45509
46269
|
if (hasRecentCheckTimestamp(file, intervalMs))
|
|
45510
46270
|
return null;
|
|
45511
|
-
mkdirSync9(
|
|
46271
|
+
mkdirSync9(dirname15(file), { recursive: true });
|
|
45512
46272
|
const lockPath = `${file}.lock`;
|
|
45513
46273
|
const owner = { pid: process.pid, startedMs: Date.now() };
|
|
45514
46274
|
let lockFd = null;
|
|
@@ -45579,9 +46339,9 @@ function isOrphanedCheckLock(lockPath) {
|
|
|
45579
46339
|
}
|
|
45580
46340
|
}
|
|
45581
46341
|
function readCheckLockState(lockPath) {
|
|
45582
|
-
const fallbackStartedMs =
|
|
46342
|
+
const fallbackStartedMs = statSync15(lockPath).mtimeMs;
|
|
45583
46343
|
try {
|
|
45584
|
-
const parsed = JSON.parse(
|
|
46344
|
+
const parsed = JSON.parse(readFileSync18(lockPath, "utf-8"));
|
|
45585
46345
|
const pid = Number.isSafeInteger(parsed.pid) && (parsed.pid ?? 0) > 0 ? parsed.pid ?? null : null;
|
|
45586
46346
|
const startedMs = typeof parsed.startedMs === "number" && Number.isFinite(parsed.startedMs) ? parsed.startedMs : fallbackStartedMs;
|
|
45587
46347
|
return { pid, startedMs };
|
|
@@ -45591,7 +46351,7 @@ function readCheckLockState(lockPath) {
|
|
|
45591
46351
|
}
|
|
45592
46352
|
function checkLockIsOwnedBy(lockPath, owner) {
|
|
45593
46353
|
try {
|
|
45594
|
-
const parsed = JSON.parse(
|
|
46354
|
+
const parsed = JSON.parse(readFileSync18(lockPath, "utf-8"));
|
|
45595
46355
|
return parsed.pid === owner.pid && parsed.startedMs === owner.startedMs;
|
|
45596
46356
|
} catch {
|
|
45597
46357
|
return false;
|
|
@@ -45601,7 +46361,7 @@ function hasRecentCheckTimestamp(file, intervalMs) {
|
|
|
45601
46361
|
if (!existsSync21(file))
|
|
45602
46362
|
return false;
|
|
45603
46363
|
try {
|
|
45604
|
-
const raw = JSON.parse(
|
|
46364
|
+
const raw = JSON.parse(readFileSync18(file, "utf-8"));
|
|
45605
46365
|
const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
|
|
45606
46366
|
return Number.isFinite(last) && Date.now() - last < intervalMs;
|
|
45607
46367
|
} catch {
|
|
@@ -45657,6 +46417,7 @@ async function runBackgroundUpdateCheck(ctx, options) {
|
|
|
45657
46417
|
const channel = extractChannel(pluginInfo.pinnedVersion ?? currentVersion);
|
|
45658
46418
|
const latestVersion = await getLatestVersion(channel, {
|
|
45659
46419
|
registryUrl: options.npmRegistryUrl,
|
|
46420
|
+
directory: ctx.directory,
|
|
45660
46421
|
timeoutMs: options.fetchTimeoutMs,
|
|
45661
46422
|
signal: options.signal
|
|
45662
46423
|
});
|
|
@@ -45797,13 +46558,13 @@ import {
|
|
|
45797
46558
|
existsSync as existsSync22,
|
|
45798
46559
|
mkdirSync as mkdirSync10,
|
|
45799
46560
|
readdirSync as readdirSync6,
|
|
45800
|
-
readFileSync as
|
|
46561
|
+
readFileSync as readFileSync19,
|
|
45801
46562
|
renameSync as renameSync12,
|
|
45802
46563
|
unlinkSync as unlinkSync8,
|
|
45803
46564
|
writeFileSync as writeFileSync13
|
|
45804
46565
|
} from "node:fs";
|
|
45805
46566
|
import { createServer } from "node:http";
|
|
45806
|
-
import { dirname as
|
|
46567
|
+
import { dirname as dirname16, join as join25 } from "node:path";
|
|
45807
46568
|
|
|
45808
46569
|
// src/shared/rpc-utils.ts
|
|
45809
46570
|
import { join as join24 } from "node:path";
|
|
@@ -45953,7 +46714,7 @@ class AftRpcServer {
|
|
|
45953
46714
|
}
|
|
45954
46715
|
}
|
|
45955
46716
|
writePortFile() {
|
|
45956
|
-
const dir =
|
|
46717
|
+
const dir = dirname16(this.portFilePath);
|
|
45957
46718
|
mkdirSync10(dir, { recursive: true, mode: 448 });
|
|
45958
46719
|
const tmpPath = `${this.portFilePath}.tmp`;
|
|
45959
46720
|
writeFileSync13(tmpPath, JSON.stringify({
|
|
@@ -45978,7 +46739,7 @@ class AftRpcServer {
|
|
|
45978
46739
|
if (filePath === this.portFilePath)
|
|
45979
46740
|
continue;
|
|
45980
46741
|
try {
|
|
45981
|
-
const record = parseRpcPortRecord(
|
|
46742
|
+
const record = parseRpcPortRecord(readFileSync19(filePath, "utf-8"));
|
|
45982
46743
|
if (record === null) {
|
|
45983
46744
|
unlinkSync8(filePath);
|
|
45984
46745
|
continue;
|
|
@@ -46193,7 +46954,7 @@ function formatSemanticIndexLabel(semantic) {
|
|
|
46193
46954
|
backendUrl: semantic.backend_url
|
|
46194
46955
|
});
|
|
46195
46956
|
}
|
|
46196
|
-
function
|
|
46957
|
+
function asRecord3(value) {
|
|
46197
46958
|
return typeof value === "object" && value !== null ? value : {};
|
|
46198
46959
|
}
|
|
46199
46960
|
function readString(value, fallback = "") {
|
|
@@ -46212,7 +46973,7 @@ function readOptionalNumber(value) {
|
|
|
46212
46973
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
46213
46974
|
}
|
|
46214
46975
|
function readCompressionAggregate(value) {
|
|
46215
|
-
const aggregate =
|
|
46976
|
+
const aggregate = asRecord3(value);
|
|
46216
46977
|
return {
|
|
46217
46978
|
events: readNumber(aggregate.events),
|
|
46218
46979
|
original_tokens: readNumber(aggregate.original_tokens),
|
|
@@ -46223,7 +46984,7 @@ function readCompressionAggregate(value) {
|
|
|
46223
46984
|
function readCompression(value) {
|
|
46224
46985
|
if (typeof value !== "object" || value === null)
|
|
46225
46986
|
return;
|
|
46226
|
-
const compression =
|
|
46987
|
+
const compression = asRecord3(value);
|
|
46227
46988
|
return {
|
|
46228
46989
|
project: readCompressionAggregate(compression.project),
|
|
46229
46990
|
session: readCompressionAggregate(compression.session)
|
|
@@ -46232,7 +46993,7 @@ function readCompression(value) {
|
|
|
46232
46993
|
function readStatusBar(value) {
|
|
46233
46994
|
if (typeof value !== "object" || value === null)
|
|
46234
46995
|
return;
|
|
46235
|
-
const bar =
|
|
46996
|
+
const bar = asRecord3(value);
|
|
46236
46997
|
const errors = readOptionalNumber(bar.errors);
|
|
46237
46998
|
const warnings = readOptionalNumber(bar.warnings);
|
|
46238
46999
|
const deadCode = readOptionalNumber(bar.dead_code);
|
|
@@ -46290,17 +47051,17 @@ function formatBytes(bytes) {
|
|
|
46290
47051
|
return `${value.toFixed(decimals)} ${units[unitIndex]}`;
|
|
46291
47052
|
}
|
|
46292
47053
|
function coerceAftStatus(response) {
|
|
46293
|
-
const features =
|
|
46294
|
-
const searchIndex =
|
|
46295
|
-
const semanticIndex =
|
|
47054
|
+
const features = asRecord3(response.features);
|
|
47055
|
+
const searchIndex = asRecord3(response.search_index);
|
|
47056
|
+
const semanticIndex = asRecord3(response.semantic_index);
|
|
46296
47057
|
const semanticConfig = {
|
|
46297
|
-
...
|
|
46298
|
-
...
|
|
47058
|
+
...asRecord3(response.semantic),
|
|
47059
|
+
...asRecord3(response.semantic_config)
|
|
46299
47060
|
};
|
|
46300
|
-
const disk =
|
|
46301
|
-
const symbolCache =
|
|
46302
|
-
const runtime =
|
|
46303
|
-
const session =
|
|
47061
|
+
const disk = asRecord3(response.disk);
|
|
47062
|
+
const symbolCache = asRecord3(response.symbol_cache);
|
|
47063
|
+
const runtime = asRecord3(response.runtime);
|
|
47064
|
+
const session = asRecord3(response.session);
|
|
46304
47065
|
return {
|
|
46305
47066
|
version: readString(response.version, "unknown"),
|
|
46306
47067
|
project_root: readNullableString(response.project_root),
|
|
@@ -46841,6 +47602,16 @@ async function initializePluginForDirectory(input) {
|
|
|
46841
47602
|
storageDir: configOverrides.storage_dir,
|
|
46842
47603
|
isProjectEnabled
|
|
46843
47604
|
};
|
|
47605
|
+
const liveConfigReload = startOpenCodeLiveConfigReload({
|
|
47606
|
+
directory: registrationRoot,
|
|
47607
|
+
initialSources: bootstrap.sources ?? [],
|
|
47608
|
+
initialSourceTexts: bootstrap.sourceTexts,
|
|
47609
|
+
getConfig: () => ctx.config,
|
|
47610
|
+
setConfig: (config) => {
|
|
47611
|
+
ctx.config = config;
|
|
47612
|
+
},
|
|
47613
|
+
notify: (message) => deliverConfigMigrationWarnings(registrationRoot, [message])
|
|
47614
|
+
});
|
|
46844
47615
|
const statusSubscribedBridges = new WeakSet;
|
|
46845
47616
|
const statusUnsubscribes = new Set;
|
|
46846
47617
|
const subscribeBridgeStatus = (bridge) => {
|
|
@@ -46878,6 +47649,7 @@ async function initializePluginForDirectory(input) {
|
|
|
46878
47649
|
let clearInspectTier2Idle = () => {};
|
|
46879
47650
|
const shutdownCleanup = registerShutdownCleanup(async (reason) => {
|
|
46880
47651
|
autoUpdateAbort.abort();
|
|
47652
|
+
liveConfigReload.stop();
|
|
46881
47653
|
clearInspectTier2Idle();
|
|
46882
47654
|
for (const unsubscribe of statusUnsubscribes) {
|
|
46883
47655
|
try {
|
|
@@ -47036,7 +47808,7 @@ Install: ${getManualInstallHint()}`);
|
|
|
47036
47808
|
}
|
|
47037
47809
|
const inspectTier2Idle = createInspectTier2IdleScheduler({
|
|
47038
47810
|
isEnabled: () => registeredTools.has("aft_inspect"),
|
|
47039
|
-
idleMinutes: () =>
|
|
47811
|
+
idleMinutes: () => ctx.config.inspect?.tier2_idle_minutes,
|
|
47040
47812
|
warn: warn2,
|
|
47041
47813
|
run: async (sessionID) => {
|
|
47042
47814
|
const sessionDir = await getSessionDirectory(input.client, sessionID, input.directory) ?? input.directory;
|
|
@@ -47094,11 +47866,17 @@ Install: ${getManualInstallHint()}`);
|
|
|
47094
47866
|
storageDir: configOverrides.storage_dir,
|
|
47095
47867
|
pluginVersion: PLUGIN_VERSION,
|
|
47096
47868
|
serverUrl: input.serverUrl?.toString(),
|
|
47097
|
-
delivery:
|
|
47869
|
+
delivery: ctx.config.configure_warnings_delivery ?? "toast"
|
|
47098
47870
|
});
|
|
47099
47871
|
}
|
|
47100
47872
|
await flushConfigureWarningsOnIdle(sessionID);
|
|
47101
47873
|
},
|
|
47874
|
+
"chat.params": async (params) => {
|
|
47875
|
+
rememberReadModel(input.client, params.sessionID, {
|
|
47876
|
+
providerID: params.model.providerID,
|
|
47877
|
+
modelID: params.model.id
|
|
47878
|
+
});
|
|
47879
|
+
},
|
|
47102
47880
|
"chat.message": async (messageInput, messageOutput) => {
|
|
47103
47881
|
const sid = messageInput.sessionID ?? messageInput.sessionId ?? messageInput.id;
|
|
47104
47882
|
warmSessionDirectory(input.client, sid, input.directory);
|