@cortexkit/aft-opencode 0.39.4 → 0.40.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/tui.js CHANGED
@@ -4568,45 +4568,45 @@ var require_esprima = __commonJS((exports, module) => {
4568
4568
  this.errors = [];
4569
4569
  this.tolerant = false;
4570
4570
  }
4571
- ErrorHandler2.prototype.recordError = function(error) {
4572
- this.errors.push(error);
4571
+ ErrorHandler2.prototype.recordError = function(error2) {
4572
+ this.errors.push(error2);
4573
4573
  };
4574
- ErrorHandler2.prototype.tolerate = function(error) {
4574
+ ErrorHandler2.prototype.tolerate = function(error2) {
4575
4575
  if (this.tolerant) {
4576
- this.recordError(error);
4576
+ this.recordError(error2);
4577
4577
  } else {
4578
- throw error;
4578
+ throw error2;
4579
4579
  }
4580
4580
  };
4581
4581
  ErrorHandler2.prototype.constructError = function(msg, column) {
4582
- var error = new Error(msg);
4582
+ var error2 = new Error(msg);
4583
4583
  try {
4584
- throw error;
4584
+ throw error2;
4585
4585
  } catch (base) {
4586
4586
  if (Object.create && Object.defineProperty) {
4587
- error = Object.create(base);
4588
- Object.defineProperty(error, "column", { value: column });
4587
+ error2 = Object.create(base);
4588
+ Object.defineProperty(error2, "column", { value: column });
4589
4589
  }
4590
4590
  }
4591
- return error;
4591
+ return error2;
4592
4592
  };
4593
4593
  ErrorHandler2.prototype.createError = function(index, line, col, description) {
4594
4594
  var msg = "Line " + line + ": " + description;
4595
- var error = this.constructError(msg, col);
4596
- error.index = index;
4597
- error.lineNumber = line;
4598
- error.description = description;
4599
- return error;
4595
+ var error2 = this.constructError(msg, col);
4596
+ error2.index = index;
4597
+ error2.lineNumber = line;
4598
+ error2.description = description;
4599
+ return error2;
4600
4600
  };
4601
4601
  ErrorHandler2.prototype.throwError = function(index, line, col, description) {
4602
4602
  throw this.createError(index, line, col, description);
4603
4603
  };
4604
4604
  ErrorHandler2.prototype.tolerateError = function(index, line, col, description) {
4605
- var error = this.createError(index, line, col, description);
4605
+ var error2 = this.createError(index, line, col, description);
4606
4606
  if (this.tolerant) {
4607
- this.recordError(error);
4607
+ this.recordError(error2);
4608
4608
  } else {
4609
- throw error;
4609
+ throw error2;
4610
4610
  }
4611
4611
  };
4612
4612
  return ErrorHandler2;
@@ -7276,19 +7276,19 @@ var require_parse = __commonJS((exports, module) => {
7276
7276
  var symbolFor = (prefix) => Symbol.for(last_prop !== UNDEFINED ? prefix + COLON + last_prop : prefix);
7277
7277
  var transform = (k, { value, context = {} }) => reviver ? reviver(k, value, context) : value;
7278
7278
  var unexpected = () => {
7279
- const error = new SyntaxError(`Unexpected token '${current.value.slice(0, 1)}', "${current_code}" is not valid JSON`);
7280
- Object.assign(error, current.loc.start);
7279
+ const error2 = new SyntaxError(`Unexpected token '${current.value.slice(0, 1)}', "${current_code}" is not valid JSON`);
7280
+ Object.assign(error2, current.loc.start);
7281
7281
  free();
7282
- throw error;
7282
+ throw error2;
7283
7283
  };
7284
7284
  var unexpected_end = () => {
7285
- const error = new SyntaxError("Unexpected end of JSON input");
7286
- Object.assign(error, last ? last.loc.end : {
7285
+ const error2 = new SyntaxError("Unexpected end of JSON input");
7286
+ Object.assign(error2, last ? last.loc.end : {
7287
7287
  line: 1,
7288
7288
  column: 0
7289
7289
  });
7290
7290
  free();
7291
- throw error;
7291
+ throw error2;
7292
7292
  };
7293
7293
  var next = () => {
7294
7294
  const new_token = tokens[++index];
@@ -7637,10 +7637,10 @@ var require_stringify = __commonJS((exports, module) => {
7637
7637
  replacer = null;
7638
7638
  indent = EMPTY;
7639
7639
  };
7640
- var join4 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
7640
+ var join5 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
7641
7641
  var join_content = (inside, value, gap) => {
7642
7642
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
7643
- return join4(comment, inside, gap);
7643
+ return join5(comment, inside, gap);
7644
7644
  };
7645
7645
  var stringify_string = (holder, key, value) => {
7646
7646
  const raw = get_raw_string_literal(holder, key);
@@ -7662,13 +7662,13 @@ var require_stringify = __commonJS((exports, module) => {
7662
7662
  if (i !== 0) {
7663
7663
  inside += COMMA;
7664
7664
  }
7665
- const before = join4(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7665
+ const before = join5(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7666
7666
  inside += before || LF + deeper_gap;
7667
7667
  inside += stringify(i, value, deeper_gap) || STR_NULL;
7668
7668
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
7669
7669
  after_comma = process_comments(value, AFTER(i), deeper_gap);
7670
7670
  }
7671
- inside += join4(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7671
+ inside += join5(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7672
7672
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
7673
7673
  };
7674
7674
  var object_stringify = (value, gap) => {
@@ -7689,13 +7689,13 @@ var require_stringify = __commonJS((exports, module) => {
7689
7689
  inside += COMMA;
7690
7690
  }
7691
7691
  first = false;
7692
- const before = join4(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7692
+ const before = join5(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7693
7693
  inside += before || LF + deeper_gap;
7694
7694
  inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
7695
7695
  after_comma = process_comments(value, AFTER(key), deeper_gap);
7696
7696
  };
7697
7697
  keys.forEach(iteratee);
7698
- inside += join4(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7698
+ inside += join5(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7699
7699
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
7700
7700
  };
7701
7701
  function stringify(key, holder, gap) {
@@ -7790,26 +7790,1244 @@ var require_src2 = __commonJS((exports, module) => {
7790
7790
  // src/tui/index.tsx
7791
7791
  import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
7792
7792
  // package.json
7793
- var version = "0.39.4";
7793
+ var version = "0.40.0";
7794
7794
 
7795
7795
  // src/shared/rpc-client.ts
7796
7796
  import { existsSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
7797
- import { join as join2 } from "node:path";
7797
+ import { join as join3 } from "node:path";
7798
7798
 
7799
7799
  // src/shared/rpc-utils.ts
7800
- import { createHash } from "node:crypto";
7800
+ import { join as join2 } from "node:path";
7801
+
7802
+ // ../aft-bridge/dist/active-logger.js
7803
+ var ACTIVE_LOGGER_SYMBOL = Symbol.for("aft-bridge-active-logger");
7804
+ function loggerGlobal() {
7805
+ return globalThis;
7806
+ }
7807
+ function getActiveLogger() {
7808
+ return loggerGlobal()[ACTIVE_LOGGER_SYMBOL];
7809
+ }
7810
+ function getLogFilePath() {
7811
+ try {
7812
+ return getActiveLogger()?.getLogFilePath?.();
7813
+ } catch (err) {
7814
+ console.error(`[aft-bridge] ERROR: active logger getLogFilePath threw: ${err instanceof Error ? err.message : String(err)}`);
7815
+ return;
7816
+ }
7817
+ }
7818
+ function log(message, meta) {
7819
+ const active = getActiveLogger();
7820
+ if (active) {
7821
+ try {
7822
+ active.log(message, meta);
7823
+ } catch (err) {
7824
+ console.error(`[aft-bridge] ERROR: active logger log threw: ${err instanceof Error ? err.message : String(err)}`);
7825
+ console.error(`[aft-bridge] ${message}`);
7826
+ }
7827
+ } else {
7828
+ console.error(`[aft-bridge] ${message}`);
7829
+ }
7830
+ }
7831
+ function warn(message, meta) {
7832
+ const active = getActiveLogger();
7833
+ if (active) {
7834
+ try {
7835
+ active.warn(message, meta);
7836
+ } catch (err) {
7837
+ console.error(`[aft-bridge] ERROR: active logger warn threw: ${err instanceof Error ? err.message : String(err)}`);
7838
+ console.error(`[aft-bridge] WARN: ${message}`);
7839
+ }
7840
+ } else {
7841
+ console.error(`[aft-bridge] WARN: ${message}`);
7842
+ }
7843
+ }
7844
+ function error(message, meta) {
7845
+ const active = getActiveLogger();
7846
+ if (active) {
7847
+ try {
7848
+ active.error(message, meta);
7849
+ } catch (err) {
7850
+ console.error(`[aft-bridge] ERROR: active logger error threw: ${err instanceof Error ? err.message : String(err)}`);
7851
+ console.error(`[aft-bridge] ERROR: ${message}`);
7852
+ }
7853
+ } else {
7854
+ console.error(`[aft-bridge] ERROR: ${message}`);
7855
+ }
7856
+ }
7857
+ // ../aft-bridge/dist/bridge.js
7858
+ import { spawn } from "node:child_process";
7859
+ import { homedir } from "node:os";
7801
7860
  import { join } from "node:path";
7861
+ import { StringDecoder } from "node:string_decoder";
7862
+
7863
+ // ../aft-bridge/dist/command-timeouts.js
7864
+ var PASSIVE_COMMANDS = new Set(["status"]);
7865
+ var PASSIVE_COMMAND_TIMEOUT_MS = 5000;
7866
+ function isPassiveCommand(command) {
7867
+ return PASSIVE_COMMANDS.has(command);
7868
+ }
7869
+
7870
+ // ../aft-bridge/dist/status-bar.js
7871
+ function parseStatusBarCounts(value) {
7872
+ if (!value || typeof value !== "object")
7873
+ return;
7874
+ const record = value;
7875
+ const num = (key) => {
7876
+ const raw = record[key];
7877
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
7878
+ };
7879
+ return {
7880
+ errors: num("errors"),
7881
+ warnings: num("warnings"),
7882
+ dead_code: num("dead_code"),
7883
+ unused_exports: num("unused_exports"),
7884
+ duplicates: num("duplicates"),
7885
+ todos: num("todos"),
7886
+ tier2_stale: record.tier2_stale === true
7887
+ };
7888
+ }
7889
+
7890
+ // ../aft-bridge/dist/bridge.js
7891
+ var DEFAULT_BRIDGE_TIMEOUT_MS = 30000;
7892
+ var BRIDGE_HANG_TIMEOUT_THRESHOLD = 2;
7893
+ var MAX_STDOUT_BUFFER = 64 * 1024 * 1024;
7894
+ var STDOUT_BUFFER_COMPACT_THRESHOLD = 64 * 1024;
7895
+ var TERMINAL_BASH_STATUSES = new Set([
7896
+ "completed",
7897
+ "failed",
7898
+ "killed",
7899
+ "timed_out",
7900
+ "cancelled",
7901
+ "timeout"
7902
+ ]);
7903
+ function isTerminalBashStatus(status) {
7904
+ return typeof status === "string" && TERMINAL_BASH_STATUSES.has(status);
7905
+ }
7906
+ function bashTaskIdFrom(response) {
7907
+ const snakeCase = response.task_id;
7908
+ if (typeof snakeCase === "string" && snakeCase.length > 0)
7909
+ return snakeCase;
7910
+ const camelCase = response.taskId;
7911
+ if (typeof camelCase === "string" && camelCase.length > 0)
7912
+ return camelCase;
7913
+ return;
7914
+ }
7915
+ function tagStderrLine(line) {
7916
+ return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
7917
+ }
7918
+ var BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo";
7919
+ function shouldSurfaceStderrLine(line) {
7920
+ const normalized = line.trim();
7921
+ return !(normalized === `Error in cpuinfo: ${BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE}` || normalized === BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE);
7922
+ }
7923
+ function compareSemver(a, b) {
7924
+ const [aMain, aPre] = a.split("-", 2);
7925
+ const [bMain, bPre] = b.split("-", 2);
7926
+ const aParts = aMain.split(".").map(Number);
7927
+ const bParts = bMain.split(".").map(Number);
7928
+ for (let i = 0;i < 3; i++) {
7929
+ if (aParts[i] !== bParts[i])
7930
+ return (aParts[i] ?? 0) - (bParts[i] ?? 0);
7931
+ }
7932
+ if (!aPre && !bPre)
7933
+ return 0;
7934
+ if (!aPre)
7935
+ return 1;
7936
+ if (!bPre)
7937
+ return -1;
7938
+ const aIds = aPre.split(".");
7939
+ const bIds = bPre.split(".");
7940
+ for (let i = 0;i < Math.max(aIds.length, bIds.length); i++) {
7941
+ const ai = aIds[i];
7942
+ const bi = bIds[i];
7943
+ if (ai === undefined)
7944
+ return -1;
7945
+ if (bi === undefined)
7946
+ return 1;
7947
+ const aNum = /^\d+$/.test(ai);
7948
+ const bNum = /^\d+$/.test(bi);
7949
+ if (aNum && bNum) {
7950
+ const diff = Number.parseInt(ai, 10) - Number.parseInt(bi, 10);
7951
+ if (diff !== 0)
7952
+ return diff;
7953
+ } else if (aNum) {
7954
+ return -1;
7955
+ } else if (bNum) {
7956
+ return 1;
7957
+ } else {
7958
+ const cmp = ai.localeCompare(bi);
7959
+ if (cmp !== 0)
7960
+ return cmp;
7961
+ }
7962
+ }
7963
+ return 0;
7964
+ }
7965
+ function coerceConfigureDroppedKeys(value) {
7966
+ if (!Array.isArray(value))
7967
+ return [];
7968
+ const dropped = [];
7969
+ for (const item of value) {
7970
+ if (!item || typeof item !== "object" || Array.isArray(item))
7971
+ continue;
7972
+ const record = item;
7973
+ if (typeof record.key === "string" && typeof record.tier === "string" && typeof record.reason === "string") {
7974
+ dropped.push({ key: record.key, tier: record.tier, reason: record.reason });
7975
+ }
7976
+ }
7977
+ return dropped;
7978
+ }
7979
+
7980
+ class BridgeReplacedDuringVersionCheck extends Error {
7981
+ newBinaryPath;
7982
+ constructor(newBinaryPath) {
7983
+ super(`Bridge binary replaced during version check: ${newBinaryPath}`);
7984
+ this.newBinaryPath = newBinaryPath;
7985
+ this.name = "BridgeReplacedDuringVersionCheck";
7986
+ }
7987
+ }
7988
+
7989
+ class BridgeTransportTimeoutError extends Error {
7990
+ command;
7991
+ timeoutMs;
7992
+ code = "transport_timeout";
7993
+ constructor(command, timeoutMs, message) {
7994
+ super(message);
7995
+ this.command = command;
7996
+ this.timeoutMs = timeoutMs;
7997
+ this.name = "BridgeTransportTimeoutError";
7998
+ }
7999
+ }
8000
+ class BinaryBridge {
8001
+ static RESTART_RESET_MS = 5 * 60 * 1000;
8002
+ static STDERR_TAIL_MAX = 20;
8003
+ binaryPath;
8004
+ cwd;
8005
+ process = null;
8006
+ pending = new Map;
8007
+ outstandingBackgroundTaskIds = new Set;
8008
+ nextId = 1;
8009
+ stdoutBuffer = "";
8010
+ stdoutReadOffset = 0;
8011
+ stderrBuffer = "";
8012
+ stderrTail = [];
8013
+ _restartCount = 0;
8014
+ _shuttingDown = false;
8015
+ timeoutMs;
8016
+ hangThreshold;
8017
+ maxRestarts;
8018
+ configured = false;
8019
+ _configurePromise = null;
8020
+ configOverrides;
8021
+ minVersion;
8022
+ onVersionMismatch;
8023
+ onConfigureWarnings;
8024
+ onBashCompletion;
8025
+ onBashLongRunning;
8026
+ onBashPatternMatch;
8027
+ cachedStatus = null;
8028
+ statusListeners = new Set;
8029
+ configureWarningClients = new Map;
8030
+ restartResetTimer = null;
8031
+ lastChildActivityAt = 0;
8032
+ lastStatusBar;
8033
+ consecutiveRequestTimeouts = 0;
8034
+ errorPrefix;
8035
+ logger;
8036
+ childEnv;
8037
+ constructor(binaryPath, cwd, options, configOverrides) {
8038
+ this.binaryPath = binaryPath;
8039
+ this.cwd = cwd;
8040
+ this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
8041
+ this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
8042
+ this.maxRestarts = options?.maxRestarts ?? 3;
8043
+ this.configOverrides = configOverrides ?? {};
8044
+ this.minVersion = options?.minVersion;
8045
+ this.onVersionMismatch = options?.onVersionMismatch;
8046
+ this.onConfigureWarnings = options?.onConfigureWarnings;
8047
+ this.onBashCompletion = options?.onBashCompletion;
8048
+ this.onBashLongRunning = options?.onBashLongRunning;
8049
+ this.onBashPatternMatch = options?.onBashPatternMatch;
8050
+ this.errorPrefix = options?.errorPrefix ?? "[aft-bridge]";
8051
+ this.logger = options?.logger;
8052
+ this.childEnv = options?.childEnv;
8053
+ }
8054
+ logVia(message, meta) {
8055
+ const logger = this.logger ?? getActiveLogger();
8056
+ if (logger) {
8057
+ try {
8058
+ logger.log(message, meta);
8059
+ } catch (err) {
8060
+ console.error(`[aft-bridge] ERROR: logger log threw: ${err instanceof Error ? err.message : String(err)}`);
8061
+ console.error(`[aft-bridge] ${message}`);
8062
+ }
8063
+ } else {
8064
+ log(message, meta);
8065
+ }
8066
+ }
8067
+ warnVia(message, meta) {
8068
+ const logger = this.logger ?? getActiveLogger();
8069
+ if (logger) {
8070
+ try {
8071
+ logger.warn(message, meta);
8072
+ } catch (err) {
8073
+ console.error(`[aft-bridge] ERROR: logger warn threw: ${err instanceof Error ? err.message : String(err)}`);
8074
+ console.error(`[aft-bridge] WARN: ${message}`);
8075
+ }
8076
+ } else {
8077
+ warn(message, meta);
8078
+ }
8079
+ }
8080
+ errorVia(message, meta) {
8081
+ const logger = this.logger ?? getActiveLogger();
8082
+ if (logger) {
8083
+ try {
8084
+ logger.error(message, meta);
8085
+ } catch (err) {
8086
+ console.error(`[aft-bridge] ERROR: logger error threw: ${err instanceof Error ? err.message : String(err)}`);
8087
+ console.error(`[aft-bridge] ERROR: ${message}`);
8088
+ }
8089
+ } else {
8090
+ error(message, meta);
8091
+ }
8092
+ }
8093
+ getLogFilePathVia() {
8094
+ if (this.logger?.getLogFilePath) {
8095
+ try {
8096
+ return this.logger.getLogFilePath();
8097
+ } catch (err) {
8098
+ console.error(`[aft-bridge] ERROR: logger getLogFilePath threw: ${err instanceof Error ? err.message : String(err)}`);
8099
+ return;
8100
+ }
8101
+ }
8102
+ return getLogFilePath();
8103
+ }
8104
+ sessionLogVia(sessionId, message) {
8105
+ this.logVia(message, sessionId ? { sessionId } : undefined);
8106
+ }
8107
+ sessionWarnVia(sessionId, message) {
8108
+ this.warnVia(message, sessionId ? { sessionId } : undefined);
8109
+ }
8110
+ sessionErrorVia(sessionId, message) {
8111
+ this.errorVia(message, sessionId ? { sessionId } : undefined);
8112
+ }
8113
+ get restartCount() {
8114
+ return this._restartCount;
8115
+ }
8116
+ isAlive() {
8117
+ return this.process !== null && this.process.exitCode === null && !this.process.killed;
8118
+ }
8119
+ hasPendingRequests() {
8120
+ return this.pending.size > 0;
8121
+ }
8122
+ hasOutstandingBackgroundTasks() {
8123
+ return this.outstandingBackgroundTaskIds.size > 0;
8124
+ }
8125
+ getCwd() {
8126
+ return this.cwd;
8127
+ }
8128
+ getCachedStatus() {
8129
+ return this.cachedStatus;
8130
+ }
8131
+ subscribeStatus(listener) {
8132
+ this.statusListeners.add(listener);
8133
+ if (this.cachedStatus !== null) {
8134
+ this.deliverStatusSnapshot(listener, this.cachedStatus);
8135
+ }
8136
+ return () => {
8137
+ this.statusListeners.delete(listener);
8138
+ };
8139
+ }
8140
+ cacheStatusSnapshot(snapshot) {
8141
+ this.cachedStatus = snapshot;
8142
+ }
8143
+ async send(command, params = {}, options) {
8144
+ return this.sendWithVersionMismatchRetry(command, params, options, true);
8145
+ }
8146
+ async sendWithVersionMismatchRetry(command, params, options, canRetryAfterVersionSwap) {
8147
+ try {
8148
+ if (this._shuttingDown) {
8149
+ throw new Error(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
8150
+ }
8151
+ if (Object.hasOwn(params, "id")) {
8152
+ throw new Error("params cannot contain reserved key 'id'");
8153
+ }
8154
+ const requestSessionId = typeof params.session_id === "string" && params.session_id.length > 0 ? params.session_id : undefined;
8155
+ this.ensureSpawned(requestSessionId);
8156
+ if (requestSessionId && options?.configureWarningClient !== undefined) {
8157
+ this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
8158
+ }
8159
+ const passive = isPassiveCommand(command);
8160
+ const resolvedTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
8161
+ const effectiveTimeoutMs = passive ? Math.min(resolvedTimeoutMs, PASSIVE_COMMAND_TIMEOUT_MS) : resolvedTimeoutMs;
8162
+ const implicitTransportOptions = {
8163
+ ...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
8164
+ markConfiguredOnSuccess: false
8165
+ };
8166
+ if (!this.configured) {
8167
+ if (command !== "configure" && command !== "version") {
8168
+ if (!this._configurePromise) {
8169
+ const sessionIdForConfigure = typeof params.session_id === "string" ? params.session_id : undefined;
8170
+ this._configurePromise = (async () => {
8171
+ try {
8172
+ const configResult = await this.send("configure", {
8173
+ project_root: this.cwd,
8174
+ ...this.configOverrides,
8175
+ ...sessionIdForConfigure ? { session_id: sessionIdForConfigure } : {}
8176
+ }, implicitTransportOptions);
8177
+ if (configResult.success === false) {
8178
+ throw new Error(`${this.errorPrefix} Configure failed: ${configResult.message ?? "unknown error"}`);
8179
+ }
8180
+ await this.deliverConfigureWarnings(configResult, params, options);
8181
+ await this.checkVersion(implicitTransportOptions);
8182
+ if (!this.isAlive()) {
8183
+ throw new Error(`${this.errorPrefix} Bridge died during version check. Check logs: ${this.getLogFilePathVia()}`);
8184
+ }
8185
+ this.configured = true;
8186
+ } finally {
8187
+ this._configurePromise = null;
8188
+ }
8189
+ })();
8190
+ }
8191
+ await this._configurePromise;
8192
+ }
8193
+ }
8194
+ const id = String(this.nextId++);
8195
+ let request;
8196
+ if (Object.hasOwn(params, "command") || Object.hasOwn(params, "method")) {
8197
+ const nested = { ...params };
8198
+ const reserved = {};
8199
+ for (const key of ["session_id", "lsp_hints"]) {
8200
+ if (Object.hasOwn(nested, key)) {
8201
+ reserved[key] = nested[key];
8202
+ delete nested[key];
8203
+ }
8204
+ }
8205
+ request = { id, command, ...reserved, params: nested };
8206
+ } else {
8207
+ request = { id, command, ...params };
8208
+ }
8209
+ const line = `${JSON.stringify(request)}
8210
+ `;
8211
+ const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
8212
+ let requestSentAt = Date.now();
8213
+ const response = await new Promise((resolve, reject) => {
8214
+ const timer = setTimeout(() => {
8215
+ const entry = this.pending.get(id);
8216
+ if (!entry)
8217
+ return;
8218
+ this.pending.delete(id);
8219
+ clearTimeout(entry.timer);
8220
+ if (keepBridgeOnTimeout) {
8221
+ const timeoutMsg2 = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`;
8222
+ if (requestSessionId) {
8223
+ this.sessionWarnVia(requestSessionId, timeoutMsg2);
8224
+ } else {
8225
+ this.warnVia(timeoutMsg2);
8226
+ }
8227
+ entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
8228
+ return;
8229
+ }
8230
+ const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
8231
+ const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
8232
+ this.consecutiveRequestTimeouts = consecutiveTimeouts;
8233
+ const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
8234
+ const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
8235
+ const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
8236
+ if (requestSessionId) {
8237
+ this.sessionWarnVia(requestSessionId, timeoutMsg);
8238
+ } else {
8239
+ this.warnVia(timeoutMsg);
8240
+ }
8241
+ if (keepWarm) {
8242
+ entry.reject(new Error(`${this.errorPrefix} request "${command}" timed out after ${effectiveTimeoutMs}ms (bridge busy/under load); bridge kept warm — retry`));
8243
+ return;
8244
+ }
8245
+ entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
8246
+ this.handleTimeout(requestSessionId);
8247
+ }, effectiveTimeoutMs);
8248
+ this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
8249
+ if (!this.process?.stdin?.writable) {
8250
+ this.pending.delete(id);
8251
+ clearTimeout(timer);
8252
+ reject(new Error(`${this.errorPrefix} stdin not writable for command "${command}"`));
8253
+ return;
8254
+ }
8255
+ requestSentAt = Date.now();
8256
+ this.process.stdin.write(line, (err) => {
8257
+ if (err) {
8258
+ const entry = this.pending.get(id);
8259
+ if (entry) {
8260
+ this.pending.delete(id);
8261
+ clearTimeout(entry.timer);
8262
+ entry.reject(new Error(`${this.errorPrefix} Failed to write to stdin: ${err.message}`));
8263
+ }
8264
+ }
8265
+ });
8266
+ });
8267
+ if (command === "configure" && response.success === true && options?.markConfiguredOnSuccess !== false) {
8268
+ this.configured = true;
8269
+ }
8270
+ return response;
8271
+ } catch (err) {
8272
+ if (err instanceof BridgeReplacedDuringVersionCheck && canRetryAfterVersionSwap && command !== "configure" && command !== "version") {
8273
+ this.logVia(`Retrying request "${command}" once after coordinated binary replacement: ${err.newBinaryPath}`);
8274
+ return this.sendWithVersionMismatchRetry(command, params, options, false);
8275
+ }
8276
+ throw err;
8277
+ }
8278
+ }
8279
+ async deliverConfigureWarnings(configResult, params, options) {
8280
+ if (!this.onConfigureWarnings)
8281
+ return;
8282
+ const warnings = Array.isArray(configResult.warnings) ? configResult.warnings : [];
8283
+ const configDroppedKeys = coerceConfigureDroppedKeys(configResult.config_dropped_keys);
8284
+ if (warnings.length === 0 && configDroppedKeys.length === 0)
8285
+ return;
8286
+ const sessionId = typeof params.session_id === "string" ? params.session_id : undefined;
8287
+ const context = {
8288
+ projectRoot: this.cwd,
8289
+ sessionId,
8290
+ client: options?.configureWarningClient ?? (sessionId ? this.configureWarningClients.get(sessionId) : undefined),
8291
+ warnings
8292
+ };
8293
+ if (configDroppedKeys.length > 0) {
8294
+ context.configDroppedKeys = configDroppedKeys;
8295
+ }
8296
+ try {
8297
+ await this.onConfigureWarnings(context);
8298
+ } catch (err) {
8299
+ this.warnVia(`configure warning delivery failed: ${err instanceof Error ? err.message : String(err)}`);
8300
+ } finally {
8301
+ if (sessionId) {
8302
+ this.configureWarningClients.delete(sessionId);
8303
+ }
8304
+ }
8305
+ }
8306
+ async handleConfigureWarningsFrame(frame) {
8307
+ if (!this.onConfigureWarnings)
8308
+ return;
8309
+ const warnings = frame.warnings;
8310
+ if (!Array.isArray(warnings) || warnings.length === 0)
8311
+ return;
8312
+ const projectRoot = typeof frame.project_root === "string" ? frame.project_root : this.cwd;
8313
+ const rawSessionId = frame.session_id;
8314
+ const sessionId = typeof rawSessionId === "string" && rawSessionId.length > 0 ? rawSessionId : null;
8315
+ try {
8316
+ await this.onConfigureWarnings({
8317
+ projectRoot,
8318
+ sessionId,
8319
+ client: sessionId ? this.configureWarningClients.get(sessionId) : undefined,
8320
+ warnings
8321
+ });
8322
+ } finally {
8323
+ if (sessionId) {
8324
+ this.configureWarningClients.delete(sessionId);
8325
+ }
8326
+ }
8327
+ }
8328
+ handleStatusChangedFrame(frame) {
8329
+ const snapshot = frame.snapshot;
8330
+ if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot))
8331
+ return;
8332
+ this.cachedStatus = snapshot;
8333
+ for (const listener of this.statusListeners) {
8334
+ this.deliverStatusSnapshot(listener, this.cachedStatus);
8335
+ }
8336
+ }
8337
+ deliverStatusSnapshot(listener, snapshot) {
8338
+ try {
8339
+ listener(snapshot);
8340
+ } catch (err) {
8341
+ this.warnVia(`status listener threw: ${err instanceof Error ? err.message : String(err)}`);
8342
+ }
8343
+ }
8344
+ async shutdown() {
8345
+ this._shuttingDown = true;
8346
+ this.clearRestartResetTimer();
8347
+ this.configureWarningClients.clear();
8348
+ this.rejectAllPending(new Error(`${this.errorPrefix} Bridge shutting down`));
8349
+ if (this.process) {
8350
+ const proc = this.process;
8351
+ this.process = null;
8352
+ return new Promise((resolve) => {
8353
+ const forceKillTimer = setTimeout(() => {
8354
+ proc.kill("SIGKILL");
8355
+ resolve();
8356
+ }, 5000);
8357
+ proc.once("exit", () => {
8358
+ clearTimeout(forceKillTimer);
8359
+ this.logVia("Process exited during shutdown");
8360
+ resolve();
8361
+ });
8362
+ proc.kill("SIGTERM");
8363
+ });
8364
+ }
8365
+ }
8366
+ async checkVersion(options) {
8367
+ if (!this.minVersion)
8368
+ return;
8369
+ try {
8370
+ const resp = await this.send("version", {}, options);
8371
+ if (resp.success === false) {
8372
+ throw new Error(`Binary version check failed: ${String(resp.code ?? "unknown")} — likely too old`);
8373
+ }
8374
+ const binaryVersion = resp.version;
8375
+ if (typeof binaryVersion !== "string") {
8376
+ throw new Error(`Binary did not report a version — likely too old (minVersion: ${this.minVersion})`);
8377
+ }
8378
+ this.logVia(`Binary version: ${binaryVersion}`);
8379
+ if (compareSemver(binaryVersion, this.minVersion) < 0) {
8380
+ this.warnVia(`Binary version ${binaryVersion} is older than required ${this.minVersion}`);
8381
+ const replacementPath = await this.onVersionMismatch?.(binaryVersion, this.minVersion);
8382
+ if (replacementPath === undefined) {
8383
+ return;
8384
+ }
8385
+ if (replacementPath === null || replacementPath.length === 0) {
8386
+ throw new Error(`Binary version ${binaryVersion} is older than required ${this.minVersion}; no compatible replacement binary was provided`);
8387
+ }
8388
+ await this.replaceCurrentBinary(replacementPath);
8389
+ throw new BridgeReplacedDuringVersionCheck(replacementPath);
8390
+ }
8391
+ } catch (err) {
8392
+ this.warnVia(`Version check failed: ${err.message}`);
8393
+ throw err;
8394
+ }
8395
+ }
8396
+ async replaceCurrentBinary(newBinaryPath) {
8397
+ this.binaryPath = newBinaryPath;
8398
+ this.configured = false;
8399
+ this.clearRestartResetTimer();
8400
+ this.rejectAllPending(new Error(`${this.errorPrefix} Bridge restarting with updated binary: ${newBinaryPath}`));
8401
+ if (!this.process)
8402
+ return;
8403
+ const proc = this.process;
8404
+ this.process = null;
8405
+ await new Promise((resolve) => {
8406
+ const forceKillTimer = setTimeout(() => {
8407
+ proc.kill("SIGKILL");
8408
+ resolve();
8409
+ }, 5000);
8410
+ proc.once("exit", () => {
8411
+ clearTimeout(forceKillTimer);
8412
+ this.logVia("Process exited during coordinated binary replacement");
8413
+ resolve();
8414
+ });
8415
+ proc.kill("SIGTERM");
8416
+ });
8417
+ }
8418
+ ensureSpawned(triggeringSessionId) {
8419
+ if (this.isAlive())
8420
+ return;
8421
+ this.spawnProcess(triggeringSessionId);
8422
+ }
8423
+ spawnProcess(triggeringSessionId) {
8424
+ this.lastStatusBar = undefined;
8425
+ if (triggeringSessionId) {
8426
+ this.sessionLogVia(triggeringSessionId, `Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
8427
+ } else {
8428
+ this.logVia(`Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
8429
+ }
8430
+ const semantic = this.configOverrides.semantic;
8431
+ const semanticBackend = (() => {
8432
+ if (semantic && typeof semantic === "object" && !Array.isArray(semantic)) {
8433
+ const candidate = semantic.backend;
8434
+ return typeof candidate === "string" ? candidate : undefined;
8435
+ }
8436
+ return;
8437
+ })();
8438
+ const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
8439
+ const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
8440
+ const ortLibraryPath = ortDir == null ? null : join(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
8441
+ const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
8442
+ const env = {
8443
+ ...process.env,
8444
+ ...envPath ? { PATH: envPath } : {}
8445
+ };
8446
+ this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
8447
+ if (useFastembedBackend) {
8448
+ env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join(this.configOverrides.storage_dir, "semantic", "models") : join(homedir() || "", ".cache", "fastembed"));
8449
+ if (process.env.ORT_DYLIB_PATH) {
8450
+ this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
8451
+ } else if (ortLibraryPath) {
8452
+ env.ORT_DYLIB_PATH = ortLibraryPath;
8453
+ this.logVia(`ORT_DYLIB_PATH set from managed ONNX Runtime: ${ortLibraryPath}`);
8454
+ }
8455
+ }
8456
+ if (this.childEnv) {
8457
+ for (const [key, value] of Object.entries(this.childEnv)) {
8458
+ if (value === undefined) {
8459
+ delete env[key];
8460
+ } else {
8461
+ env[key] = value;
8462
+ }
8463
+ }
8464
+ }
8465
+ const child = spawn(this.binaryPath, [], {
8466
+ cwd: this.cwd,
8467
+ stdio: ["pipe", "pipe", "pipe"],
8468
+ env
8469
+ });
8470
+ const currentChild = child;
8471
+ const stdoutDecoder = new StringDecoder("utf8");
8472
+ child.stdout?.on("data", (chunk) => {
8473
+ this.onStdoutData(stdoutDecoder.write(chunk));
8474
+ });
8475
+ child.stdout?.on("end", () => {
8476
+ const remaining = stdoutDecoder.end();
8477
+ if (remaining)
8478
+ this.onStdoutData(remaining);
8479
+ this.flushStdoutBuffer();
8480
+ });
8481
+ const stderrDecoder = new StringDecoder("utf8");
8482
+ child.stderr?.on("data", (chunk) => {
8483
+ this.onStderrData(stderrDecoder.write(chunk));
8484
+ });
8485
+ child.stderr?.on("end", () => {
8486
+ const remaining = stderrDecoder.end();
8487
+ if (remaining)
8488
+ this.onStderrData(remaining);
8489
+ this.flushStderrBuffer();
8490
+ });
8491
+ child.on("error", (err) => {
8492
+ if (this.process !== currentChild)
8493
+ return;
8494
+ this.errorVia(`Process error: ${err.message}${this.formatStderrTail()}`);
8495
+ this.handleCrash();
8496
+ });
8497
+ child.on("exit", (code, signal) => {
8498
+ if (this.process !== currentChild)
8499
+ return;
8500
+ if (this._shuttingDown)
8501
+ return;
8502
+ this.flushStdoutBuffer();
8503
+ this.logVia(`Process exited: code=${code}, signal=${signal}`);
8504
+ if (signal === "SIGTERM" || signal === "SIGKILL" || signal === "SIGHUP" || signal === "SIGINT") {
8505
+ this.process = null;
8506
+ this.configured = false;
8507
+ this.clearRestartResetTimer();
8508
+ this.rejectAllPending(new Error(`${this.errorPrefix} Binary killed by ${signal}`));
8509
+ return;
8510
+ }
8511
+ this.handleCrash();
8512
+ });
8513
+ this.process = child;
8514
+ this.stdoutBuffer = "";
8515
+ this.stdoutReadOffset = 0;
8516
+ this.stderrBuffer = "";
8517
+ this.lastChildActivityAt = 0;
8518
+ this.consecutiveRequestTimeouts = 0;
8519
+ this.stderrTail = [];
8520
+ }
8521
+ pushStderrLine(line) {
8522
+ this.stderrTail.push(line);
8523
+ if (this.stderrTail.length > BinaryBridge.STDERR_TAIL_MAX) {
8524
+ this.stderrTail.shift();
8525
+ }
8526
+ }
8527
+ onStderrData(data) {
8528
+ this.stderrBuffer += data;
8529
+ let newlineIdx;
8530
+ while ((newlineIdx = this.stderrBuffer.indexOf(`
8531
+ `)) !== -1) {
8532
+ const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
8533
+ this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
8534
+ if (!line || !shouldSurfaceStderrLine(line))
8535
+ continue;
8536
+ const tagged = tagStderrLine(line);
8537
+ this.logVia(tagged);
8538
+ this.pushStderrLine(tagged);
8539
+ }
8540
+ }
8541
+ flushStderrBuffer() {
8542
+ const line = this.stderrBuffer.replace(/\r$/, "");
8543
+ this.stderrBuffer = "";
8544
+ if (!line || !shouldSurfaceStderrLine(line))
8545
+ return;
8546
+ const tagged = tagStderrLine(line);
8547
+ this.logVia(tagged);
8548
+ this.pushStderrLine(tagged);
8549
+ }
8550
+ formatStderrTail() {
8551
+ if (this.stderrTail.length === 0)
8552
+ return "";
8553
+ const tail = this.stderrTail.join(`
8554
+ `);
8555
+ return `
8556
+ --- last ${this.stderrTail.length} stderr lines ---
8557
+ ${tail}`;
8558
+ }
8559
+ onStdoutData(data) {
8560
+ if (this.stdoutReadOffset > STDOUT_BUFFER_COMPACT_THRESHOLD) {
8561
+ this.compactStdoutBuffer();
8562
+ }
8563
+ this.stdoutBuffer += data;
8564
+ if (this.stdoutBuffer.length - this.stdoutReadOffset > MAX_STDOUT_BUFFER) {
8565
+ this.handleCrash(new Error(`aft bridge stdout buffer exceeded ${MAX_STDOUT_BUFFER} bytes — killing bridge`));
8566
+ return;
8567
+ }
8568
+ let newlineIdx;
8569
+ while ((newlineIdx = this.stdoutBuffer.indexOf(`
8570
+ `, this.stdoutReadOffset)) !== -1) {
8571
+ const line = this.stdoutBuffer.slice(this.stdoutReadOffset, newlineIdx).trim();
8572
+ this.stdoutReadOffset = newlineIdx + 1;
8573
+ if (line) {
8574
+ this.processStdoutLine(line);
8575
+ }
8576
+ if (this.stdoutReadOffset > STDOUT_BUFFER_COMPACT_THRESHOLD && this.stdoutReadOffset > this.stdoutBuffer.length / 2) {
8577
+ this.compactStdoutBuffer();
8578
+ }
8579
+ }
8580
+ if (this.stdoutReadOffset === this.stdoutBuffer.length) {
8581
+ this.stdoutBuffer = "";
8582
+ this.stdoutReadOffset = 0;
8583
+ }
8584
+ }
8585
+ compactStdoutBuffer() {
8586
+ if (this.stdoutReadOffset === 0)
8587
+ return;
8588
+ this.stdoutBuffer = this.stdoutBuffer.slice(this.stdoutReadOffset);
8589
+ this.stdoutReadOffset = 0;
8590
+ }
8591
+ flushStdoutBuffer() {
8592
+ const line = this.stdoutBuffer.slice(this.stdoutReadOffset).trim();
8593
+ this.stdoutBuffer = "";
8594
+ this.stdoutReadOffset = 0;
8595
+ if (!line)
8596
+ return;
8597
+ this.processStdoutLine(line);
8598
+ }
8599
+ processStdoutLine(line) {
8600
+ try {
8601
+ const response = JSON.parse(line);
8602
+ this.lastChildActivityAt = Date.now();
8603
+ if (response.type === "progress") {
8604
+ const requestId = response.request_id;
8605
+ const entry = requestId ? this.pending.get(requestId) : undefined;
8606
+ const kind = response.kind === "stderr" ? "stderr" : "stdout";
8607
+ const text = typeof response.chunk === "string" ? response.chunk : "";
8608
+ entry?.onProgress?.({ kind, text });
8609
+ return;
8610
+ }
8611
+ if (response.type === "permission_ask") {
8612
+ const requestId = response.request_id;
8613
+ const entry = requestId ? this.pending.get(requestId) : undefined;
8614
+ if (requestId && entry) {
8615
+ this.pending.delete(requestId);
8616
+ clearTimeout(entry.timer);
8617
+ entry.resolve({
8618
+ success: false,
8619
+ code: "permission_required",
8620
+ message: "bash command requires permission",
8621
+ asks: response.asks
8622
+ });
8623
+ }
8624
+ return;
8625
+ }
8626
+ if (response.type === "bash_completed") {
8627
+ const taskId = bashTaskIdFrom(response);
8628
+ if (taskId)
8629
+ this.outstandingBackgroundTaskIds.delete(taskId);
8630
+ this.onBashCompletion?.(response, this);
8631
+ return;
8632
+ }
8633
+ if (response.type === "bash_long_running") {
8634
+ this.onBashLongRunning?.(response, this);
8635
+ return;
8636
+ }
8637
+ if (response.type === "bash_pattern_match") {
8638
+ this.onBashPatternMatch?.(response, this);
8639
+ return;
8640
+ }
8641
+ if (response.type === "configure_warnings") {
8642
+ this.handleConfigureWarningsFrame(response).catch((err) => {
8643
+ this.warnVia(`configure warning delivery failed: ${err instanceof Error ? err.message : String(err)}`);
8644
+ });
8645
+ return;
8646
+ }
8647
+ if (response.type === "status_changed") {
8648
+ this.handleStatusChangedFrame(response);
8649
+ return;
8650
+ }
8651
+ const id = response.id;
8652
+ if (id && this.pending.has(id)) {
8653
+ const entry = this.pending.get(id);
8654
+ if (!entry)
8655
+ return;
8656
+ this.pending.delete(id);
8657
+ clearTimeout(entry.timer);
8658
+ this.consecutiveRequestTimeouts = 0;
8659
+ this.scheduleRestartCountReset();
8660
+ this.accountForBashTaskResponse(entry.command, response);
8661
+ this.captureStatusBar(response);
8662
+ entry.resolve(response);
8663
+ } else if (typeof response.type === "string") {
8664
+ this.logVia(`Ignoring unknown stdout push frame type: ${response.type}`);
8665
+ }
8666
+ } catch (_err) {
8667
+ this.warnVia(`Failed to parse stdout line: ${line}`);
8668
+ }
8669
+ }
8670
+ accountForBashTaskResponse(command, response) {
8671
+ const taskId = bashTaskIdFrom(response);
8672
+ if (!taskId)
8673
+ return;
8674
+ if (isTerminalBashStatus(response.status)) {
8675
+ this.outstandingBackgroundTaskIds.delete(taskId);
8676
+ return;
8677
+ }
8678
+ if (command === "bash" && response.success !== false) {
8679
+ this.outstandingBackgroundTaskIds.add(taskId);
8680
+ }
8681
+ }
8682
+ captureStatusBar(response) {
8683
+ const parsed = parseStatusBarCounts(response.status_bar);
8684
+ if (parsed)
8685
+ this.lastStatusBar = parsed;
8686
+ }
8687
+ getStatusBar() {
8688
+ return this.lastStatusBar;
8689
+ }
8690
+ handleTimeout(triggeringSessionId) {
8691
+ this.consecutiveRequestTimeouts = 0;
8692
+ this.rejectAllPending(new Error(`${this.errorPrefix} bridge killed during sibling timeout — request aborted`));
8693
+ this.outstandingBackgroundTaskIds.clear();
8694
+ if (this.process) {
8695
+ this.process.kill("SIGKILL");
8696
+ this.process = null;
8697
+ }
8698
+ this.clearRestartResetTimer();
8699
+ this.configured = false;
8700
+ const tail = this.formatStderrTail();
8701
+ this.stderrTail = [];
8702
+ const killedMsg = tail ? `Bridge killed after timeout.${tail}` : `Bridge killed after timeout (see ${this.getLogFilePathVia()})`;
8703
+ if (tail) {
8704
+ if (triggeringSessionId) {
8705
+ this.sessionErrorVia(triggeringSessionId, killedMsg);
8706
+ } else {
8707
+ this.errorVia(killedMsg);
8708
+ }
8709
+ } else if (triggeringSessionId) {
8710
+ this.sessionWarnVia(triggeringSessionId, killedMsg);
8711
+ } else {
8712
+ this.warnVia(killedMsg);
8713
+ }
8714
+ }
8715
+ handleCrash(cause) {
8716
+ const proc = this.process;
8717
+ this.process = null;
8718
+ if (proc && proc.exitCode === null && !proc.killed) {
8719
+ proc.kill("SIGKILL");
8720
+ }
8721
+ this.clearRestartResetTimer();
8722
+ this.configured = false;
8723
+ this.outstandingBackgroundTaskIds.clear();
8724
+ const tail = this.formatStderrTail();
8725
+ if (tail) {
8726
+ this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
8727
+ }
8728
+ this.rejectAllPending(new Error(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`));
8729
+ if (this._restartCount < this.maxRestarts) {
8730
+ const delay = 100 * 2 ** this._restartCount;
8731
+ this._restartCount++;
8732
+ this.logVia(`Auto-restart #${this._restartCount} in ${delay}ms`);
8733
+ setTimeout(() => {
8734
+ if (!this._shuttingDown && !this.isAlive()) {
8735
+ try {
8736
+ this.spawnProcess();
8737
+ } catch (err) {
8738
+ this.errorVia(`Failed to restart: ${err.message}`);
8739
+ }
8740
+ }
8741
+ }, delay);
8742
+ this.scheduleRestartCountReset();
8743
+ } else {
8744
+ this.errorVia(`Max restarts (${this.maxRestarts}) reached, giving up. Logs: ${this.getLogFilePathVia()}${tail}`);
8745
+ this.scheduleRestartCountReset();
8746
+ }
8747
+ }
8748
+ rejectAllPending(error2) {
8749
+ for (const [_id, entry] of this.pending) {
8750
+ clearTimeout(entry.timer);
8751
+ entry.reject(error2);
8752
+ }
8753
+ this.pending.clear();
8754
+ }
8755
+ scheduleRestartCountReset() {
8756
+ this.clearRestartResetTimer();
8757
+ this.restartResetTimer = setTimeout(() => {
8758
+ this._restartCount = 0;
8759
+ this.restartResetTimer = null;
8760
+ }, BinaryBridge.RESTART_RESET_MS);
8761
+ }
8762
+ clearRestartResetTimer() {
8763
+ if (this.restartResetTimer) {
8764
+ clearTimeout(this.restartResetTimer);
8765
+ this.restartResetTimer = null;
8766
+ }
8767
+ }
8768
+ }
8769
+ // ../aft-bridge/dist/downloader.js
8770
+ var MAX_DOWNLOAD_BYTES = 200 * 1024 * 1024;
8771
+ var DOWNLOAD_LOCK_STALE_MS = 10 * 60000;
8772
+ // ../aft-bridge/dist/migration.js
8773
+ var DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
8774
+ // ../aft-bridge/dist/onnx-runtime.js
8775
+ var ORT_VERSION = "1.24.4";
8776
+ var MAX_DOWNLOAD_BYTES2 = 256 * 1024 * 1024;
8777
+ var MAX_EXTRACT_BYTES = 1 * 1024 * 1024 * 1024;
8778
+ var STALE_LOCK_MS = 5 * 60 * 1000;
8779
+ var ORT_PLATFORM_MAP = {
8780
+ darwin: {
8781
+ arm64: {
8782
+ assetName: `onnxruntime-osx-arm64-${ORT_VERSION}`,
8783
+ libName: "libonnxruntime.dylib",
8784
+ archiveType: "tgz"
8785
+ }
8786
+ },
8787
+ linux: {
8788
+ x64: {
8789
+ assetName: `onnxruntime-linux-x64-${ORT_VERSION}`,
8790
+ libName: "libonnxruntime.so",
8791
+ archiveType: "tgz"
8792
+ },
8793
+ arm64: {
8794
+ assetName: `onnxruntime-linux-aarch64-${ORT_VERSION}`,
8795
+ libName: "libonnxruntime.so",
8796
+ archiveType: "tgz"
8797
+ }
8798
+ },
8799
+ win32: {
8800
+ x64: {
8801
+ assetName: `onnxruntime-win-x64-${ORT_VERSION}`,
8802
+ libName: "onnxruntime.dll",
8803
+ archiveType: "zip"
8804
+ },
8805
+ arm64: {
8806
+ assetName: `onnxruntime-win-arm64-${ORT_VERSION}`,
8807
+ libName: "onnxruntime.dll",
8808
+ archiveType: "zip"
8809
+ }
8810
+ }
8811
+ };
8812
+ // ../aft-bridge/dist/project-identity.js
8813
+ import { createHash } from "node:crypto";
8814
+ import { realpathSync } from "node:fs";
8815
+ import { resolve } from "node:path";
8816
+ function canonicalizeProjectRoot(dir) {
8817
+ const trimmed = dir.replace(/[/\\]+$/, "");
8818
+ let canonical;
8819
+ try {
8820
+ canonical = realpathSync(trimmed);
8821
+ } catch {
8822
+ canonical = resolve(trimmed);
8823
+ }
8824
+ return normalizeWindowsRoot(canonical);
8825
+ }
8826
+ function normalizeWindowsRoot(p) {
8827
+ if (process.platform !== "win32")
8828
+ return p;
8829
+ let s = p;
8830
+ if (s.startsWith("\\\\?\\UNC\\")) {
8831
+ s = `\\\\${s.slice("\\\\?\\UNC\\".length)}`;
8832
+ } else if (s.startsWith("\\\\?\\")) {
8833
+ s = s.slice("\\\\?\\".length);
8834
+ }
8835
+ if (s.length >= 2 && s[1] === ":") {
8836
+ const drive = s.charCodeAt(0);
8837
+ if (drive >= 97 && drive <= 122) {
8838
+ s = s[0].toUpperCase() + s.slice(1);
8839
+ }
8840
+ }
8841
+ return s;
8842
+ }
8843
+ function projectRootKeyHash(dir) {
8844
+ return createHash("sha256").update(canonicalizeProjectRoot(dir)).digest("hex").slice(0, 16);
8845
+ }
8846
+
8847
+ // ../aft-bridge/dist/pool.js
8848
+ var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
8849
+ var DEFAULT_MAX_POOL_SIZE = 8;
8850
+ var CLEANUP_INTERVAL_MS = 60 * 1000;
8851
+ class BridgePool {
8852
+ bridges = new Map;
8853
+ staleBridges = new Set;
8854
+ binaryPath;
8855
+ maxPoolSize;
8856
+ idleTimeoutMs;
8857
+ bridgeOptions;
8858
+ configOverrides;
8859
+ projectConfigLoader;
8860
+ logger;
8861
+ cleanupTimer = null;
8862
+ constructor(binaryPath, options = {}, configOverrides = {}) {
8863
+ this.binaryPath = binaryPath;
8864
+ this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
8865
+ this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
8866
+ this.logger = options.logger;
8867
+ this.projectConfigLoader = options.projectConfigLoader;
8868
+ this.bridgeOptions = {
8869
+ timeoutMs: options.timeoutMs,
8870
+ hangThreshold: options.hangThreshold,
8871
+ maxRestarts: options.maxRestarts,
8872
+ minVersion: options.minVersion,
8873
+ onVersionMismatch: options.onVersionMismatch,
8874
+ onConfigureWarnings: options.onConfigureWarnings,
8875
+ onBashCompletion: options.onBashCompletion,
8876
+ onBashLongRunning: options.onBashLongRunning,
8877
+ onBashPatternMatch: options.onBashPatternMatch,
8878
+ errorPrefix: options.errorPrefix,
8879
+ logger: options.logger,
8880
+ childEnv: options.childEnv
8881
+ };
8882
+ this.configOverrides = configOverrides;
8883
+ if (Number.isFinite(this.idleTimeoutMs)) {
8884
+ this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
8885
+ this.cleanupTimer.unref();
8886
+ }
8887
+ }
8888
+ getActiveBridgeForRoot(projectRoot) {
8889
+ const key = normalizeKey(projectRoot);
8890
+ const entry = this.bridges.get(key);
8891
+ if (!entry?.bridge.isAlive())
8892
+ return null;
8893
+ entry.lastUsed = Date.now();
8894
+ return entry.bridge;
8895
+ }
8896
+ getBridge(projectRoot) {
8897
+ const key = normalizeKey(projectRoot);
8898
+ const existing = this.bridges.get(key);
8899
+ if (existing) {
8900
+ existing.lastUsed = Date.now();
8901
+ return existing.bridge;
8902
+ }
8903
+ if (this.bridges.size >= this.maxPoolSize) {
8904
+ this.evictLRU();
8905
+ }
8906
+ let projectOverrides = {};
8907
+ if (this.projectConfigLoader) {
8908
+ try {
8909
+ projectOverrides = this.projectConfigLoader(key) ?? {};
8910
+ } catch (err) {
8911
+ const message = err instanceof Error ? err.message : String(err);
8912
+ this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
8913
+ }
8914
+ }
8915
+ const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
8916
+ const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
8917
+ this.bridges.set(key, { bridge, lastUsed: Date.now() });
8918
+ return bridge;
8919
+ }
8920
+ cleanup() {
8921
+ const now = Date.now();
8922
+ for (const [dir, entry] of this.bridges) {
8923
+ if (entry.bridge.hasPendingRequests() || entry.bridge.hasOutstandingBackgroundTasks())
8924
+ continue;
8925
+ if (now - entry.lastUsed > this.idleTimeoutMs) {
8926
+ entry.bridge.shutdown().catch((err) => this.error("cleanup shutdown failed:", err));
8927
+ this.bridges.delete(dir);
8928
+ }
8929
+ }
8930
+ for (const bridge of this.staleBridges) {
8931
+ if (bridge.hasPendingRequests() || bridge.hasOutstandingBackgroundTasks())
8932
+ continue;
8933
+ bridge.shutdown().catch((err) => this.error("stale cleanup shutdown failed:", err));
8934
+ this.staleBridges.delete(bridge);
8935
+ }
8936
+ }
8937
+ evictLRU() {
8938
+ let oldestDir = null;
8939
+ let oldestTime = Infinity;
8940
+ for (const [dir, entry] of this.bridges) {
8941
+ if (entry.bridge.hasPendingRequests() || entry.bridge.hasOutstandingBackgroundTasks())
8942
+ continue;
8943
+ if (entry.lastUsed < oldestTime) {
8944
+ oldestTime = entry.lastUsed;
8945
+ oldestDir = dir;
8946
+ }
8947
+ }
8948
+ if (oldestDir) {
8949
+ const entry = this.bridges.get(oldestDir);
8950
+ entry?.bridge.shutdown().catch((err) => this.error("eviction shutdown failed:", err));
8951
+ this.bridges.delete(oldestDir);
8952
+ }
8953
+ }
8954
+ async shutdown() {
8955
+ if (this.cleanupTimer) {
8956
+ clearInterval(this.cleanupTimer);
8957
+ this.cleanupTimer = null;
8958
+ }
8959
+ const shutdowns = [
8960
+ ...Array.from(this.bridges.values(), (e) => e.bridge.shutdown()),
8961
+ ...Array.from(this.staleBridges.values(), (bridge) => bridge.shutdown())
8962
+ ];
8963
+ this.bridges.clear();
8964
+ this.staleBridges.clear();
8965
+ await Promise.allSettled(shutdowns);
8966
+ }
8967
+ async replaceBinary(newPath) {
8968
+ this.binaryPath = newPath;
8969
+ for (const entry of this.bridges.values()) {
8970
+ this.staleBridges.add(entry.bridge);
8971
+ }
8972
+ this.bridges.clear();
8973
+ this.log(`Binary path updated to ${newPath}. Active bridges marked stale — next calls will use the new binary.`);
8974
+ return newPath;
8975
+ }
8976
+ log(message, meta) {
8977
+ const logger = this.logger ?? getActiveLogger();
8978
+ if (logger) {
8979
+ try {
8980
+ logger.log(message, meta);
8981
+ } catch (err) {
8982
+ console.error(`[aft-bridge] ERROR: pool logger log threw: ${err instanceof Error ? err.message : String(err)}`);
8983
+ console.error(`[aft-bridge] ${message}`);
8984
+ }
8985
+ } else
8986
+ log(message, meta);
8987
+ }
8988
+ error(message, meta) {
8989
+ const logger = this.logger ?? getActiveLogger();
8990
+ if (logger) {
8991
+ try {
8992
+ logger.error(message, meta);
8993
+ } catch (err) {
8994
+ console.error(`[aft-bridge] ERROR: pool logger error threw: ${err instanceof Error ? err.message : String(err)}`);
8995
+ console.error(`[aft-bridge] ERROR: ${message}`);
8996
+ }
8997
+ } else
8998
+ error(message, meta);
8999
+ }
9000
+ setConfigureOverride(key, value) {
9001
+ if (value === undefined) {
9002
+ delete this.configOverrides[key];
9003
+ } else {
9004
+ this.configOverrides[key] = value;
9005
+ }
9006
+ }
9007
+ get size() {
9008
+ return this.bridges.size;
9009
+ }
9010
+ _testGetConfigOverrides() {
9011
+ return { ...this.configOverrides };
9012
+ }
9013
+ _testGetBridgeOptions() {
9014
+ return { ...this.bridgeOptions };
9015
+ }
9016
+ }
9017
+ function normalizeKey(projectRoot) {
9018
+ return canonicalizeProjectRoot(projectRoot);
9019
+ }
9020
+ // src/shared/rpc-utils.ts
7802
9021
  function projectHash(directory) {
7803
- const normalized = directory.replace(/\/+$/, "");
7804
- return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
9022
+ return projectRootKeyHash(directory);
7805
9023
  }
7806
9024
  function rpcPortFilePath(storageDir, directory) {
7807
9025
  const hash = projectHash(directory);
7808
- return join(storageDir, "rpc", hash, "port");
9026
+ return join2(storageDir, "rpc", hash, "port");
7809
9027
  }
7810
9028
  function rpcPortFileDir(storageDir, directory) {
7811
9029
  const hash = projectHash(directory);
7812
- return join(storageDir, "rpc", hash, "ports");
9030
+ return join2(storageDir, "rpc", hash, "ports");
7813
9031
  }
7814
9032
  function isPidAlive(pid) {
7815
9033
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
@@ -7863,7 +9081,7 @@ function throwIfAborted(signal) {
7863
9081
  }
7864
9082
  function delay(ms, signal) {
7865
9083
  throwIfAborted(signal);
7866
- return new Promise((resolve, reject) => {
9084
+ return new Promise((resolve2, reject) => {
7867
9085
  let timer;
7868
9086
  const onAbort = () => {
7869
9087
  clearTimeout(timer);
@@ -7871,7 +9089,7 @@ function delay(ms, signal) {
7871
9089
  };
7872
9090
  timer = setTimeout(() => {
7873
9091
  signal?.removeEventListener("abort", onAbort);
7874
- resolve();
9092
+ resolve2();
7875
9093
  }, ms);
7876
9094
  signal?.addEventListener("abort", onAbort, { once: true });
7877
9095
  });
@@ -7984,7 +9202,7 @@ class AftRpcClient {
7984
9202
  for (const entry of readdirSync(this.portsDir)) {
7985
9203
  if (!entry.endsWith(".json"))
7986
9204
  continue;
7987
- const filePath = join2(this.portsDir, entry);
9205
+ const filePath = join3(this.portsDir, entry);
7988
9206
  const info = this.parsePortFile(filePath);
7989
9207
  if (!info)
7990
9208
  continue;
@@ -8233,39 +9451,39 @@ function coerceAftStatus(response) {
8233
9451
  import { createEffect, createMemo, createSignal, on, onCleanup } from "solid-js";
8234
9452
 
8235
9453
  // src/shared/storage-paths.ts
8236
- import { homedir } from "node:os";
8237
- import { join as join3 } from "node:path";
9454
+ import { homedir as homedir2 } from "node:os";
9455
+ import { join as join4 } from "node:path";
8238
9456
  function homeDir() {
8239
9457
  if (process.platform === "win32")
8240
- return process.env.USERPROFILE || process.env.HOME || homedir();
8241
- return process.env.HOME || homedir();
9458
+ return process.env.USERPROFILE || process.env.HOME || homedir2();
9459
+ return process.env.HOME || homedir2();
8242
9460
  }
8243
9461
  function dataHome() {
8244
9462
  if (process.env.XDG_DATA_HOME)
8245
9463
  return process.env.XDG_DATA_HOME;
8246
9464
  if (process.platform === "win32") {
8247
- return process.env.LOCALAPPDATA || process.env.APPDATA || join3(homeDir(), "AppData", "Local");
9465
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join4(homeDir(), "AppData", "Local");
8248
9466
  }
8249
- return join3(homeDir(), ".local", "share");
9467
+ return join4(homeDir(), ".local", "share");
8250
9468
  }
8251
- function resolveCortexKitStorageRoot() {
8252
- return join3(dataHome(), "cortexkit", "aft");
9469
+ function resolveCortexKitStorageRoot2() {
9470
+ return join4(dataHome(), "cortexkit", "aft");
8253
9471
  }
8254
9472
 
8255
9473
  // src/tui/preferences.ts
8256
9474
  var import_comment_json = __toESM(require_src2(), 1);
8257
9475
  import { watch } from "node:fs";
8258
9476
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
8259
- import { homedir as homedir2 } from "node:os";
8260
- import { basename, dirname, join as join4 } from "node:path";
9477
+ import { homedir as homedir3 } from "node:os";
9478
+ import { basename, dirname, join as join5 } from "node:path";
8261
9479
  var TUI_PREFS_FILE_ENV = "OPENCODE_TUI_PREFERENCES_FILE";
8262
9480
  var FILE_NAME = "tui-preferences.jsonc";
8263
9481
  function getTuiPreferencesFile() {
8264
9482
  const override = process.env[TUI_PREFS_FILE_ENV];
8265
9483
  if (override)
8266
9484
  return override;
8267
- const configDir = process.env.OPENCODE_CONFIG_DIR || join4(process.env.XDG_CONFIG_HOME || join4(homedir2(), ".config"), "opencode");
8268
- return join4(configDir, FILE_NAME);
9485
+ const configDir = process.env.OPENCODE_CONFIG_DIR || join5(process.env.XDG_CONFIG_HOME || join5(homedir3(), ".config"), "opencode");
9486
+ return join5(configDir, FILE_NAME);
8269
9487
  }
8270
9488
  function isRecord(value) {
8271
9489
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -8606,7 +9824,7 @@ function collapsedHealthLights(statusBar) {
8606
9824
  return { diagnostics, code, todos };
8607
9825
  }
8608
9826
  function resolveTuiStorageDir() {
8609
- return resolveCortexKitStorageRoot();
9827
+ return resolveCortexKitStorageRoot2();
8610
9828
  }
8611
9829
  var sidebarClients = new Map;
8612
9830
  function getClient(directory) {
@@ -8628,16 +9846,16 @@ function shouldSuppressUninitializedDowngrade(incomingCacheRole, haveInitialized
8628
9846
  return incomingCacheRole === "not_initialized" && haveInitializedForContext;
8629
9847
  }
8630
9848
  function isSnapshotForContext(snapshot, directory, servedDirectory) {
8631
- const stripSlash = (p) => p.replace(/\/+$/, "");
9849
+ const canon = (p) => canonicalizeProjectRoot(p);
8632
9850
  const roots = [snapshot.project_root, snapshot.canonical_root].filter((r) => typeof r === "string" && r.length > 0);
8633
9851
  if (roots.length === 0)
8634
9852
  return true;
8635
- const dir = stripSlash(directory);
8636
- if (roots.some((r) => stripSlash(r) === dir))
9853
+ const dir = canon(directory);
9854
+ if (roots.some((r) => canon(r) === dir))
8637
9855
  return true;
8638
9856
  if (typeof servedDirectory === "string" && servedDirectory.length > 0) {
8639
- const served = stripSlash(servedDirectory);
8640
- return roots.some((r) => stripSlash(r) === served);
9857
+ const served = canon(servedDirectory);
9858
+ return roots.some((r) => canon(r) === served);
8641
9859
  }
8642
9860
  return false;
8643
9861
  }
@@ -9123,7 +10341,6 @@ async function createAftSidebarSlot(api, pluginVersion) {
9123
10341
 
9124
10342
  // src/tui/index.tsx
9125
10343
  import { jsxDEV as jsxDEV2 } from "@opentui/solid/jsx-dev-runtime";
9126
- var STATUS_COMMAND = "aft-status";
9127
10344
  var rpcClients = new Map;
9128
10345
  function getRpcClient(directory) {
9129
10346
  let client = rpcClients.get(directory);
@@ -9142,6 +10359,29 @@ function getSessionId(api) {
9142
10359
  } catch {}
9143
10360
  return null;
9144
10361
  }
10362
+ var lastReceivedNotificationIdBySession = new Map;
10363
+ async function consumeTuiMessages(client, sessionId) {
10364
+ try {
10365
+ const result = await client.call("consume-notifications", {
10366
+ lastReceivedId: lastReceivedNotificationIdBySession.get(sessionId) ?? 0,
10367
+ sessionId
10368
+ });
10369
+ return (result.messages ?? []).map((message) => ({
10370
+ id: message.id,
10371
+ type: message.type,
10372
+ payload: message.payload,
10373
+ sessionId: message.sessionId
10374
+ }));
10375
+ } catch {
10376
+ return [];
10377
+ }
10378
+ }
10379
+ function markTuiMessagesReceived(sessionId, messages) {
10380
+ const previous = lastReceivedNotificationIdBySession.get(sessionId) ?? 0;
10381
+ const next = messages.reduce((max, message) => Math.max(max, message.id), previous);
10382
+ if (next > previous)
10383
+ lastReceivedNotificationIdBySession.set(sessionId, next);
10384
+ }
9145
10385
  var POLL_INTERVAL_MS2 = 1500;
9146
10386
  function formatCountShort(value) {
9147
10387
  if (value == null || !Number.isFinite(value))
@@ -9214,7 +10454,7 @@ var StatusDialog = (props) => {
9214
10454
  const theme = createMemo2(() => props.api.theme.current);
9215
10455
  const t = () => theme();
9216
10456
  const [status, setStatus] = createSignal2(props.initial);
9217
- const [error, setError] = createSignal2(props.initialError);
10457
+ const [error2, setError] = createSignal2(props.initialError);
9218
10458
  let pollGeneration = 0;
9219
10459
  let pollController = null;
9220
10460
  const pollStatus = async () => {
@@ -9287,12 +10527,12 @@ var StatusDialog = (props) => {
9287
10527
  }, undefined, true, undefined, this)
9288
10528
  ]
9289
10529
  }, undefined, true, undefined, this),
9290
- error() ? /* @__PURE__ */ jsxDEV2("box", {
10530
+ error2() ? /* @__PURE__ */ jsxDEV2("box", {
9291
10531
  width: "100%",
9292
10532
  marginBottom: 1,
9293
10533
  children: /* @__PURE__ */ jsxDEV2("text", {
9294
10534
  fg: t().warning,
9295
- children: error()
10535
+ children: error2()
9296
10536
  }, undefined, false, undefined, this)
9297
10537
  }, undefined, false, undefined, this) : null,
9298
10538
  status()?.cache_role === "not_initialized" ? /* @__PURE__ */ jsxDEV2("box", {
@@ -9650,24 +10890,15 @@ async function showStatusDialog(api) {
9650
10890
  } catch {
9651
10891
  initialError = "AFT is starting up. Status will refresh automatically...";
9652
10892
  }
9653
- const dismissStatusDialog = () => {
9654
- api.ui.dialog.setSize("medium");
9655
- api.ui.dialog.clear();
9656
- };
10893
+ api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(StatusDialog, {
10894
+ api,
10895
+ client,
10896
+ directory,
10897
+ sessionID,
10898
+ initial,
10899
+ initialError
10900
+ }, undefined, false, undefined, this));
9657
10901
  api.ui.dialog.setSize("large");
9658
- api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(api.ui.Dialog, {
9659
- size: "large",
9660
- onClose: dismissStatusDialog,
9661
- children: /* @__PURE__ */ jsxDEV2(StatusDialog, {
9662
- api,
9663
- client,
9664
- directory,
9665
- sessionID,
9666
- initial,
9667
- initialError,
9668
- onClose: dismissStatusDialog
9669
- }, undefined, false, undefined, this)
9670
- }, undefined, false, undefined, this), dismissStatusDialog);
9671
10902
  }
9672
10903
  function registerStatusCommand(api) {
9673
10904
  const apiAny = api;
@@ -9679,7 +10910,6 @@ function registerStatusCommand(api) {
9679
10910
  name: "aft.status",
9680
10911
  title: "AFT: Status",
9681
10912
  category: "AFT",
9682
- slashName: STATUS_COMMAND,
9683
10913
  run() {
9684
10914
  showStatusDialog(api);
9685
10915
  }
@@ -9695,7 +10925,6 @@ function registerStatusCommand(api) {
9695
10925
  title: "AFT: Status",
9696
10926
  value: "aft.status",
9697
10927
  category: "AFT",
9698
- slash: { name: STATUS_COMMAND },
9699
10928
  onSelect() {
9700
10929
  showStatusDialog(api);
9701
10930
  }
@@ -9753,6 +10982,47 @@ var tui = async (api) => {
9753
10982
  api.slots.register(await createAftSidebarSlot(api, version));
9754
10983
  } catch {}
9755
10984
  registerStatusCommand(api);
10985
+ let pollInFlight = false;
10986
+ const messagePoller = setInterval(() => {
10987
+ if (pollInFlight)
10988
+ return;
10989
+ const requestedSessionId = getSessionId(api);
10990
+ if (!requestedSessionId)
10991
+ return;
10992
+ const directory = api.state.path.directory ?? "";
10993
+ if (!directory)
10994
+ return;
10995
+ pollInFlight = true;
10996
+ const client = getRpcClient(directory);
10997
+ consumeTuiMessages(client, requestedSessionId).then(async (messages) => {
10998
+ if (getSessionId(api) !== requestedSessionId)
10999
+ return;
11000
+ const orderedMessages = [...messages].sort((a, b) => a.id - b.id);
11001
+ for (const message of orderedMessages) {
11002
+ if (getSessionId(api) !== requestedSessionId)
11003
+ return;
11004
+ if (message.sessionId && message.sessionId !== requestedSessionId)
11005
+ continue;
11006
+ if (message.type !== "action")
11007
+ continue;
11008
+ if (message.payload?.action !== "show-status-dialog")
11009
+ continue;
11010
+ await showStatusDialog(api);
11011
+ }
11012
+ if (getSessionId(api) !== requestedSessionId)
11013
+ return;
11014
+ markTuiMessagesReceived(requestedSessionId, orderedMessages);
11015
+ }).catch(() => {}).finally(() => {
11016
+ pollInFlight = false;
11017
+ });
11018
+ }, 500);
11019
+ api.lifecycle?.onDispose?.(() => {
11020
+ clearInterval(messagePoller);
11021
+ lastReceivedNotificationIdBySession.clear();
11022
+ for (const client of rpcClients.values())
11023
+ client.reset();
11024
+ rpcClients.clear();
11025
+ });
9756
11026
  showStartupNotifications(api);
9757
11027
  };
9758
11028
  var id = "aft-opencode";