@cortexkit/aft-opencode 0.37.1 → 0.38.0
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/index.js +176 -49
- package/dist/shared/rpc-client.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts +3 -0
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/shutdown-hooks.d.ts +17 -0
- package/dist/shutdown-hooks.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/ast.d.ts.map +1 -1
- package/dist/tui.js +28 -2
- package/package.json +8 -8
- package/src/shared/rpc-client.ts +7 -0
- package/src/shared/rpc-server.ts +39 -0
- package/src/shared/status.ts +4 -6
- package/src/tui/index.tsx +2 -4
- package/src/tui/sidebar.tsx +7 -13
package/dist/index.js
CHANGED
|
@@ -14250,37 +14250,67 @@ var GREP_GUARD_FLAGS = new Set([
|
|
|
14250
14250
|
function maybeStripCompressorPipe(command, compressionEnabled) {
|
|
14251
14251
|
if (!compressionEnabled)
|
|
14252
14252
|
return { command, stripped: false };
|
|
14253
|
-
|
|
14254
|
-
return { command, stripped: false };
|
|
14255
|
-
const chain = splitTopLevelAndChain(command);
|
|
14253
|
+
const chain = splitTopLevelCommandChain(command);
|
|
14256
14254
|
if (chain === null)
|
|
14257
14255
|
return { command, stripped: false };
|
|
14258
|
-
|
|
14259
|
-
const
|
|
14260
|
-
const
|
|
14261
|
-
|
|
14256
|
+
let stripped = false;
|
|
14257
|
+
const droppedFilterChains = [];
|
|
14258
|
+
const rebuilt = chain.map(({ segment, separator }) => {
|
|
14259
|
+
const result = stripSinglePipelineSegment(segment);
|
|
14260
|
+
if (result.stripped) {
|
|
14261
|
+
stripped = true;
|
|
14262
|
+
droppedFilterChains.push(result.filters);
|
|
14263
|
+
}
|
|
14264
|
+
return `${result.segment}${separator}`;
|
|
14265
|
+
}).join("");
|
|
14266
|
+
if (!stripped)
|
|
14262
14267
|
return { command, stripped: false };
|
|
14268
|
+
return {
|
|
14269
|
+
command: rebuilt,
|
|
14270
|
+
stripped: true,
|
|
14271
|
+
note: formatStripNote(droppedFilterChains)
|
|
14272
|
+
};
|
|
14273
|
+
}
|
|
14274
|
+
function stripSinglePipelineSegment(segment) {
|
|
14275
|
+
const leading = /^\s*/.exec(segment)?.[0] ?? "";
|
|
14276
|
+
const trailing = /\s*$/.exec(segment)?.[0] ?? "";
|
|
14277
|
+
const coreStart = leading.length;
|
|
14278
|
+
const coreEnd = segment.length - trailing.length;
|
|
14279
|
+
if (coreEnd <= coreStart)
|
|
14280
|
+
return { segment, stripped: false };
|
|
14281
|
+
const core = segment.slice(coreStart, coreEnd);
|
|
14282
|
+
if (containsUnsplittableConstruct(core))
|
|
14283
|
+
return { segment, stripped: false };
|
|
14284
|
+
if (hasUnquotedBackground(core))
|
|
14285
|
+
return { segment, stripped: false };
|
|
14286
|
+
const stages = splitTopLevelPipeline(core);
|
|
14287
|
+
if (stages.length < 2)
|
|
14288
|
+
return { segment, stripped: false };
|
|
14263
14289
|
const firstStage = stages[0]?.trim() ?? "";
|
|
14264
14290
|
if (!isCompressorHandledRunner(firstStage))
|
|
14265
|
-
return {
|
|
14291
|
+
return { segment, stripped: false };
|
|
14266
14292
|
const filterStages = stages.slice(1).map((stage) => stage.trim());
|
|
14267
14293
|
for (const stage of filterStages) {
|
|
14268
14294
|
if (!filterStageIsSafeToDrop(stage))
|
|
14269
|
-
return {
|
|
14295
|
+
return { segment, stripped: false };
|
|
14270
14296
|
}
|
|
14271
|
-
const filters = filterStages.join(" | ");
|
|
14272
|
-
const rebuilt = [...prefix, firstStage].join(" && ");
|
|
14273
14297
|
return {
|
|
14274
|
-
|
|
14298
|
+
segment: `${leading}${firstStage}${trailing}`,
|
|
14275
14299
|
stripped: true,
|
|
14276
|
-
|
|
14300
|
+
filters: filterStages.join(" | ")
|
|
14277
14301
|
};
|
|
14278
14302
|
}
|
|
14279
|
-
function
|
|
14303
|
+
function formatStripNote(droppedFilterChains) {
|
|
14304
|
+
const filters = droppedFilterChains.map((filter) => `\`| ${filter}\``).join(", ");
|
|
14305
|
+
return `[AFT dropped ${filters} (compressed:false to keep)]`;
|
|
14306
|
+
}
|
|
14307
|
+
function splitTopLevelCommandChain(command) {
|
|
14280
14308
|
const segments = [];
|
|
14281
14309
|
let start = 0;
|
|
14282
14310
|
let quote = null;
|
|
14283
14311
|
let escaped = false;
|
|
14312
|
+
let inBacktick = false;
|
|
14313
|
+
let parenDepth = 0;
|
|
14284
14314
|
for (let index = 0;index < command.length; index++) {
|
|
14285
14315
|
const char = command[index];
|
|
14286
14316
|
const next = command[index + 1];
|
|
@@ -14288,6 +14318,13 @@ function splitTopLevelAndChain(command) {
|
|
|
14288
14318
|
escaped = false;
|
|
14289
14319
|
continue;
|
|
14290
14320
|
}
|
|
14321
|
+
if (inBacktick) {
|
|
14322
|
+
if (char === "\\")
|
|
14323
|
+
escaped = true;
|
|
14324
|
+
else if (char === "`")
|
|
14325
|
+
inBacktick = false;
|
|
14326
|
+
continue;
|
|
14327
|
+
}
|
|
14291
14328
|
if (char === "\\" && quote !== "'") {
|
|
14292
14329
|
escaped = true;
|
|
14293
14330
|
continue;
|
|
@@ -14301,26 +14338,47 @@ function splitTopLevelAndChain(command) {
|
|
|
14301
14338
|
quote = char;
|
|
14302
14339
|
continue;
|
|
14303
14340
|
}
|
|
14304
|
-
if (char === "
|
|
14305
|
-
|
|
14306
|
-
start = index + 2;
|
|
14307
|
-
index++;
|
|
14341
|
+
if (char === "`") {
|
|
14342
|
+
inBacktick = true;
|
|
14308
14343
|
continue;
|
|
14309
14344
|
}
|
|
14310
|
-
if (char === "
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
14345
|
+
if (char === "(") {
|
|
14346
|
+
parenDepth++;
|
|
14347
|
+
continue;
|
|
14348
|
+
}
|
|
14349
|
+
if (char === ")") {
|
|
14350
|
+
if (parenDepth === 0)
|
|
14351
|
+
return null;
|
|
14352
|
+
parenDepth--;
|
|
14353
|
+
continue;
|
|
14354
|
+
}
|
|
14355
|
+
if (parenDepth > 0)
|
|
14356
|
+
continue;
|
|
14314
14357
|
if (char === `
|
|
14315
14358
|
` || char === "\r")
|
|
14316
14359
|
return null;
|
|
14317
|
-
if (char === "
|
|
14318
|
-
|
|
14319
|
-
|
|
14320
|
-
|
|
14360
|
+
if (char === "#" && (index === 0 || command[index - 1] === " " || command[index - 1] === "\t"))
|
|
14361
|
+
return null;
|
|
14362
|
+
if (char === "&" && next === "&") {
|
|
14363
|
+
segments.push({ segment: command.slice(start, index), separator: "&&" });
|
|
14364
|
+
start = index + 2;
|
|
14365
|
+
index++;
|
|
14366
|
+
continue;
|
|
14367
|
+
}
|
|
14368
|
+
if (char === "|" && next === "|") {
|
|
14369
|
+
segments.push({ segment: command.slice(start, index), separator: "||" });
|
|
14370
|
+
start = index + 2;
|
|
14371
|
+
index++;
|
|
14372
|
+
continue;
|
|
14373
|
+
}
|
|
14374
|
+
if (char === ";") {
|
|
14375
|
+
segments.push({ segment: command.slice(start, index), separator: ";" });
|
|
14376
|
+
start = index + 1;
|
|
14321
14377
|
}
|
|
14322
14378
|
}
|
|
14323
|
-
|
|
14379
|
+
if (escaped || quote || inBacktick || parenDepth !== 0)
|
|
14380
|
+
return null;
|
|
14381
|
+
segments.push({ segment: command.slice(start), separator: "" });
|
|
14324
14382
|
return segments;
|
|
14325
14383
|
}
|
|
14326
14384
|
function splitTopLevelPipeline(command) {
|
|
@@ -14383,13 +14441,13 @@ function isCompressorHandledRunner(stage) {
|
|
|
14383
14441
|
args = args.slice(1);
|
|
14384
14442
|
const sub = args[0];
|
|
14385
14443
|
const subNext = args[1];
|
|
14386
|
-
return sub === "test" || sub === "run" &&
|
|
14444
|
+
return sub === "test" || sub === "run" && isJsVerificationScript(subNext);
|
|
14387
14445
|
}
|
|
14388
14446
|
if (first === "npm" || first === "pnpm") {
|
|
14389
|
-
return second === "test" || second === "run" &&
|
|
14447
|
+
return second === "test" || second === "run" && isJsVerificationScript(third);
|
|
14390
14448
|
}
|
|
14391
14449
|
if (first === "yarn") {
|
|
14392
|
-
return
|
|
14450
|
+
return isJsVerificationScript(second) || second === "run" && isJsVerificationScript(third);
|
|
14393
14451
|
}
|
|
14394
14452
|
if (first === "deno")
|
|
14395
14453
|
return ["test", "lint", "check", "bench"].includes(second ?? "");
|
|
@@ -14467,8 +14525,10 @@ function hasBuildTask(args, tasks) {
|
|
|
14467
14525
|
}
|
|
14468
14526
|
return sawAllowed;
|
|
14469
14527
|
}
|
|
14470
|
-
function
|
|
14471
|
-
|
|
14528
|
+
function isJsVerificationScript(token) {
|
|
14529
|
+
if (!token)
|
|
14530
|
+
return false;
|
|
14531
|
+
return token.startsWith("test") || token === "typecheck" || token.startsWith("typecheck:");
|
|
14472
14532
|
}
|
|
14473
14533
|
var XCODEBUILD_VALUE_FLAGS = new Set([
|
|
14474
14534
|
"-scheme",
|
|
@@ -33127,6 +33187,7 @@ function writeTerminal(terminal, data) {
|
|
|
33127
33187
|
// src/shared/rpc-server.ts
|
|
33128
33188
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
33129
33189
|
import {
|
|
33190
|
+
existsSync as existsSync14,
|
|
33130
33191
|
mkdirSync as mkdirSync10,
|
|
33131
33192
|
readdirSync as readdirSync5,
|
|
33132
33193
|
readFileSync as readFileSync13,
|
|
@@ -33185,6 +33246,8 @@ function parseRpcPortRecord(content) {
|
|
|
33185
33246
|
}
|
|
33186
33247
|
|
|
33187
33248
|
// src/shared/rpc-server.ts
|
|
33249
|
+
var PORT_FILE_HEARTBEAT_MS = 15000;
|
|
33250
|
+
|
|
33188
33251
|
class AftRpcServer {
|
|
33189
33252
|
server = null;
|
|
33190
33253
|
port = 0;
|
|
@@ -33192,6 +33255,7 @@ class AftRpcServer {
|
|
|
33192
33255
|
handlers = new Map;
|
|
33193
33256
|
portFilePath;
|
|
33194
33257
|
portsDir;
|
|
33258
|
+
heartbeatTimer = null;
|
|
33195
33259
|
instanceId;
|
|
33196
33260
|
constructor(storageDir, directory) {
|
|
33197
33261
|
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
@@ -33229,6 +33293,8 @@ class AftRpcServer {
|
|
|
33229
33293
|
}), { encoding: "utf-8", mode: 384 });
|
|
33230
33294
|
renameSync8(tmpPath, this.portFilePath);
|
|
33231
33295
|
log2(`RPC server listening on 127.0.0.1:${this.port}`);
|
|
33296
|
+
this.heartbeatTimer = setInterval(() => this.ensurePortFile(), PORT_FILE_HEARTBEAT_MS);
|
|
33297
|
+
this.heartbeatTimer.unref?.();
|
|
33232
33298
|
this.sweepDeadPortFiles();
|
|
33233
33299
|
} catch (err) {
|
|
33234
33300
|
warn2(`Failed to write RPC port file: ${err}`);
|
|
@@ -33263,7 +33329,28 @@ class AftRpcServer {
|
|
|
33263
33329
|
} catch {}
|
|
33264
33330
|
}
|
|
33265
33331
|
}
|
|
33332
|
+
ensurePortFile() {
|
|
33333
|
+
if (!this.server || this.token === null)
|
|
33334
|
+
return;
|
|
33335
|
+
try {
|
|
33336
|
+
if (existsSync14(this.portFilePath))
|
|
33337
|
+
return;
|
|
33338
|
+
const tmpPath = `${this.portFilePath}.tmp`;
|
|
33339
|
+
writeFileSync10(tmpPath, JSON.stringify({
|
|
33340
|
+
port: this.port,
|
|
33341
|
+
token: this.token,
|
|
33342
|
+
pid: process.pid,
|
|
33343
|
+
started_at: Date.now()
|
|
33344
|
+
}), { encoding: "utf-8", mode: 384 });
|
|
33345
|
+
renameSync8(tmpPath, this.portFilePath);
|
|
33346
|
+
log2(`RPC port file was missing; rewrote ${this.portFilePath}`);
|
|
33347
|
+
} catch {}
|
|
33348
|
+
}
|
|
33266
33349
|
stop() {
|
|
33350
|
+
if (this.heartbeatTimer) {
|
|
33351
|
+
clearInterval(this.heartbeatTimer);
|
|
33352
|
+
this.heartbeatTimer = null;
|
|
33353
|
+
}
|
|
33267
33354
|
if (this.server) {
|
|
33268
33355
|
this.server.close();
|
|
33269
33356
|
this.server = null;
|
|
@@ -33622,7 +33709,7 @@ function formatStatusMarkdown(status) {
|
|
|
33622
33709
|
}
|
|
33623
33710
|
if (status.status_bar) {
|
|
33624
33711
|
const sb = status.status_bar;
|
|
33625
|
-
lines.push("", `### Code Health${sb.tier2_stale ? " (~ stale)" : ""}`, `- **Errors:** ${formatCount(sb.errors)}`, `- **Warnings:** ${formatCount(sb.warnings)}`, `- **Duplicates:** ${formatCount(sb.duplicates)}`, `- **TODOs:** ${formatCount(sb.todos)}`);
|
|
33712
|
+
lines.push("", `### Code Health${sb.tier2_stale ? " (~ stale)" : ""}`, `- **Errors:** ${formatCount(sb.errors)}`, `- **Warnings:** ${formatCount(sb.warnings)}`, `- **Dead code:** ${formatCount(sb.dead_code)}`, `- **Unused exports:** ${formatCount(sb.unused_exports)}`, `- **Duplicates:** ${formatCount(sb.duplicates)}`, `- **TODOs:** ${formatCount(sb.todos)}`);
|
|
33626
33713
|
}
|
|
33627
33714
|
lines.push("", "### Current session", `- **ID:** \`${status.session.id}\``, `- **Tracked files:** ${formatCount(status.session.tracked_files)}`, `- **Checkpoints:** ${formatCount(status.session.checkpoints)}`, `- **Project checkpoints (all sessions):** ${formatCount(status.checkpoints_total)}`);
|
|
33628
33715
|
return lines.join(`
|
|
@@ -33631,7 +33718,7 @@ function formatStatusMarkdown(status) {
|
|
|
33631
33718
|
|
|
33632
33719
|
// src/shared/tui-config.ts
|
|
33633
33720
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
33634
|
-
import { existsSync as
|
|
33721
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
|
|
33635
33722
|
import { dirname as dirname10, join as join21 } from "node:path";
|
|
33636
33723
|
|
|
33637
33724
|
// src/shared/opencode-config-dir.ts
|
|
@@ -33668,9 +33755,9 @@ function resolveTuiConfigPath() {
|
|
|
33668
33755
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
33669
33756
|
const jsoncPath = join21(configDir, "tui.jsonc");
|
|
33670
33757
|
const jsonPath = join21(configDir, "tui.json");
|
|
33671
|
-
if (
|
|
33758
|
+
if (existsSync15(jsoncPath))
|
|
33672
33759
|
return jsoncPath;
|
|
33673
|
-
if (
|
|
33760
|
+
if (existsSync15(jsonPath))
|
|
33674
33761
|
return jsonPath;
|
|
33675
33762
|
return jsonPath;
|
|
33676
33763
|
}
|
|
@@ -33678,7 +33765,7 @@ function ensureTuiPluginEntry() {
|
|
|
33678
33765
|
try {
|
|
33679
33766
|
const configPath = resolveTuiConfigPath();
|
|
33680
33767
|
let config2 = {};
|
|
33681
|
-
if (
|
|
33768
|
+
if (existsSync15(configPath)) {
|
|
33682
33769
|
config2 = import_comment_json4.parse(readFileSync14(configPath, "utf-8")) ?? {};
|
|
33683
33770
|
}
|
|
33684
33771
|
const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((value) => typeof value === "string") : [];
|
|
@@ -33730,6 +33817,12 @@ async function runCleanups(reason) {
|
|
|
33730
33817
|
runningCleanups = false;
|
|
33731
33818
|
}
|
|
33732
33819
|
}
|
|
33820
|
+
var SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143, SIGHUP: 129 };
|
|
33821
|
+
var SIGNAL_CLEANUP_TIMEOUT_MS = 5000;
|
|
33822
|
+
function shouldForceExit(otherListenerCount) {
|
|
33823
|
+
return otherListenerCount === 0;
|
|
33824
|
+
}
|
|
33825
|
+
var signalShutdownStarted = false;
|
|
33733
33826
|
function installProcessHandlers() {
|
|
33734
33827
|
const state = getState();
|
|
33735
33828
|
if (state.installed)
|
|
@@ -33737,9 +33830,27 @@ function installProcessHandlers() {
|
|
|
33737
33830
|
state.installed = true;
|
|
33738
33831
|
const signals = ["SIGTERM", "SIGINT", "SIGHUP"];
|
|
33739
33832
|
for (const sig of signals) {
|
|
33740
|
-
|
|
33741
|
-
|
|
33742
|
-
|
|
33833
|
+
const handler = () => {
|
|
33834
|
+
const others = process.listenerCount(sig) - 1;
|
|
33835
|
+
if (!shouldForceExit(others)) {
|
|
33836
|
+
const names = process.listeners(sig).filter((fn) => fn !== handler).map((fn) => fn.name || fn.toString().slice(0, 80).replace(/\s+/g, " ")).join(" | ");
|
|
33837
|
+
log2(`${sig}: deferring termination to ${others} other listener(s); cleanup only. Others: ${names}`);
|
|
33838
|
+
runCleanups(sig);
|
|
33839
|
+
return;
|
|
33840
|
+
}
|
|
33841
|
+
if (signalShutdownStarted) {
|
|
33842
|
+
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
33843
|
+
}
|
|
33844
|
+
signalShutdownStarted = true;
|
|
33845
|
+
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
33846
|
+
const timeout = new Promise((resolve5) => {
|
|
33847
|
+
setTimeout(resolve5, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
33848
|
+
});
|
|
33849
|
+
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
33850
|
+
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
33851
|
+
});
|
|
33852
|
+
};
|
|
33853
|
+
process.on(sig, handler);
|
|
33743
33854
|
}
|
|
33744
33855
|
process.on("beforeExit", () => {
|
|
33745
33856
|
runCleanups("beforeExit");
|
|
@@ -33910,7 +34021,15 @@ ${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
|
33910
34021
|
`);
|
|
33911
34022
|
}
|
|
33912
34023
|
function collectStructuredExtras(response) {
|
|
33913
|
-
const reserved = new Set([
|
|
34024
|
+
const reserved = new Set([
|
|
34025
|
+
"id",
|
|
34026
|
+
"success",
|
|
34027
|
+
"code",
|
|
34028
|
+
"message",
|
|
34029
|
+
"data",
|
|
34030
|
+
"status_bar",
|
|
34031
|
+
"bg_completions"
|
|
34032
|
+
]);
|
|
33914
34033
|
const extras = {};
|
|
33915
34034
|
for (const [key, value] of Object.entries(response)) {
|
|
33916
34035
|
if (reserved.has(key))
|
|
@@ -34190,16 +34309,24 @@ async function checkAstPathsPermission(context, paths) {
|
|
|
34190
34309
|
}
|
|
34191
34310
|
return;
|
|
34192
34311
|
}
|
|
34193
|
-
var SUPPORTED_LANGS = [
|
|
34312
|
+
var SUPPORTED_LANGS = [
|
|
34313
|
+
"typescript",
|
|
34314
|
+
"tsx",
|
|
34315
|
+
"javascript",
|
|
34316
|
+
"python",
|
|
34317
|
+
"rust",
|
|
34318
|
+
"go",
|
|
34319
|
+
"pascal"
|
|
34320
|
+
];
|
|
34194
34321
|
function astTools(ctx) {
|
|
34195
34322
|
const searchTool = {
|
|
34196
|
-
description: `Search code patterns across filesystem using AST-aware matching. Supports
|
|
34323
|
+
description: `Search code patterns across filesystem using AST-aware matching. Supports 7 languages.
|
|
34197
34324
|
|
|
34198
34325
|
` + `Use meta-variables: $VAR matches a single AST node, $$$ matches multiple nodes (variadic).
|
|
34199
34326
|
` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
|
|
34200
34327
|
` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
|
|
34201
34328
|
|
|
34202
|
-
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python'",
|
|
34329
|
+
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal'",
|
|
34203
34330
|
args: {
|
|
34204
34331
|
pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
34205
34332
|
lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
|
|
@@ -38091,12 +38218,12 @@ var PLUGIN_VERSION = (() => {
|
|
|
38091
38218
|
return "0.0.0";
|
|
38092
38219
|
}
|
|
38093
38220
|
})();
|
|
38094
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
38221
|
+
var ANNOUNCEMENT_VERSION = "0.38.0";
|
|
38095
38222
|
var ANNOUNCEMENT_FEATURES = [
|
|
38096
|
-
"
|
|
38097
|
-
"
|
|
38098
|
-
"
|
|
38099
|
-
"
|
|
38223
|
+
"Code Health you can trust: dead code and unused exports are back in the sidebar and status displays, rebuilt on a real TS/JS module-graph engine (oxc) — barrel re-exports, entry points, and dynamic imports resolve correctly now.",
|
|
38224
|
+
"Tools stay responsive during builds: filesystem events are processed off the request thread, so a cargo/webpack compile no longer queues your tool calls behind an event flood.",
|
|
38225
|
+
"Pascal support in outline, zoom, and the AST tools.",
|
|
38226
|
+
"Sidebar reliability: the status panel reconnects after heavy host load instead of going dark, and transient environment errors (schema fetch timeouts) no longer count as code errors."
|
|
38100
38227
|
];
|
|
38101
38228
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
|
|
38102
38229
|
var plugin = async (input) => initializePluginForDirectory(input);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-client.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;CACvC;AA4BD,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,iBAAiB,CAA6B;gBAE1C,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKjD,iFAAiF;IAC3E,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,CAAC,CAAC;YA8CC,OAAO;IAsBrB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAM5B,4CAA4C;IACtC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC;;;;OAIG;YACW,gBAAgB;IAwB9B,OAAO,CAAC,gBAAgB;IAwDxB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,iBAAiB;
|
|
1
|
+
{"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-client.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;CACvC;AA4BD,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,iBAAiB,CAA6B;gBAE1C,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKjD,iFAAiF;IAC3E,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,CAAC,CAAC;YA8CC,OAAO;IAsBrB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAM5B,4CAA4C;IACtC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC;;;;OAIG;YACW,gBAAgB;IAwB9B,OAAO,CAAC,gBAAgB;IAwDxB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,iBAAiB;YA6BX,WAAW;YAkCX,gBAAgB;IAmB9B,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -6,6 +6,7 @@ export declare class AftRpcServer {
|
|
|
6
6
|
private handlers;
|
|
7
7
|
private portFilePath;
|
|
8
8
|
private portsDir;
|
|
9
|
+
private heartbeatTimer;
|
|
9
10
|
/** Unique per-instance ID — distinguishes our entry from duplicate plugin loads. */
|
|
10
11
|
private instanceId;
|
|
11
12
|
constructor(storageDir: string, directory: string);
|
|
@@ -20,6 +21,8 @@ export declare class AftRpcServer {
|
|
|
20
21
|
* Never touches our own freshly written file.
|
|
21
22
|
*/
|
|
22
23
|
private sweepDeadPortFiles;
|
|
24
|
+
/** Rewrite the port file if it disappeared (wrongful deletion recovery). */
|
|
25
|
+
private ensurePortFile;
|
|
23
26
|
/** Stop the server and clean up port file. */
|
|
24
27
|
stop(): void;
|
|
25
28
|
private dispatch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAeA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAIxF,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAA+C;IACrE,oFAAoF;IACpF,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkE9B;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IA6B1B,4EAA4E;IAC5E,OAAO,CAAC,cAAc;IAsBtB,8CAA8C;IAC9C,IAAI,IAAI,IAAI;IAiBZ,OAAO,CAAC,QAAQ;CAoEjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/shared/status.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/shared/status.ts"],"names":[],"mappings":"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"}
|
package/dist/shutdown-hooks.d.ts
CHANGED
|
@@ -16,6 +16,23 @@
|
|
|
16
16
|
*/
|
|
17
17
|
type Cleanup = () => Promise<void> | void;
|
|
18
18
|
export declare function runCleanups(reason: string): Promise<void>;
|
|
19
|
+
/** Conventional exit codes for fatal signals (128 + signal number). */
|
|
20
|
+
export declare const SIGNAL_EXIT_CODES: {
|
|
21
|
+
readonly SIGINT: 130;
|
|
22
|
+
readonly SIGTERM: 143;
|
|
23
|
+
readonly SIGHUP: 129;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Decide whether AFT's handler must terminate the process after cleanup.
|
|
27
|
+
*
|
|
28
|
+
* Registering ANY listener for SIGINT/SIGTERM/SIGHUP disables Node/Bun's
|
|
29
|
+
* default terminate-on-signal behavior. If AFT's listener is the only one,
|
|
30
|
+
* the default was suppressed solely by us, so we must exit or the host hangs
|
|
31
|
+
* forever (OpenCode serve + Desktop /event SSE hung on Ctrl-C until SIGKILL).
|
|
32
|
+
* If the host or another plugin also listens, terminating is THEIR call —
|
|
33
|
+
* forcing an exit here would race a host's graceful shutdown.
|
|
34
|
+
*/
|
|
35
|
+
export declare function shouldForceExit(otherListenerCount: number): boolean;
|
|
19
36
|
/**
|
|
20
37
|
* Register a shutdown cleanup. Call from plugin initialization; returned
|
|
21
38
|
* function unregisters (use in `dispose` so plugin reloads don't leak).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown-hooks.d.ts","sourceRoot":"","sources":["../src/shutdown-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,KAAK,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAoB1C,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/D;
|
|
1
|
+
{"version":3,"file":"shutdown-hooks.d.ts","sourceRoot":"","sources":["../src/shutdown-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,KAAK,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAoB1C,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/D;AAED,uEAAuE;AACvE,eAAO,MAAM,iBAAiB;;;;CAAsD,CAAC;AAKrF;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAEnE;AA2DD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,IAAI,CAO/D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAUhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,GACR,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,OAAO,EACV,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAUhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,GACR,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,OAAO,EACV,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAepB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMpD;AAMD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAIhD,OAAO,EAAE,+BAA+B,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AA2B3F,8EAA8E;AAC9E,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,MAAM,CAsDR;AAiCD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAW3D;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;2BAE2B;AAC3B,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtF;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAEhF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgClC;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMlC;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAE9F"}
|
package/dist/tools/ast.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/tools/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/tools/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqEjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwS3E"}
|
package/dist/tui.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/tui/index.tsx
|
|
2
2
|
import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
|
|
3
3
|
// package.json
|
|
4
|
-
var version = "0.
|
|
4
|
+
var version = "0.38.0";
|
|
5
5
|
|
|
6
6
|
// src/shared/rpc-client.ts
|
|
7
7
|
import { existsSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
@@ -248,6 +248,8 @@ class AftRpcClient {
|
|
|
248
248
|
return;
|
|
249
249
|
}
|
|
250
250
|
this.stalePortFailures.delete(key);
|
|
251
|
+
if (info.pid === undefined || isPidAlive(info.pid))
|
|
252
|
+
return;
|
|
251
253
|
try {
|
|
252
254
|
const current = this.parsePortFile(info.path);
|
|
253
255
|
if (current?.port === info.port && current.token === info.token) {
|
|
@@ -599,7 +601,7 @@ function collapsedHealthLights(statusBar) {
|
|
|
599
601
|
if (!statusBar)
|
|
600
602
|
return null;
|
|
601
603
|
const diagnostics = statusBar.errors > 0 ? "err" : statusBar.warnings > 0 ? "warn" : "ok";
|
|
602
|
-
const code = statusBar.duplicates > 0 ? "warn" : "ok";
|
|
604
|
+
const code = statusBar.dead_code > 0 || statusBar.unused_exports > 0 || statusBar.duplicates > 0 ? "warn" : "ok";
|
|
603
605
|
const todos = statusBar.todos > 0 ? "warn" : "ok";
|
|
604
606
|
return { diagnostics, code, todos };
|
|
605
607
|
}
|
|
@@ -1022,6 +1024,18 @@ var SidebarContent = (props) => {
|
|
|
1022
1024
|
value: formatCount(statusBar().warnings),
|
|
1023
1025
|
tone: statusBar().warnings > 0 ? "warn" : "muted"
|
|
1024
1026
|
}, undefined, false, undefined, this),
|
|
1027
|
+
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
1028
|
+
theme: props.theme,
|
|
1029
|
+
label: "Dead Code",
|
|
1030
|
+
value: formatCount(statusBar().dead_code),
|
|
1031
|
+
tone: "muted"
|
|
1032
|
+
}, undefined, false, undefined, this),
|
|
1033
|
+
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
1034
|
+
theme: props.theme,
|
|
1035
|
+
label: "Unused Exports",
|
|
1036
|
+
value: formatCount(statusBar().unused_exports),
|
|
1037
|
+
tone: "muted"
|
|
1038
|
+
}, undefined, false, undefined, this),
|
|
1025
1039
|
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
1026
1040
|
theme: props.theme,
|
|
1027
1041
|
label: "Duplicates",
|
|
@@ -1556,6 +1570,18 @@ var StatusDialog = (props) => {
|
|
|
1556
1570
|
value: formatCountShort(status().status_bar.warnings),
|
|
1557
1571
|
tone: status().status_bar.warnings > 0 ? "warn" : "muted"
|
|
1558
1572
|
}, undefined, false, undefined, this),
|
|
1573
|
+
/* @__PURE__ */ jsxDEV2(R, {
|
|
1574
|
+
theme: t(),
|
|
1575
|
+
label: "Dead Code",
|
|
1576
|
+
value: formatCountShort(status().status_bar.dead_code),
|
|
1577
|
+
tone: "muted"
|
|
1578
|
+
}, undefined, false, undefined, this),
|
|
1579
|
+
/* @__PURE__ */ jsxDEV2(R, {
|
|
1580
|
+
theme: t(),
|
|
1581
|
+
label: "Unused Exports",
|
|
1582
|
+
value: formatCountShort(status().status_bar.unused_exports),
|
|
1583
|
+
tone: "muted"
|
|
1584
|
+
}, undefined, false, undefined, this),
|
|
1559
1585
|
/* @__PURE__ */ jsxDEV2(R, {
|
|
1560
1586
|
theme: t(),
|
|
1561
1587
|
label: "Duplicates",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/aft-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,19 +30,19 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@clack/prompts": "^1.2.0",
|
|
33
|
-
"@cortexkit/aft-bridge": "0.
|
|
33
|
+
"@cortexkit/aft-bridge": "0.38.0",
|
|
34
34
|
"@xterm/headless": "^5.5.0",
|
|
35
35
|
"comment-json": "^4.6.2",
|
|
36
36
|
"undici": "^7.25.0",
|
|
37
37
|
"zod": "^4.1.8"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
41
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
42
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
43
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
44
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
45
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
40
|
+
"@cortexkit/aft-darwin-arm64": "0.38.0",
|
|
41
|
+
"@cortexkit/aft-darwin-x64": "0.38.0",
|
|
42
|
+
"@cortexkit/aft-linux-arm64": "0.38.0",
|
|
43
|
+
"@cortexkit/aft-linux-x64": "0.38.0",
|
|
44
|
+
"@cortexkit/aft-win32-arm64": "0.38.0",
|
|
45
|
+
"@cortexkit/aft-win32-x64": "0.38.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@opencode-ai/plugin": "^1.15.11",
|
package/src/shared/rpc-client.ts
CHANGED
|
@@ -281,6 +281,13 @@ export class AftRpcClient {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
this.stalePortFailures.delete(key);
|
|
284
|
+
// Deletion requires a provably-dead owner. Health checks time out under
|
|
285
|
+
// host load (blocked event loop during builds/streaming), and unlinking a
|
|
286
|
+
// LIVE server's port file is permanent: the server only wrote it at
|
|
287
|
+
// startup, so the sidebar could never reconnect until host restart
|
|
288
|
+
// (issue #110). Live-pid and pid-less files are skipped this round and
|
|
289
|
+
// retried on the next poll instead.
|
|
290
|
+
if (info.pid === undefined || isPidAlive(info.pid)) return;
|
|
284
291
|
try {
|
|
285
292
|
// Do not unlink a replacement written after the failed health checks.
|
|
286
293
|
const current = this.parsePortFile(info.path);
|
package/src/shared/rpc-server.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import {
|
|
3
|
+
existsSync,
|
|
3
4
|
mkdirSync,
|
|
4
5
|
readdirSync,
|
|
5
6
|
readFileSync,
|
|
@@ -14,6 +15,8 @@ import { isPidAlive, parseRpcPortRecord, rpcPortFileDir } from "./rpc-utils";
|
|
|
14
15
|
|
|
15
16
|
type RpcHandler = (params: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
16
17
|
|
|
18
|
+
const PORT_FILE_HEARTBEAT_MS = 15_000;
|
|
19
|
+
|
|
17
20
|
export class AftRpcServer {
|
|
18
21
|
private server: Server | null = null;
|
|
19
22
|
private port = 0;
|
|
@@ -21,6 +24,7 @@ export class AftRpcServer {
|
|
|
21
24
|
private handlers = new Map<string, RpcHandler>();
|
|
22
25
|
private portFilePath: string;
|
|
23
26
|
private portsDir: string;
|
|
27
|
+
private heartbeatTimer: ReturnType<typeof setInterval> | null = null;
|
|
24
28
|
/** Unique per-instance ID — distinguishes our entry from duplicate plugin loads. */
|
|
25
29
|
private instanceId: string;
|
|
26
30
|
|
|
@@ -75,6 +79,14 @@ export class AftRpcServer {
|
|
|
75
79
|
);
|
|
76
80
|
renameSync(tmpPath, this.portFilePath);
|
|
77
81
|
log(`RPC server listening on 127.0.0.1:${this.port}`);
|
|
82
|
+
// Self-heal: the port file is this server's only discoverability
|
|
83
|
+
// record, and historically it was written exactly once — anything
|
|
84
|
+
// that deleted it (a client misjudging a load-induced health-check
|
|
85
|
+
// timeout as staleness, cache cleanup, manual sweeps) silently
|
|
86
|
+
// orphaned the server until host restart (issue #110: sidebar stuck
|
|
87
|
+
// on the lazy placeholder forever). Recreate it if it goes missing.
|
|
88
|
+
this.heartbeatTimer = setInterval(() => this.ensurePortFile(), PORT_FILE_HEARTBEAT_MS);
|
|
89
|
+
this.heartbeatTimer.unref?.();
|
|
78
90
|
// Hygiene: sweep dead siblings while we're here. The client only
|
|
79
91
|
// reclaims dead-pid files on a cold port scan, and it caches the
|
|
80
92
|
// first warm port afterwards — so crash/restart leftovers piled up
|
|
@@ -129,8 +141,35 @@ export class AftRpcServer {
|
|
|
129
141
|
}
|
|
130
142
|
}
|
|
131
143
|
|
|
144
|
+
/** Rewrite the port file if it disappeared (wrongful deletion recovery). */
|
|
145
|
+
private ensurePortFile(): void {
|
|
146
|
+
if (!this.server || this.token === null) return;
|
|
147
|
+
try {
|
|
148
|
+
if (existsSync(this.portFilePath)) return;
|
|
149
|
+
const tmpPath = `${this.portFilePath}.tmp`;
|
|
150
|
+
writeFileSync(
|
|
151
|
+
tmpPath,
|
|
152
|
+
JSON.stringify({
|
|
153
|
+
port: this.port,
|
|
154
|
+
token: this.token,
|
|
155
|
+
pid: process.pid,
|
|
156
|
+
started_at: Date.now(),
|
|
157
|
+
}),
|
|
158
|
+
{ encoding: "utf-8", mode: 0o600 },
|
|
159
|
+
);
|
|
160
|
+
renameSync(tmpPath, this.portFilePath);
|
|
161
|
+
log(`RPC port file was missing; rewrote ${this.portFilePath}`);
|
|
162
|
+
} catch {
|
|
163
|
+
// best-effort; retried on the next heartbeat
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
132
167
|
/** Stop the server and clean up port file. */
|
|
133
168
|
stop(): void {
|
|
169
|
+
if (this.heartbeatTimer) {
|
|
170
|
+
clearInterval(this.heartbeatTimer);
|
|
171
|
+
this.heartbeatTimer = null;
|
|
172
|
+
}
|
|
134
173
|
if (this.server) {
|
|
135
174
|
this.server.close();
|
|
136
175
|
this.server = null;
|
package/src/shared/status.ts
CHANGED
|
@@ -337,9 +337,8 @@ export function formatStatusDialogMessage(status: AftStatusSnapshot): string {
|
|
|
337
337
|
`Code Health${sb.tier2_stale ? " (~ stale)" : ""}`,
|
|
338
338
|
`- errors: ${formatCount(sb.errors)}`,
|
|
339
339
|
`- warnings: ${formatCount(sb.warnings)}`,
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
// `- unused exports: ${formatCount(sb.unused_exports)}`,
|
|
340
|
+
`- dead code: ${formatCount(sb.dead_code)}`,
|
|
341
|
+
`- unused exports: ${formatCount(sb.unused_exports)}`,
|
|
343
342
|
`- duplicates: ${formatCount(sb.duplicates)}`,
|
|
344
343
|
`- todos: ${formatCount(sb.todos)}`,
|
|
345
344
|
);
|
|
@@ -447,9 +446,8 @@ export function formatStatusMarkdown(status: AftStatusSnapshot): string {
|
|
|
447
446
|
`### Code Health${sb.tier2_stale ? " (~ stale)" : ""}`,
|
|
448
447
|
`- **Errors:** ${formatCount(sb.errors)}`,
|
|
449
448
|
`- **Warnings:** ${formatCount(sb.warnings)}`,
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
// `- **Unused exports:** ${formatCount(sb.unused_exports)}`,
|
|
449
|
+
`- **Dead code:** ${formatCount(sb.dead_code)}`,
|
|
450
|
+
`- **Unused exports:** ${formatCount(sb.unused_exports)}`,
|
|
453
451
|
`- **Duplicates:** ${formatCount(sb.duplicates)}`,
|
|
454
452
|
`- **TODOs:** ${formatCount(sb.todos)}`,
|
|
455
453
|
);
|
package/src/tui/index.tsx
CHANGED
|
@@ -507,9 +507,7 @@ const StatusDialog = (props: StatusDialogProps) => {
|
|
|
507
507
|
value={formatCountShort(status()!.status_bar!.warnings)}
|
|
508
508
|
tone={status()!.status_bar!.warnings > 0 ? "warn" : "muted"}
|
|
509
509
|
/>
|
|
510
|
-
|
|
511
|
-
(current scanner over-reports on barrel re-exports). Restore both. */}
|
|
512
|
-
{/* <R
|
|
510
|
+
<R
|
|
513
511
|
theme={t()}
|
|
514
512
|
label="Dead Code"
|
|
515
513
|
value={formatCountShort(status()!.status_bar!.dead_code)}
|
|
@@ -520,7 +518,7 @@ const StatusDialog = (props: StatusDialogProps) => {
|
|
|
520
518
|
label="Unused Exports"
|
|
521
519
|
value={formatCountShort(status()!.status_bar!.unused_exports)}
|
|
522
520
|
tone="muted"
|
|
523
|
-
/>
|
|
521
|
+
/>
|
|
524
522
|
<R
|
|
525
523
|
theme={t()}
|
|
526
524
|
label="Duplicates"
|
package/src/tui/sidebar.tsx
CHANGED
|
@@ -185,11 +185,8 @@ export type HealthLightTone = "ok" | "warn" | "err";
|
|
|
185
185
|
export interface HealthLights {
|
|
186
186
|
// Diagnostics: red if any errors, yellow if any warnings, else green.
|
|
187
187
|
diagnostics: HealthLightTone;
|
|
188
|
-
// Code cruft: yellow if there is any
|
|
189
|
-
// cruft is not a build failure.
|
|
190
|
-
// temporarily excluded from this signal (and the expanded rows below) until
|
|
191
|
-
// the oxc-based resolver lands and makes those counts trustworthy on real
|
|
192
|
-
// TS/JS codebases. Restore them here when that engine ships.
|
|
188
|
+
// Code cruft: yellow if there is any dead code, unused export, or duplicate,
|
|
189
|
+
// green when zero. Never red — cruft is not a build failure.
|
|
193
190
|
code: HealthLightTone;
|
|
194
191
|
// TODOs: yellow if any, else green.
|
|
195
192
|
todos: HealthLightTone;
|
|
@@ -202,8 +199,9 @@ export function collapsedHealthLights(statusBar: StatusBar | undefined): HealthL
|
|
|
202
199
|
const diagnostics: HealthLightTone =
|
|
203
200
|
statusBar.errors > 0 ? "err" : statusBar.warnings > 0 ? "warn" : "ok";
|
|
204
201
|
const code: HealthLightTone =
|
|
205
|
-
|
|
206
|
-
|
|
202
|
+
statusBar.dead_code > 0 || statusBar.unused_exports > 0 || statusBar.duplicates > 0
|
|
203
|
+
? "warn"
|
|
204
|
+
: "ok";
|
|
207
205
|
const todos: HealthLightTone = statusBar.todos > 0 ? "warn" : "ok";
|
|
208
206
|
return { diagnostics, code, todos };
|
|
209
207
|
}
|
|
@@ -744,11 +742,7 @@ const SidebarContent = (props: {
|
|
|
744
742
|
value={formatCount(statusBar()!.warnings)}
|
|
745
743
|
tone={statusBar()!.warnings > 0 ? "warn" : "muted"}
|
|
746
744
|
/>
|
|
747
|
-
|
|
748
|
-
oxc-based resolver lands and makes these trustworthy on real
|
|
749
|
-
TS/JS codebases (current tree-sitter scanner over-reports via
|
|
750
|
-
barrel re-export gaps). Restore both rows when that ships. */}
|
|
751
|
-
{/* <StatRow
|
|
745
|
+
<StatRow
|
|
752
746
|
theme={props.theme}
|
|
753
747
|
label="Dead Code"
|
|
754
748
|
value={formatCount(statusBar()!.dead_code)}
|
|
@@ -759,7 +753,7 @@ const SidebarContent = (props: {
|
|
|
759
753
|
label="Unused Exports"
|
|
760
754
|
value={formatCount(statusBar()!.unused_exports)}
|
|
761
755
|
tone="muted"
|
|
762
|
-
/>
|
|
756
|
+
/>
|
|
763
757
|
<StatRow
|
|
764
758
|
theme={props.theme}
|
|
765
759
|
label="Duplicates"
|