@cortexkit/aft-opencode 0.13.0 → 0.14.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 CHANGED
@@ -22233,12 +22233,14 @@ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
22233
22233
 
22234
22234
  class BinaryBridge {
22235
22235
  static RESTART_RESET_MS = 5 * 60 * 1000;
22236
+ static STDERR_TAIL_MAX = 20;
22236
22237
  binaryPath;
22237
22238
  cwd;
22238
22239
  process = null;
22239
22240
  pending = new Map;
22240
22241
  nextId = 1;
22241
22242
  stdoutBuffer = "";
22243
+ stderrTail = [];
22242
22244
  _restartCount = 0;
22243
22245
  _shuttingDown = false;
22244
22246
  timeoutMs;
@@ -22405,22 +22407,48 @@ class BinaryBridge {
22405
22407
  const lines = chunk.toString("utf-8").trimEnd().split(`
22406
22408
  `);
22407
22409
  for (const line of lines) {
22410
+ if (!line)
22411
+ continue;
22408
22412
  const stripped = line.replace(/^\[aft\]\s*/, "");
22409
22413
  log(`[aft] ${stripped}`);
22414
+ this.pushStderrLine(stripped);
22410
22415
  }
22411
22416
  });
22412
22417
  child.on("error", (err) => {
22413
- error48(`Process error: ${err.message}`);
22418
+ error48(`Process error: ${err.message}${this.formatStderrTail()}`);
22414
22419
  this.handleCrash();
22415
22420
  });
22416
22421
  child.on("exit", (code, signal) => {
22417
22422
  if (this._shuttingDown)
22418
22423
  return;
22419
22424
  log(`Process exited: code=${code}, signal=${signal}`);
22425
+ if (signal === "SIGTERM" || signal === "SIGKILL" || signal === "SIGHUP" || signal === "SIGINT") {
22426
+ this.process = null;
22427
+ this.configured = false;
22428
+ this.clearRestartResetTimer();
22429
+ this.rejectAllPending(new Error(`[aft-plugin] Binary killed by ${signal}`));
22430
+ return;
22431
+ }
22420
22432
  this.handleCrash();
22421
22433
  });
22422
22434
  this.process = child;
22423
22435
  this.stdoutBuffer = "";
22436
+ this.stderrTail = [];
22437
+ }
22438
+ pushStderrLine(line) {
22439
+ this.stderrTail.push(line);
22440
+ if (this.stderrTail.length > BinaryBridge.STDERR_TAIL_MAX) {
22441
+ this.stderrTail.shift();
22442
+ }
22443
+ }
22444
+ formatStderrTail() {
22445
+ if (this.stderrTail.length === 0)
22446
+ return "";
22447
+ const tail = this.stderrTail.join(`
22448
+ `);
22449
+ return `
22450
+ --- last ${this.stderrTail.length} stderr lines ---
22451
+ ${tail}`;
22424
22452
  }
22425
22453
  onStdoutData(data) {
22426
22454
  this.stdoutBuffer += data;
@@ -22455,13 +22483,16 @@ class BinaryBridge {
22455
22483
  }
22456
22484
  this.clearRestartResetTimer();
22457
22485
  this.configured = false;
22458
- this.rejectAllPending(new Error("[aft-plugin] Bridge restarted after timeout"));
22486
+ const tail = this.formatStderrTail();
22487
+ this.stderrTail = [];
22488
+ this.rejectAllPending(new Error(`[aft-plugin] Bridge restarted after timeout${tail}`));
22459
22489
  }
22460
22490
  handleCrash() {
22461
22491
  this.process = null;
22462
22492
  this.clearRestartResetTimer();
22463
22493
  this.configured = false;
22464
- this.rejectAllPending(new Error(`[aft-plugin] Binary crashed (restarts: ${this._restartCount})`));
22494
+ const tail = this.formatStderrTail();
22495
+ this.rejectAllPending(new Error(`[aft-plugin] Binary crashed (restarts: ${this._restartCount})${tail}`));
22465
22496
  if (this._restartCount < this.maxRestarts) {
22466
22497
  const delay = 100 * 2 ** this._restartCount;
22467
22498
  this._restartCount++;
@@ -22476,7 +22507,7 @@ class BinaryBridge {
22476
22507
  }
22477
22508
  }, delay);
22478
22509
  } else {
22479
- error48(`Max restarts (${this.maxRestarts}) reached, giving up. Logs: ${getLogFilePath()}`);
22510
+ error48(`Max restarts (${this.maxRestarts}) reached, giving up. Logs: ${getLogFilePath()}${tail}`);
22480
22511
  }
22481
22512
  }
22482
22513
  rejectAllPending(error49) {
@@ -22530,8 +22561,14 @@ class BridgePool {
22530
22561
  this.cleanupTimer.unref();
22531
22562
  }
22532
22563
  }
22533
- getAnyActiveBridge(_directory) {
22534
- for (const [, entry] of this.bridges) {
22564
+ getAnyActiveBridge(projectRoot) {
22565
+ const key = normalizeKey(projectRoot);
22566
+ const preferred = this.bridges.get(key);
22567
+ if (preferred?.bridge.isAlive()) {
22568
+ preferred.lastUsed = Date.now();
22569
+ return preferred.bridge;
22570
+ }
22571
+ for (const entry of this.bridges.values()) {
22535
22572
  if (entry.bridge.isAlive()) {
22536
22573
  entry.lastUsed = Date.now();
22537
22574
  return entry.bridge;
@@ -22539,8 +22576,8 @@ class BridgePool {
22539
22576
  }
22540
22577
  return null;
22541
22578
  }
22542
- getBridge(directory, sessionID) {
22543
- const key = sessionID || directory.replace(/\/+$/, "");
22579
+ getBridge(projectRoot) {
22580
+ const key = normalizeKey(projectRoot);
22544
22581
  const existing = this.bridges.get(key);
22545
22582
  if (existing) {
22546
22583
  existing.lastUsed = Date.now();
@@ -22549,8 +22586,7 @@ class BridgePool {
22549
22586
  if (this.bridges.size >= this.maxPoolSize) {
22550
22587
  this.evictLRU();
22551
22588
  }
22552
- const normalized = directory.replace(/\/+$/, "");
22553
- const bridge = new BinaryBridge(this.binaryPath, normalized, this.bridgeOptions, this.configOverrides);
22589
+ const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, this.configOverrides);
22554
22590
  this.bridges.set(key, { bridge, lastUsed: Date.now() });
22555
22591
  return bridge;
22556
22592
  }
@@ -22601,6 +22637,9 @@ class BridgePool {
22601
22637
  return this.bridges.size;
22602
22638
  }
22603
22639
  }
22640
+ function normalizeKey(projectRoot) {
22641
+ return projectRoot.replace(/[/\\]+$/, "");
22642
+ }
22604
22643
 
22605
22644
  // src/resolver.ts
22606
22645
  import { execSync, spawnSync } from "child_process";
@@ -22902,6 +22941,7 @@ function coerceAftStatus(response) {
22902
22941
  };
22903
22942
  const disk = asRecord(response.disk);
22904
22943
  const symbolCache = asRecord(response.symbol_cache);
22944
+ const session = asRecord(response.session);
22905
22945
  return {
22906
22946
  version: readString(response.version, "unknown"),
22907
22947
  project_root: readNullableString(response.project_root),
@@ -22939,7 +22979,13 @@ function coerceAftStatus(response) {
22939
22979
  local_entries: readNumber(symbolCache.local_entries),
22940
22980
  warm_entries: readNumber(symbolCache.warm_entries)
22941
22981
  },
22942
- storage_dir: readNullableString(response.storage_dir)
22982
+ storage_dir: readNullableString(response.storage_dir),
22983
+ checkpoints_total: readNumber(response.checkpoints_total),
22984
+ session: {
22985
+ id: readString(session.id, "__default__"),
22986
+ tracked_files: readNumber(session.tracked_files),
22987
+ checkpoints: readNumber(session.checkpoints)
22988
+ }
22943
22989
  };
22944
22990
  }
22945
22991
  function formatStatusMarkdown(status) {
@@ -22988,6 +23034,7 @@ function formatStatusMarkdown(status) {
22988
23034
  if (status.storage_dir ?? status.disk.storage_dir) {
22989
23035
  lines.push(`- **Storage dir:** \`${status.storage_dir ?? status.disk.storage_dir}\``);
22990
23036
  }
23037
+ 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)}`);
22991
23038
  return lines.join(`
22992
23039
  `);
22993
23040
  }
@@ -23232,16 +23279,91 @@ function cleanupUrlCache(storageDir) {
23232
23279
  }
23233
23280
  }
23234
23281
 
23282
+ // src/shutdown-hooks.ts
23283
+ var GLOBAL_KEY2 = "__aftShutdownHooks__";
23284
+ function getState() {
23285
+ const g = globalThis;
23286
+ if (!g[GLOBAL_KEY2]) {
23287
+ g[GLOBAL_KEY2] = { cleanups: new Set, installed: false };
23288
+ }
23289
+ return g[GLOBAL_KEY2];
23290
+ }
23291
+ var shuttingDown = false;
23292
+ async function runCleanups(reason) {
23293
+ if (shuttingDown)
23294
+ return;
23295
+ shuttingDown = true;
23296
+ const state = getState();
23297
+ if (state.cleanups.size === 0)
23298
+ return;
23299
+ log(`Shutdown triggered by ${reason} \u2014 running ${state.cleanups.size} cleanup(s)`);
23300
+ const cleanups = Array.from(state.cleanups);
23301
+ state.cleanups.clear();
23302
+ await Promise.allSettled(cleanups.map(async (fn) => {
23303
+ try {
23304
+ await fn();
23305
+ } catch (err) {
23306
+ log(`Cleanup error: ${err.message}`);
23307
+ }
23308
+ }));
23309
+ }
23310
+ function installProcessHandlers() {
23311
+ const state = getState();
23312
+ if (state.installed)
23313
+ return;
23314
+ state.installed = true;
23315
+ const signals = ["SIGTERM", "SIGINT", "SIGHUP"];
23316
+ for (const sig of signals) {
23317
+ process.on(sig, () => {
23318
+ runCleanups(sig);
23319
+ });
23320
+ }
23321
+ process.on("beforeExit", () => {
23322
+ runCleanups("beforeExit");
23323
+ });
23324
+ }
23325
+ function registerShutdownCleanup(fn) {
23326
+ installProcessHandlers();
23327
+ const state = getState();
23328
+ state.cleanups.add(fn);
23329
+ return () => {
23330
+ state.cleanups.delete(fn);
23331
+ };
23332
+ }
23333
+
23235
23334
  // src/tools/ast.ts
23236
23335
  import { tool as tool2 } from "@opencode-ai/plugin";
23237
23336
 
23238
- // src/tools/permissions.ts
23337
+ // src/tools/_shared.ts
23338
+ import * as fs2 from "fs";
23239
23339
  import * as path2 from "path";
23340
+ function projectRootFor(runtime) {
23341
+ const raw = runtime.worktree ?? runtime.directory;
23342
+ const trimmed = raw.replace(/[/\\]+$/, "");
23343
+ try {
23344
+ return fs2.realpathSync(trimmed);
23345
+ } catch {
23346
+ return path2.resolve(trimmed);
23347
+ }
23348
+ }
23349
+ function bridgeFor(ctx, runtime) {
23350
+ return ctx.pool.getBridge(projectRootFor(runtime));
23351
+ }
23352
+ function callBridge(ctx, runtime, command, params = {}) {
23353
+ const merged = { ...params };
23354
+ if (runtime.sessionID) {
23355
+ merged.session_id = runtime.sessionID;
23356
+ }
23357
+ return bridgeFor(ctx, runtime).send(command, merged);
23358
+ }
23359
+
23360
+ // src/tools/permissions.ts
23361
+ import * as path3 from "path";
23240
23362
  function resolveAbsolutePath(context, target) {
23241
- return path2.isAbsolute(target) ? target : path2.resolve(context.directory, target);
23363
+ return path3.isAbsolute(target) ? target : path3.resolve(context.directory, target);
23242
23364
  }
23243
23365
  function resolveRelativePattern(context, target) {
23244
- return path2.relative(context.worktree, resolveAbsolutePath(context, target)) || ".";
23366
+ return path3.relative(context.worktree, resolveAbsolutePath(context, target)) || ".";
23245
23367
  }
23246
23368
  function resolveRelativePatterns(context, targets) {
23247
23369
  const seen = new Set;
@@ -23329,7 +23451,6 @@ function astTools(ctx) {
23329
23451
  contextLines: z2.number().optional().describe("Number of context lines to show around each match")
23330
23452
  },
23331
23453
  execute: async (args, context) => {
23332
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
23333
23454
  const params = {
23334
23455
  pattern: args.pattern,
23335
23456
  lang: args.lang
@@ -23340,7 +23461,7 @@ function astTools(ctx) {
23340
23461
  params.globs = args.globs;
23341
23462
  if (args.contextLines !== undefined)
23342
23463
  params.context = Number(args.contextLines);
23343
- const response = await bridge.send("ast_search", params);
23464
+ const response = await callBridge(ctx, context, "ast_search", params);
23344
23465
  if (response.success === false) {
23345
23466
  throw new Error(response.message || "ast_search failed");
23346
23467
  }
@@ -23406,7 +23527,6 @@ ${hint}`;
23406
23527
  dryRun: z2.boolean().optional().describe("Preview changes without applying (default: false)")
23407
23528
  },
23408
23529
  execute: async (args, context) => {
23409
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
23410
23530
  const isDryRun = args.dryRun === true;
23411
23531
  if (!isDryRun) {
23412
23532
  const explicitPaths = Array.isArray(args.paths) ? resolveRelativePatterns(context, args.paths) : [];
@@ -23430,7 +23550,7 @@ ${hint}`;
23430
23550
  if (args.globs)
23431
23551
  params.globs = args.globs;
23432
23552
  params.dry_run = args.dryRun === true;
23433
- const response = await bridge.send("ast_replace", params);
23553
+ const response = await callBridge(ctx, context, "ast_replace", params);
23434
23554
  if (response.success === false) {
23435
23555
  throw new Error(response.message || "ast_replace failed");
23436
23556
  }
@@ -23482,8 +23602,7 @@ function conflictTools(ctx) {
23482
23602
  description: "Show all git merge conflicts across the repository \u2014 returns line-numbered conflict regions with context for every conflicted file in a single call.",
23483
23603
  args: {},
23484
23604
  execute: async (_args, context) => {
23485
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
23486
- const response = await bridge.send("git_conflicts", {});
23605
+ const response = await callBridge(ctx, context, "git_conflicts", {});
23487
23606
  if (response.success === false) {
23488
23607
  throw new Error(response.message || "git_conflicts failed");
23489
23608
  }
@@ -23494,8 +23613,8 @@ function conflictTools(ctx) {
23494
23613
  }
23495
23614
 
23496
23615
  // src/tools/hoisted.ts
23497
- import * as fs2 from "fs";
23498
- import * as path3 from "path";
23616
+ import * as fs3 from "fs";
23617
+ import * as path4 from "path";
23499
23618
  import { tool as tool3 } from "@opencode-ai/plugin";
23500
23619
 
23501
23620
  // src/patch-parser.ts
@@ -23732,7 +23851,7 @@ function getCallID(ctx) {
23732
23851
  return c.callID ?? c.callId ?? c.call_id;
23733
23852
  }
23734
23853
  function relativeToWorktree(fp, worktree) {
23735
- return path3.relative(worktree, fp);
23854
+ return path4.relative(worktree, fp);
23736
23855
  }
23737
23856
  function buildUnifiedDiff(fp, before, after) {
23738
23857
  const SIZE_CAP = 100 * 1024;
@@ -23814,16 +23933,15 @@ function createReadTool(ctx) {
23814
23933
  offset: z3.number().optional().describe("1-based line number to start reading from (use with limit). Ignored if startLine is provided")
23815
23934
  },
23816
23935
  execute: async (args, context) => {
23817
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
23818
23936
  const file2 = args.filePath;
23819
- const filePath = path3.isAbsolute(file2) ? file2 : path3.resolve(context.directory, file2);
23937
+ const filePath = path4.isAbsolute(file2) ? file2 : path4.resolve(context.directory, file2);
23820
23938
  await context.ask({
23821
23939
  permission: "read",
23822
23940
  patterns: [filePath],
23823
23941
  always: ["*"],
23824
23942
  metadata: {}
23825
23943
  });
23826
- const ext = path3.extname(filePath).toLowerCase();
23944
+ const ext = path4.extname(filePath).toLowerCase();
23827
23945
  const mimeMap = {
23828
23946
  ".png": "image/png",
23829
23947
  ".jpg": "image/jpeg",
@@ -23845,7 +23963,7 @@ function createReadTool(ctx) {
23845
23963
  const label = isImage ? "Image" : "PDF";
23846
23964
  let fileSize = 0;
23847
23965
  try {
23848
- const stat = await import("fs/promises").then((fs3) => fs3.stat(filePath));
23966
+ const stat = await import("fs/promises").then((fs4) => fs4.stat(filePath));
23849
23967
  fileSize = stat.size;
23850
23968
  } catch {}
23851
23969
  const sizeStr = fileSize > 1048576 ? `${(fileSize / 1048576).toFixed(1)}MB` : fileSize > 1024 ? `${(fileSize / 1024).toFixed(0)}KB` : `${fileSize} bytes`;
@@ -23853,7 +23971,7 @@ function createReadTool(ctx) {
23853
23971
  const imgCallID = getCallID(context);
23854
23972
  if (imgCallID) {
23855
23973
  storeToolMetadata(context.sessionID, imgCallID, {
23856
- title: path3.relative(context.worktree, filePath),
23974
+ title: path4.relative(context.worktree, filePath),
23857
23975
  metadata: {
23858
23976
  preview: msg,
23859
23977
  filepath: filePath,
@@ -23879,7 +23997,7 @@ function createReadTool(ctx) {
23879
23997
  params.end_line = endLine;
23880
23998
  if (args.limit !== undefined && args.offset === undefined)
23881
23999
  params.limit = args.limit;
23882
- const data = await bridge.send("read", params);
24000
+ const data = await callBridge(ctx, context, "read", params);
23883
24001
  if (data.success === false) {
23884
24002
  throw new Error(data.message || "read failed");
23885
24003
  }
@@ -23937,18 +24055,17 @@ function createWriteTool(ctx, editToolName = "edit") {
23937
24055
  content: z3.string().describe("The full content to write to the file")
23938
24056
  },
23939
24057
  execute: async (args, context) => {
23940
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
23941
24058
  const file2 = args.filePath;
23942
24059
  const content = args.content;
23943
- const filePath = path3.isAbsolute(file2) ? file2 : path3.resolve(context.directory, file2);
23944
- const relPath = path3.relative(context.worktree, filePath);
24060
+ const filePath = path4.isAbsolute(file2) ? file2 : path4.resolve(context.directory, file2);
24061
+ const relPath = path4.relative(context.worktree, filePath);
23945
24062
  await context.ask({
23946
24063
  permission: "edit",
23947
24064
  patterns: [relPath],
23948
24065
  always: ["*"],
23949
24066
  metadata: { filepath: filePath }
23950
24067
  });
23951
- const data = await bridge.send("write", {
24068
+ const data = await callBridge(ctx, context, "write", {
23952
24069
  file: filePath,
23953
24070
  content,
23954
24071
  create_dirs: true,
@@ -24068,30 +24185,29 @@ function createEditTool(ctx, writeToolName = "write") {
24068
24185
  dryRun: z3.boolean().optional().describe("Preview changes without applying (returns diff, default: false)")
24069
24186
  },
24070
24187
  execute: async (args, context) => {
24071
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24072
24188
  if (Array.isArray(args.operations)) {
24073
24189
  const ops = args.operations;
24074
24190
  const files = ops.map((op) => op.file).filter(Boolean);
24075
24191
  await context.ask({
24076
24192
  permission: "edit",
24077
- patterns: files.map((f) => path3.relative(context.worktree, path3.resolve(context.directory, f))),
24193
+ patterns: files.map((f) => path4.relative(context.worktree, path4.resolve(context.directory, f))),
24078
24194
  always: ["*"],
24079
24195
  metadata: {}
24080
24196
  });
24081
24197
  const resolvedOps = ops.map((op) => ({
24082
24198
  ...op,
24083
- file: path3.isAbsolute(op.file) ? op.file : path3.resolve(context.directory, op.file)
24199
+ file: path4.isAbsolute(op.file) ? op.file : path4.resolve(context.directory, op.file)
24084
24200
  }));
24085
24201
  const params2 = { operations: resolvedOps };
24086
24202
  params2.dry_run = args.dryRun === true;
24087
- const data2 = await bridge.send("transaction", params2);
24203
+ const data2 = await callBridge(ctx, context, "transaction", params2);
24088
24204
  return JSON.stringify(data2);
24089
24205
  }
24090
24206
  const file2 = args.filePath;
24091
24207
  if (!file2)
24092
24208
  throw new Error("'filePath' parameter is required");
24093
- const filePath = path3.isAbsolute(file2) ? file2 : path3.resolve(context.directory, file2);
24094
- const relPath = path3.relative(context.worktree, filePath);
24209
+ const filePath = path4.isAbsolute(file2) ? file2 : path4.resolve(context.directory, file2);
24210
+ const relPath = path4.relative(context.worktree, filePath);
24095
24211
  await context.ask({
24096
24212
  permission: "edit",
24097
24213
  patterns: [relPath],
@@ -24144,7 +24260,7 @@ function createEditTool(ctx, writeToolName = "write") {
24144
24260
  params.diagnostics = true;
24145
24261
  if (!args.dryRun)
24146
24262
  params.include_diff = true;
24147
- const data = await bridge.send(command, params);
24263
+ const data = await callBridge(ctx, context, command, params);
24148
24264
  if (!args.dryRun && data.success && data.diff) {
24149
24265
  const diff = data.diff;
24150
24266
  const callID = getCallID(context);
@@ -24237,7 +24353,6 @@ function createApplyPatchTool(ctx) {
24237
24353
  patchText: z3.string().describe("The full patch text including Begin/End markers")
24238
24354
  },
24239
24355
  execute: async (args, context) => {
24240
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24241
24356
  const patchText = args.patchText;
24242
24357
  if (!patchText)
24243
24358
  throw new Error("'patchText' is required");
@@ -24250,7 +24365,7 @@ function createApplyPatchTool(ctx) {
24250
24365
  if (hunks.length === 0) {
24251
24366
  throw new Error("Empty patch: no file operations found");
24252
24367
  }
24253
- const allPaths = hunks.map((h) => path3.relative(context.worktree, path3.resolve(context.directory, h.path)));
24368
+ const allPaths = hunks.map((h) => path4.relative(context.worktree, path4.resolve(context.directory, h.path)));
24254
24369
  await context.ask({
24255
24370
  permission: "edit",
24256
24371
  patterns: allPaths,
@@ -24260,9 +24375,9 @@ function createApplyPatchTool(ctx) {
24260
24375
  const checkpointName = `apply_patch_${Date.now()}`;
24261
24376
  let checkpointCreated = false;
24262
24377
  try {
24263
- await bridge.send("checkpoint", {
24378
+ await callBridge(ctx, context, "checkpoint", {
24264
24379
  name: checkpointName,
24265
- files: allPaths.map((p) => path3.resolve(context.directory, p))
24380
+ files: allPaths.map((p) => path4.resolve(context.directory, p))
24266
24381
  });
24267
24382
  checkpointCreated = true;
24268
24383
  } catch {}
@@ -24270,11 +24385,11 @@ function createApplyPatchTool(ctx) {
24270
24385
  const perFileDiffs = [];
24271
24386
  let patchFailed = false;
24272
24387
  for (const hunk of hunks) {
24273
- const filePath = path3.resolve(context.directory, hunk.path);
24388
+ const filePath = path4.resolve(context.directory, hunk.path);
24274
24389
  switch (hunk.type) {
24275
24390
  case "add": {
24276
24391
  try {
24277
- await bridge.send("write", {
24392
+ await callBridge(ctx, context, "write", {
24278
24393
  file: filePath,
24279
24394
  content: hunk.contents.endsWith(`
24280
24395
  `) ? hunk.contents : `${hunk.contents}
@@ -24292,8 +24407,8 @@ function createApplyPatchTool(ctx) {
24292
24407
  }
24293
24408
  case "delete": {
24294
24409
  try {
24295
- const before = await fs2.promises.readFile(filePath, "utf-8").catch(() => "");
24296
- await bridge.send("delete_file", { file: filePath });
24410
+ const before = await fs3.promises.readFile(filePath, "utf-8").catch(() => "");
24411
+ await callBridge(ctx, context, "delete_file", { file: filePath });
24297
24412
  perFileDiffs.push({ filePath, before, after: "" });
24298
24413
  results.push(`Deleted ${hunk.path}`);
24299
24414
  } catch (e) {
@@ -24304,10 +24419,10 @@ function createApplyPatchTool(ctx) {
24304
24419
  }
24305
24420
  case "update": {
24306
24421
  try {
24307
- const original = await fs2.promises.readFile(filePath, "utf-8");
24422
+ const original = await fs3.promises.readFile(filePath, "utf-8");
24308
24423
  const newContent = applyUpdateChunks(original, filePath, hunk.chunks);
24309
- const targetPath = hunk.move_path ? path3.resolve(context.directory, hunk.move_path) : filePath;
24310
- const writeResult = await bridge.send("write", {
24424
+ const targetPath = hunk.move_path ? path4.resolve(context.directory, hunk.move_path) : filePath;
24425
+ const writeResult = await callBridge(ctx, context, "write", {
24311
24426
  file: targetPath,
24312
24427
  content: newContent,
24313
24428
  create_dirs: true,
@@ -24317,7 +24432,7 @@ function createApplyPatchTool(ctx) {
24317
24432
  if (diags && diags.length > 0) {
24318
24433
  const errors3 = diags.filter((d) => d.severity === "error");
24319
24434
  if (errors3.length > 0) {
24320
- const relPath = path3.relative(context.worktree, targetPath);
24435
+ const relPath = path4.relative(context.worktree, targetPath);
24321
24436
  const diagLines = errors3.map((d) => ` Line ${d.line}: ${d.message}`).join(`
24322
24437
  `);
24323
24438
  results.push(`
@@ -24327,7 +24442,7 @@ ${diagLines}`);
24327
24442
  }
24328
24443
  perFileDiffs.push({ filePath, before: original, after: newContent });
24329
24444
  if (hunk.move_path) {
24330
- await bridge.send("delete_file", { file: filePath });
24445
+ await callBridge(ctx, context, "delete_file", { file: filePath });
24331
24446
  results.push(`Updated and moved ${hunk.path} \u2192 ${hunk.move_path}`);
24332
24447
  } else {
24333
24448
  results.push(`Updated ${hunk.path}`);
@@ -24344,7 +24459,7 @@ ${diagLines}`);
24344
24459
  if (patchFailed) {
24345
24460
  if (checkpointCreated) {
24346
24461
  try {
24347
- await bridge.send("restore_checkpoint", { name: checkpointName });
24462
+ await callBridge(ctx, context, "restore_checkpoint", { name: checkpointName });
24348
24463
  results.push("Patch failed \u2014 restored files to pre-patch state.");
24349
24464
  } catch {
24350
24465
  results.push("Patch failed \u2014 checkpoint restore also failed, files may be inconsistent.");
@@ -24358,9 +24473,9 @@ ${diagLines}`);
24358
24473
  const callID = getCallID(context);
24359
24474
  if (callID) {
24360
24475
  const files = hunks.map((h) => {
24361
- const relPath = path3.relative(context.worktree, path3.resolve(context.directory, h.path));
24476
+ const relPath = path4.relative(context.worktree, path4.resolve(context.directory, h.path));
24362
24477
  return {
24363
- filePath: path3.resolve(context.directory, h.path),
24478
+ filePath: path4.resolve(context.directory, h.path),
24364
24479
  relativePath: relPath,
24365
24480
  type: h.type
24366
24481
  };
@@ -24397,15 +24512,14 @@ function createDeleteTool(ctx) {
24397
24512
  filePath: z3.string().describe("Path to file to delete")
24398
24513
  },
24399
24514
  execute: async (args, context) => {
24400
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24401
- const filePath = path3.isAbsolute(args.filePath) ? args.filePath : path3.resolve(context.directory, args.filePath);
24515
+ const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
24402
24516
  await context.ask({
24403
24517
  permission: "edit",
24404
24518
  patterns: [filePath],
24405
24519
  always: ["*"],
24406
24520
  metadata: { action: "delete" }
24407
24521
  });
24408
- const result = await bridge.send("delete_file", { file: filePath });
24522
+ const result = await callBridge(ctx, context, "delete_file", { file: filePath });
24409
24523
  if (result.success === false) {
24410
24524
  throw new Error(result.message || "delete failed");
24411
24525
  }
@@ -24423,16 +24537,15 @@ function createMoveTool(ctx) {
24423
24537
  destination: z3.string().describe("Destination file path")
24424
24538
  },
24425
24539
  execute: async (args, context) => {
24426
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24427
- const filePath = path3.isAbsolute(args.filePath) ? args.filePath : path3.resolve(context.directory, args.filePath);
24428
- const destPath = path3.isAbsolute(args.destination) ? args.destination : path3.resolve(context.directory, args.destination);
24540
+ const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
24541
+ const destPath = path4.isAbsolute(args.destination) ? args.destination : path4.resolve(context.directory, args.destination);
24429
24542
  await context.ask({
24430
24543
  permission: "edit",
24431
24544
  patterns: [filePath, destPath],
24432
24545
  always: ["*"],
24433
24546
  metadata: { action: "move" }
24434
24547
  });
24435
- const result = await bridge.send("move_file", {
24548
+ const result = await callBridge(ctx, context, "move_file", {
24436
24549
  file: filePath,
24437
24550
  destination: destPath
24438
24551
  });
@@ -24502,7 +24615,6 @@ function importTools(ctx) {
24502
24615
  dryRun: z4.boolean().optional().describe("Preview without modifying the file (default: false)")
24503
24616
  },
24504
24617
  execute: async (args, context) => {
24505
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24506
24618
  const op = args.op;
24507
24619
  const isDryRun = args.dryRun === true;
24508
24620
  if ((op === "add" || op === "remove") && typeof args.module !== "string") {
@@ -24534,7 +24646,7 @@ function importTools(ctx) {
24534
24646
  params.validate = args.validate;
24535
24647
  if (args.dryRun !== undefined)
24536
24648
  params.dry_run = args.dryRun;
24537
- const response = await bridge.send(commandMap[op], params);
24649
+ const response = await callBridge(ctx, context, commandMap[op], params);
24538
24650
  if (response.success === false) {
24539
24651
  throw new Error(response.message || `${op} failed`);
24540
24652
  }
@@ -24557,7 +24669,6 @@ function lspTools(ctx) {
24557
24669
  waitMs: z5.number().optional().describe("Wait N ms for fresh diagnostics before returning (max 10000, default: 0). Use after edits to let the server re-analyze.")
24558
24670
  },
24559
24671
  execute: async (args, context) => {
24560
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24561
24672
  const filePath = args.filePath || undefined;
24562
24673
  const directory = args.directory || undefined;
24563
24674
  if (filePath !== undefined && directory !== undefined) {
@@ -24572,7 +24683,7 @@ function lspTools(ctx) {
24572
24683
  params.severity = args.severity;
24573
24684
  if (args.waitMs !== undefined)
24574
24685
  params.wait_ms = args.waitMs;
24575
- const result = await bridge.send("lsp_diagnostics", params);
24686
+ const result = await callBridge(ctx, context, "lsp_diagnostics", params);
24576
24687
  if (result.success === false) {
24577
24688
  throw new Error(result.message || "lsp_diagnostics failed");
24578
24689
  }
@@ -24611,7 +24722,6 @@ function navigationTools(ctx) {
24611
24722
  expression: z6.string().optional().describe("Expression to track through data flow (required for trace_data op)")
24612
24723
  },
24613
24724
  execute: async (args, context) => {
24614
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24615
24725
  const params = {
24616
24726
  file: args.filePath,
24617
24727
  symbol: args.symbol
@@ -24623,7 +24733,7 @@ function navigationTools(ctx) {
24623
24733
  if (args.op === "trace_data" && typeof args.expression !== "string") {
24624
24734
  throw new Error("'expression' is required for 'trace_data' op");
24625
24735
  }
24626
- const response = await bridge.send(args.op, params);
24736
+ const response = await callBridge(ctx, context, args.op, params);
24627
24737
  if (response.success === false) {
24628
24738
  throw new Error(response.message || `${args.op} failed`);
24629
24739
  }
@@ -24635,7 +24745,7 @@ function navigationTools(ctx) {
24635
24745
 
24636
24746
  // src/tools/reading.ts
24637
24747
  import { readdir } from "fs/promises";
24638
- import { extname as extname2, join as join12, resolve as resolve4 } from "path";
24748
+ import { extname as extname2, join as join12, resolve as resolve5 } from "path";
24639
24749
  import { tool as tool7 } from "@opencode-ai/plugin";
24640
24750
  var OUTLINE_EXTENSIONS = new Set([
24641
24751
  ".ts",
@@ -24687,7 +24797,6 @@ function readingTools(ctx) {
24687
24797
  url: z7.string().optional().describe("HTTP/HTTPS URL of an HTML or Markdown document to fetch and outline")
24688
24798
  },
24689
24799
  execute: async (args, context) => {
24690
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24691
24800
  const filesArg = Array.isArray(args.files) ? args.files : undefined;
24692
24801
  const hasFilePath = typeof args.filePath === "string" && args.filePath.length > 0;
24693
24802
  const hasFiles = (filesArg?.length ?? 0) > 0;
@@ -24702,7 +24811,7 @@ function readingTools(ctx) {
24702
24811
  }
24703
24812
  if (hasUrl) {
24704
24813
  const cachedPath = await fetchUrlToTempFile(args.url, ctx.storageDir);
24705
- const response2 = await bridge.send("outline", { file: cachedPath });
24814
+ const response2 = await callBridge(ctx, context, "outline", { file: cachedPath });
24706
24815
  if (response2.success === false) {
24707
24816
  throw new Error(response2.message || "outline failed");
24708
24817
  }
@@ -24712,7 +24821,7 @@ function readingTools(ctx) {
24712
24821
  if (!dirArg && typeof args.filePath === "string" && !Array.isArray(args.files)) {
24713
24822
  try {
24714
24823
  const { stat } = await import("fs/promises");
24715
- const resolved = resolve4(context.directory, args.filePath);
24824
+ const resolved = resolve5(context.directory, args.filePath);
24716
24825
  const st = await stat(resolved);
24717
24826
  if (st.isDirectory()) {
24718
24827
  dirArg = args.filePath;
@@ -24720,7 +24829,7 @@ function readingTools(ctx) {
24720
24829
  } catch {}
24721
24830
  }
24722
24831
  if (dirArg) {
24723
- const dirPath = resolve4(context.directory, dirArg);
24832
+ const dirPath = resolve5(context.directory, dirArg);
24724
24833
  const files = await discoverSourceFiles(dirPath);
24725
24834
  if (files.length === 0) {
24726
24835
  return JSON.stringify({
@@ -24728,20 +24837,20 @@ function readingTools(ctx) {
24728
24837
  message: `No source files found under ${dirArg}`
24729
24838
  });
24730
24839
  }
24731
- const response2 = await bridge.send("outline", { files });
24840
+ const response2 = await callBridge(ctx, context, "outline", { files });
24732
24841
  if (response2.success === false) {
24733
24842
  throw new Error(response2.message || "outline failed");
24734
24843
  }
24735
24844
  return response2.text;
24736
24845
  }
24737
24846
  if (Array.isArray(args.files) && args.files.length > 0) {
24738
- const response2 = await bridge.send("outline", { files: args.files });
24847
+ const response2 = await callBridge(ctx, context, "outline", { files: args.files });
24739
24848
  if (response2.success === false) {
24740
24849
  throw new Error(response2.message || "outline failed");
24741
24850
  }
24742
24851
  return response2.text;
24743
24852
  }
24744
- const response = await bridge.send("outline", { file: args.filePath });
24853
+ const response = await callBridge(ctx, context, "outline", { file: args.filePath });
24745
24854
  if (response.success === false) {
24746
24855
  throw new Error(response.message || "outline failed");
24747
24856
  }
@@ -24760,7 +24869,6 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
24760
24869
  contextLines: z7.number().optional().describe("Lines of context before/after the symbol (default: 3)")
24761
24870
  },
24762
24871
  execute: async (args, context) => {
24763
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24764
24872
  const hasFilePath = typeof args.filePath === "string" && args.filePath.length > 0;
24765
24873
  const hasUrl = typeof args.url === "string" && args.url.length > 0;
24766
24874
  if (!hasFilePath && !hasUrl) {
@@ -24775,7 +24883,7 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
24775
24883
  const params2 = { file: file2, symbol: sym };
24776
24884
  if (args.contextLines !== undefined)
24777
24885
  params2.context_lines = args.contextLines;
24778
- return bridge.send("zoom", params2);
24886
+ return callBridge(ctx, context, "zoom", params2);
24779
24887
  }));
24780
24888
  return JSON.stringify(results);
24781
24889
  }
@@ -24784,7 +24892,7 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
24784
24892
  params.symbol = args.symbol;
24785
24893
  if (args.contextLines !== undefined)
24786
24894
  params.context_lines = args.contextLines;
24787
- const data = await bridge.send("zoom", params);
24895
+ const data = await callBridge(ctx, context, "zoom", params);
24788
24896
  if (data.success === false) {
24789
24897
  throw new Error(data.message || "zoom failed");
24790
24898
  }
@@ -24932,7 +25040,6 @@ function refactoringTools(ctx) {
24932
25040
  dryRun: z8.boolean().optional().describe("Preview changes as diff without modifying files (default: false)")
24933
25041
  },
24934
25042
  execute: async (args, context) => {
24935
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
24936
25043
  const op = args.op;
24937
25044
  if ((op === "move" || op === "inline") && typeof args.symbol !== "string") {
24938
25045
  throw new Error(`'symbol' is required for '${op}' op`);
@@ -24989,7 +25096,7 @@ function refactoringTools(ctx) {
24989
25096
  const hints = await queryLspHints(ctx.client, args.symbol ?? args.name);
24990
25097
  if (hints)
24991
25098
  params.lsp_hints = hints;
24992
- const response = await bridge.send(commandMap[op], params);
25099
+ const response = await callBridge(ctx, context, commandMap[op], params);
24993
25100
  if (response.success === false) {
24994
25101
  throw new Error(response.message || `${op} failed`);
24995
25102
  }
@@ -25028,7 +25135,6 @@ function safetyTools(ctx) {
25028
25135
  files: z9.array(z9.string()).optional().describe("Specific files to include in checkpoint (optional, defaults to all tracked files)")
25029
25136
  },
25030
25137
  execute: async (args, context) => {
25031
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
25032
25138
  const op = args.op;
25033
25139
  if ((op === "undo" || op === "history") && typeof args.filePath !== "string") {
25034
25140
  throw new Error(`'filePath' is required for '${op}' op`);
@@ -25063,7 +25169,7 @@ function safetyTools(ctx) {
25063
25169
  params.name = args.name;
25064
25170
  if (args.files !== undefined)
25065
25171
  params.files = args.files;
25066
- const response = await bridge.send(commandMap[op], params);
25172
+ const response = await callBridge(ctx, context, commandMap[op], params);
25067
25173
  if (response.success === false) {
25068
25174
  throw new Error(response.message || `${op} failed`);
25069
25175
  }
@@ -25113,8 +25219,7 @@ function searchTools(ctx) {
25113
25219
  path: arg(exports_external.string().optional().describe("Directory to search in, relative to project root"))
25114
25220
  },
25115
25221
  execute: async (args, context) => {
25116
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
25117
- const response = await bridge.send("grep", {
25222
+ const response = await callBridge(ctx, context, "grep", {
25118
25223
  pattern: args.pattern,
25119
25224
  case_sensitive: true,
25120
25225
  include: args.include ? String(args.include).split(",").map((s) => normalizeGlob(s.trim())).filter(Boolean) : undefined,
@@ -25134,7 +25239,6 @@ function searchTools(ctx) {
25134
25239
  path: arg(exports_external.string().optional().describe("Directory to search in, relative to project root"))
25135
25240
  },
25136
25241
  execute: async (args, context) => {
25137
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
25138
25242
  let globPattern = String(args.pattern);
25139
25243
  let globPath = args.path ? String(args.path) : undefined;
25140
25244
  if (!globPath && globPattern.startsWith("/")) {
@@ -25147,7 +25251,7 @@ function searchTools(ctx) {
25147
25251
  }
25148
25252
  }
25149
25253
  }
25150
- const response = await bridge.send("glob", {
25254
+ const response = await callBridge(ctx, context, "glob", {
25151
25255
  pattern: globPattern,
25152
25256
  path: globPath
25153
25257
  });
@@ -25183,8 +25287,7 @@ function semanticTools(ctx) {
25183
25287
  topK: arg2(exports_external.number().optional().describe("Number of results (default: 10)"))
25184
25288
  },
25185
25289
  execute: async (args, context) => {
25186
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
25187
- const response = await bridge.send("semantic_search", {
25290
+ const response = await callBridge(ctx, context, "semantic_search", {
25188
25291
  query: args.query,
25189
25292
  top_k: args.topK ?? 10
25190
25293
  });
@@ -25248,7 +25351,6 @@ function structureTools(ctx) {
25248
25351
  dryRun: z10.boolean().optional().describe("Preview without modifying the file (default: false)")
25249
25352
  },
25250
25353
  execute: async (args, context) => {
25251
- const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
25252
25354
  const op = args.op;
25253
25355
  if (op === "add_member") {
25254
25356
  if (typeof args.container !== "string")
@@ -25312,7 +25414,7 @@ function structureTools(ctx) {
25312
25414
  params.value = args.value;
25313
25415
  break;
25314
25416
  }
25315
- const response = await bridge.send(op, params);
25417
+ const response = await callBridge(ctx, context, op, params);
25316
25418
  if (response.success === false) {
25317
25419
  throw new Error(response.message || `${op} failed`);
25318
25420
  }
@@ -25358,6 +25460,8 @@ var PLUGIN_VERSION = (() => {
25358
25460
  return "0.0.0";
25359
25461
  }
25360
25462
  })();
25463
+ var ANNOUNCEMENT_VERSION = "";
25464
+ var ANNOUNCEMENT_FEATURES = [];
25361
25465
  var plugin = async (input) => {
25362
25466
  const binaryPath = await findBinary();
25363
25467
  const aftConfig = loadAftConfig(input.directory);
@@ -25401,10 +25505,10 @@ var plugin = async (input) => {
25401
25505
  }
25402
25506
  versionUpgradeAttempted = binaryVersion;
25403
25507
  warn(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
25404
- ensureBinary(`v${minVersion}`).then((path4) => {
25405
- if (path4) {
25406
- log(`Found/downloaded compatible binary at ${path4}. Replacing running bridges...`);
25407
- pool.replaceBinary(path4).then(() => {
25508
+ ensureBinary(`v${minVersion}`).then((path5) => {
25509
+ if (path5) {
25510
+ log(`Found/downloaded compatible binary at ${path5}. Replacing running bridges...`);
25511
+ pool.replaceBinary(path5).then(() => {
25408
25512
  log("Binary replaced successfully. New bridges will use the updated binary.");
25409
25513
  }, (err) => error48("Failed to replace binary:", err));
25410
25514
  } else {
@@ -25423,36 +25527,39 @@ var plugin = async (input) => {
25423
25527
  };
25424
25528
  setSharedBridgePool(pool);
25425
25529
  const rpcServer = new AftRpcServer(configOverrides.storage_dir, input.directory);
25530
+ const unregisterShutdown = registerShutdownCleanup(async () => {
25531
+ try {
25532
+ rpcServer.stop();
25533
+ } catch {}
25534
+ await pool.shutdown();
25535
+ });
25426
25536
  rpcServer.handle("status", async (params) => {
25427
25537
  const sessionID = params.sessionID || "rpc";
25428
- const bridge = pool.getAnyActiveBridge(input.directory) ?? pool.getBridge(input.directory, sessionID);
25429
- return await bridge.send("status", {});
25538
+ const bridge = pool.getAnyActiveBridge(input.directory) ?? pool.getBridge(input.directory);
25539
+ return await bridge.send("status", { session_id: sessionID });
25430
25540
  });
25431
25541
  const storageDir = configOverrides.storage_dir;
25432
- const featureList = [
25433
- "Semantic code search (`aft_search`) \u2014 enable with `experimental_semantic_search: true` in aft.jsonc",
25434
- "/aft-status command \u2014 live index health, disk usage, and runtime details",
25435
- "HTML outline and zoom \u2014 heading hierarchy for .html/.htm files",
25436
- "And many bugfixes"
25437
- ];
25438
25542
  rpcServer.handle("get-announcement", async () => {
25543
+ if (!ANNOUNCEMENT_VERSION || ANNOUNCEMENT_FEATURES.length === 0) {
25544
+ return { show: false };
25545
+ }
25439
25546
  if (storageDir) {
25440
25547
  const versionFile = join13(storageDir, "last_announced_version");
25441
25548
  try {
25442
25549
  if (existsSync8(versionFile)) {
25443
25550
  const lastVersion = readFileSync5(versionFile, "utf-8").trim();
25444
- if (lastVersion === PLUGIN_VERSION)
25551
+ if (lastVersion === ANNOUNCEMENT_VERSION)
25445
25552
  return { show: false };
25446
25553
  }
25447
25554
  } catch {}
25448
25555
  }
25449
- return { show: true, version: PLUGIN_VERSION, features: featureList };
25556
+ return { show: true, version: ANNOUNCEMENT_VERSION, features: ANNOUNCEMENT_FEATURES };
25450
25557
  });
25451
25558
  rpcServer.handle("mark-announced", async () => {
25452
- if (storageDir) {
25559
+ if (storageDir && ANNOUNCEMENT_VERSION) {
25453
25560
  try {
25454
25561
  mkdirSync8(storageDir, { recursive: true });
25455
- writeFileSync5(join13(storageDir, "last_announced_version"), PLUGIN_VERSION);
25562
+ writeFileSync5(join13(storageDir, "last_announced_version"), ANNOUNCEMENT_VERSION);
25456
25563
  } catch {}
25457
25564
  }
25458
25565
  return { success: true };
@@ -25478,9 +25585,11 @@ Install: ${getManualInstallHint()}`);
25478
25585
  client: input.client,
25479
25586
  directory: input.directory
25480
25587
  };
25481
- setTimeout(() => {
25482
- sendFeatureAnnouncement(notifyOpts, PLUGIN_VERSION, featureList, storageDir).catch(() => {});
25483
- }, 8000);
25588
+ if (ANNOUNCEMENT_VERSION && ANNOUNCEMENT_FEATURES.length > 0) {
25589
+ setTimeout(() => {
25590
+ sendFeatureAnnouncement(notifyOpts, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, storageDir).catch(() => {});
25591
+ }, 8000);
25592
+ }
25484
25593
  if (aftConfig.experimental_semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
25485
25594
  setTimeout(() => {
25486
25595
  if (!configOverrides._ort_dylib_dir && !isOrtAutoDownloadSupported()) {
@@ -25537,8 +25646,8 @@ Install: ${getManualInstallHint()}`).catch(() => {});
25537
25646
  if (isTuiMode2() || commandInput.command !== STATUS_COMMAND) {
25538
25647
  return;
25539
25648
  }
25540
- const bridge = ctx.pool.getAnyActiveBridge(input.directory) ?? ctx.pool.getBridge(input.directory, commandInput.sessionID);
25541
- const response = await bridge.send("status", {});
25649
+ const bridge = ctx.pool.getAnyActiveBridge(input.directory) ?? ctx.pool.getBridge(input.directory);
25650
+ const response = await bridge.send("status", { session_id: commandInput.sessionID });
25542
25651
  if (response.success === false) {
25543
25652
  throw new Error(response.message || "status failed");
25544
25653
  }
@@ -25581,6 +25690,7 @@ Install: ${getManualInstallHint()}`).catch(() => {});
25581
25690
  };
25582
25691
  },
25583
25692
  dispose: () => {
25693
+ unregisterShutdown();
25584
25694
  rpcServer.stop();
25585
25695
  clearSharedBridgePool();
25586
25696
  return pool.shutdown();