evil-omo 3.15.2 → 3.15.3

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/cli/index.js CHANGED
@@ -4917,6 +4917,196 @@ var init_command_executor = __esm(() => {
4917
4917
  // src/shared/contains-path.ts
4918
4918
  var init_contains_path = () => {};
4919
4919
 
4920
+ // src/shared/logger.ts
4921
+ import * as fs from "fs";
4922
+ import * as os from "os";
4923
+ import * as path from "path";
4924
+ function flush() {
4925
+ if (buffer.length === 0)
4926
+ return;
4927
+ const data = buffer.join("");
4928
+ buffer = [];
4929
+ try {
4930
+ fs.appendFileSync(logFile, data);
4931
+ } catch {}
4932
+ }
4933
+ function scheduleFlush() {
4934
+ if (flushTimer)
4935
+ return;
4936
+ flushTimer = setTimeout(() => {
4937
+ flushTimer = null;
4938
+ flush();
4939
+ }, FLUSH_INTERVAL_MS);
4940
+ }
4941
+ function log(message, data) {
4942
+ try {
4943
+ const timestamp2 = new Date().toISOString();
4944
+ const logEntry = `[${timestamp2}] ${message} ${data ? JSON.stringify(data) : ""}
4945
+ `;
4946
+ buffer.push(logEntry);
4947
+ if (buffer.length >= BUFFER_SIZE_LIMIT) {
4948
+ flush();
4949
+ } else {
4950
+ scheduleFlush();
4951
+ }
4952
+ } catch {}
4953
+ }
4954
+ var logFile, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50;
4955
+ var init_logger = __esm(() => {
4956
+ logFile = path.join(os.tmpdir(), "evil-omo.log");
4957
+ buffer = [];
4958
+ });
4959
+
4960
+ // src/shared/file-reference-resolver.ts
4961
+ var init_file_reference_resolver = __esm(() => {
4962
+ init_contains_path();
4963
+ init_logger();
4964
+ });
4965
+ // src/shared/deep-merge.ts
4966
+ function isPlainObject(value) {
4967
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
4968
+ }
4969
+ function deepMerge(base, override, depth = 0) {
4970
+ if (!base && !override)
4971
+ return;
4972
+ if (!base)
4973
+ return override;
4974
+ if (!override)
4975
+ return base;
4976
+ if (depth > MAX_DEPTH)
4977
+ return override ?? base;
4978
+ const result = { ...base };
4979
+ for (const key of Object.keys(override)) {
4980
+ if (DANGEROUS_KEYS.has(key))
4981
+ continue;
4982
+ const baseValue = base[key];
4983
+ const overrideValue = override[key];
4984
+ if (overrideValue === undefined)
4985
+ continue;
4986
+ if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
4987
+ result[key] = deepMerge(baseValue, overrideValue, depth + 1);
4988
+ } else {
4989
+ result[key] = overrideValue;
4990
+ }
4991
+ }
4992
+ return result;
4993
+ }
4994
+ var DANGEROUS_KEYS, MAX_DEPTH = 50;
4995
+ var init_deep_merge = __esm(() => {
4996
+ DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
4997
+ });
4998
+
4999
+ // src/shared/snake-case.ts
5000
+ var init_snake_case = __esm(() => {
5001
+ init_deep_merge();
5002
+ });
5003
+
5004
+ // src/shared/tool-name.ts
5005
+ var init_tool_name = () => {};
5006
+
5007
+ // src/shared/pattern-matcher.ts
5008
+ var regexCache;
5009
+ var init_pattern_matcher = __esm(() => {
5010
+ regexCache = new Map;
5011
+ });
5012
+ // src/shared/file-utils.ts
5013
+ import { lstatSync, realpathSync } from "fs";
5014
+ function normalizeDarwinRealpath(filePath) {
5015
+ return filePath.startsWith("/private/var/") ? filePath.slice("/private".length) : filePath;
5016
+ }
5017
+ function resolveSymlink(filePath) {
5018
+ try {
5019
+ return normalizeDarwinRealpath(realpathSync(filePath));
5020
+ } catch {
5021
+ return filePath;
5022
+ }
5023
+ }
5024
+ var init_file_utils = () => {};
5025
+
5026
+ // src/shared/context-limit-resolver.ts
5027
+ var init_context_limit_resolver = () => {};
5028
+
5029
+ // src/shared/normalize-sdk-response.ts
5030
+ function normalizeSDKResponse(response, fallback, options) {
5031
+ if (response === null || response === undefined) {
5032
+ return fallback;
5033
+ }
5034
+ if (Array.isArray(response)) {
5035
+ return response;
5036
+ }
5037
+ if (typeof response === "object" && "data" in response) {
5038
+ const data = response.data;
5039
+ if (data !== null && data !== undefined) {
5040
+ return data;
5041
+ }
5042
+ if (options?.preferResponseOnMissingData === true) {
5043
+ return response;
5044
+ }
5045
+ return fallback;
5046
+ }
5047
+ if (options?.preferResponseOnMissingData === true) {
5048
+ return response;
5049
+ }
5050
+ return fallback;
5051
+ }
5052
+
5053
+ // src/shared/dynamic-truncator.ts
5054
+ var init_dynamic_truncator = __esm(() => {
5055
+ init_context_limit_resolver();
5056
+ });
5057
+
5058
+ // src/shared/data-path.ts
5059
+ import * as path2 from "path";
5060
+ import * as os2 from "os";
5061
+ import { accessSync, constants, mkdirSync } from "fs";
5062
+ function resolveWritableDirectory(preferredDir, fallbackSuffix) {
5063
+ try {
5064
+ mkdirSync(preferredDir, { recursive: true });
5065
+ accessSync(preferredDir, constants.W_OK);
5066
+ return preferredDir;
5067
+ } catch {
5068
+ const fallbackDir = path2.join(os2.tmpdir(), fallbackSuffix);
5069
+ mkdirSync(fallbackDir, { recursive: true });
5070
+ return fallbackDir;
5071
+ }
5072
+ }
5073
+ function getDataDir() {
5074
+ const preferredDir = process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
5075
+ return resolveWritableDirectory(preferredDir, "opencode-data");
5076
+ }
5077
+ function getOpenCodeStorageDir() {
5078
+ return path2.join(getDataDir(), "opencode", "storage");
5079
+ }
5080
+ function getCacheDir() {
5081
+ const preferredDir = process.env.XDG_CACHE_HOME ?? path2.join(os2.homedir(), ".cache");
5082
+ return resolveWritableDirectory(preferredDir, "opencode-cache");
5083
+ }
5084
+ function getOmoOpenCodeCacheDir() {
5085
+ return path2.join(getCacheDir(), "evil-omo");
5086
+ }
5087
+ function getOpenCodeCacheDir() {
5088
+ return path2.join(getCacheDir(), "opencode");
5089
+ }
5090
+ var init_data_path = () => {};
5091
+
5092
+ // src/shared/config-errors.ts
5093
+ function getConfigLoadErrors() {
5094
+ return configLoadErrors;
5095
+ }
5096
+ function clearConfigLoadErrors() {
5097
+ configLoadErrors = [];
5098
+ }
5099
+ function addConfigLoadError(error) {
5100
+ configLoadErrors.push(error);
5101
+ }
5102
+ var configLoadErrors;
5103
+ var init_config_errors = __esm(() => {
5104
+ configLoadErrors = [];
5105
+ });
5106
+
5107
+ // src/shared/claude-config-dir.ts
5108
+ var init_claude_config_dir = () => {};
5109
+
4920
5110
  // node_modules/jsonc-parser/lib/esm/impl/scanner.js
4921
5111
  function createScanner(text, ignoreTrivia = false) {
4922
5112
  const len = text.length;
@@ -5781,8 +5971,30 @@ var init_main = __esm(() => {
5781
5971
  })(ParseErrorCode || (ParseErrorCode = {}));
5782
5972
  });
5783
5973
 
5974
+ // src/shared/plugin-identity.ts
5975
+ import { join as join3 } from "path";
5976
+ function detectManagedConfigFile(directory) {
5977
+ for (const baseName of ALL_CONFIG_BASENAMES) {
5978
+ const detected = detectConfigFile(join3(directory, baseName));
5979
+ if (detected.format !== "none") {
5980
+ return { ...detected, baseName };
5981
+ }
5982
+ }
5983
+ return {
5984
+ format: "none",
5985
+ path: join3(directory, `${CONFIG_BASENAME}.json`),
5986
+ baseName: CONFIG_BASENAME
5987
+ };
5988
+ }
5989
+ var PLUGIN_NAME = "evil-omo", LEGACY_PLUGIN_NAME = "oh-my-opencode", CONFIG_BASENAME = "evil-omo", LEGACY_CONFIG_BASENAME = "oh-my-opencode", ALL_CONFIG_BASENAMES;
5990
+ var init_plugin_identity = __esm(() => {
5991
+ init_jsonc_parser();
5992
+ ALL_CONFIG_BASENAMES = [CONFIG_BASENAME, LEGACY_CONFIG_BASENAME];
5993
+ });
5994
+
5784
5995
  // src/shared/jsonc-parser.ts
5785
5996
  import { existsSync, readFileSync } from "fs";
5997
+ import { join as join4 } from "path";
5786
5998
  function parseJsonc(content) {
5787
5999
  const errors = [];
5788
6000
  const result = parse2(content, errors, {
@@ -5806,202 +6018,25 @@ function detectConfigFile(basePath) {
5806
6018
  }
5807
6019
  return { format: "none", path: jsonPath };
5808
6020
  }
5809
- var init_jsonc_parser = __esm(() => {
5810
- init_main();
5811
- init_plugin_identity();
5812
- });
5813
-
5814
- // src/shared/plugin-identity.ts
5815
- import { join } from "path";
5816
- function matchesManagedName(entry, packageName) {
5817
- return entry === packageName || entry.startsWith(`${packageName}@`);
5818
- }
5819
- function findManagedPluginEntry(plugins) {
5820
- for (const [index, entry] of plugins.entries()) {
5821
- for (const packageName of ALL_PLUGIN_NAMES) {
5822
- if (matchesManagedName(entry, packageName)) {
5823
- return { index, packageName };
5824
- }
5825
- }
5826
- }
5827
- return null;
5828
- }
5829
- function detectManagedConfigFile(directory) {
5830
- for (const baseName of ALL_CONFIG_BASENAMES) {
5831
- const detected = detectConfigFile(join(directory, baseName));
5832
- if (detected.format !== "none") {
5833
- return { ...detected, baseName };
5834
- }
5835
- }
5836
- return {
5837
- format: "none",
5838
- path: join(directory, `${CONFIG_BASENAME}.json`),
5839
- baseName: CONFIG_BASENAME
5840
- };
5841
- }
5842
- var PLUGIN_NAME = "evil-omo", LEGACY_PLUGIN_NAME = "oh-my-opencode", ALL_PLUGIN_NAMES, CONFIG_BASENAME = "evil-omo", LEGACY_CONFIG_BASENAME = "oh-my-opencode", ALL_CONFIG_BASENAMES, LOG_FILENAME = "evil-omo.log", CACHE_DIR_NAME = "evil-omo", SCHEMA_FILENAME = "evil-omo.schema.json";
5843
- var init_plugin_identity = __esm(() => {
5844
- init_jsonc_parser();
5845
- ALL_PLUGIN_NAMES = [PLUGIN_NAME, LEGACY_PLUGIN_NAME];
5846
- ALL_CONFIG_BASENAMES = [CONFIG_BASENAME, LEGACY_CONFIG_BASENAME];
5847
- });
5848
-
5849
- // src/shared/logger.ts
5850
- import * as fs from "fs";
5851
- import * as os from "os";
5852
- import * as path from "path";
5853
- function log(message, data) {
5854
- try {
5855
- const timestamp2 = new Date().toISOString();
5856
- const logEntry = `[${timestamp2}] ${message} ${data ? JSON.stringify(data) : ""}
5857
- `;
5858
- fs.appendFileSync(logFile, logEntry);
5859
- } catch {}
5860
- }
5861
- var logFile;
5862
- var init_logger = __esm(() => {
5863
- init_plugin_identity();
5864
- logFile = path.join(os.tmpdir(), LOG_FILENAME);
5865
- });
5866
-
5867
- // src/shared/file-reference-resolver.ts
5868
- var init_file_reference_resolver = __esm(() => {
5869
- init_contains_path();
5870
- init_logger();
5871
- });
5872
- // src/shared/deep-merge.ts
5873
- function isPlainObject(value) {
5874
- return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
5875
- }
5876
- function deepMerge(base, override, depth = 0) {
5877
- if (!base && !override)
5878
- return;
5879
- if (!base)
5880
- return override;
5881
- if (!override)
5882
- return base;
5883
- if (depth > MAX_DEPTH)
5884
- return override ?? base;
5885
- const result = { ...base };
5886
- for (const key of Object.keys(override)) {
5887
- if (DANGEROUS_KEYS.has(key))
5888
- continue;
5889
- const baseValue = base[key];
5890
- const overrideValue = override[key];
5891
- if (overrideValue === undefined)
5892
- continue;
5893
- if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
5894
- result[key] = deepMerge(baseValue, overrideValue, depth + 1);
5895
- } else {
5896
- result[key] = overrideValue;
5897
- }
5898
- }
5899
- return result;
5900
- }
5901
- var DANGEROUS_KEYS, MAX_DEPTH = 50;
5902
- var init_deep_merge = __esm(() => {
5903
- DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
5904
- });
5905
-
5906
- // src/shared/snake-case.ts
5907
- var init_snake_case = __esm(() => {
5908
- init_deep_merge();
5909
- });
5910
-
5911
- // src/shared/tool-name.ts
5912
- var init_tool_name = () => {};
5913
-
5914
- // src/shared/pattern-matcher.ts
5915
- var regexCache;
5916
- var init_pattern_matcher = __esm(() => {
5917
- regexCache = new Map;
5918
- });
5919
- // src/shared/file-utils.ts
5920
- import { lstatSync, realpathSync } from "fs";
5921
- function normalizeDarwinRealpath(filePath) {
5922
- return filePath.startsWith("/private/var/") ? filePath.slice("/private".length) : filePath;
5923
- }
5924
- function resolveSymlink(filePath) {
5925
- try {
5926
- return normalizeDarwinRealpath(realpathSync(filePath));
5927
- } catch {
5928
- return filePath;
5929
- }
5930
- }
5931
- var init_file_utils = () => {};
5932
-
5933
- // src/shared/context-limit-resolver.ts
5934
- var init_context_limit_resolver = () => {};
5935
-
5936
- // src/shared/normalize-sdk-response.ts
5937
- function normalizeSDKResponse(response, fallback, options) {
5938
- if (response === null || response === undefined) {
5939
- return fallback;
5940
- }
5941
- if (Array.isArray(response)) {
5942
- return response;
5943
- }
5944
- if (typeof response === "object" && "data" in response) {
5945
- const data = response.data;
5946
- if (data !== null && data !== undefined) {
5947
- return data;
5948
- }
5949
- if (options?.preferResponseOnMissingData === true) {
5950
- return response;
5951
- }
5952
- return fallback;
6021
+ function detectPluginConfigFile(dir) {
6022
+ const canonicalResult = detectConfigFile(join4(dir, CONFIG_BASENAME));
6023
+ const legacyResult = detectConfigFile(join4(dir, LEGACY_CONFIG_BASENAME));
6024
+ if (canonicalResult.format !== "none") {
6025
+ return {
6026
+ ...canonicalResult,
6027
+ legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined
6028
+ };
5953
6029
  }
5954
- if (options?.preferResponseOnMissingData === true) {
5955
- return response;
6030
+ if (legacyResult.format !== "none") {
6031
+ return legacyResult;
5956
6032
  }
5957
- return fallback;
6033
+ return { format: "none", path: join4(dir, `${CONFIG_BASENAME}.json`) };
5958
6034
  }
5959
-
5960
- // src/shared/dynamic-truncator.ts
5961
- var init_dynamic_truncator = __esm(() => {
5962
- init_context_limit_resolver();
5963
- });
5964
-
5965
- // src/shared/data-path.ts
5966
- import * as path2 from "path";
5967
- import * as os2 from "os";
5968
- function getDataDir() {
5969
- return process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
5970
- }
5971
- function getOpenCodeStorageDir() {
5972
- return path2.join(getDataDir(), "opencode", "storage");
5973
- }
5974
- function getCacheDir() {
5975
- return process.env.XDG_CACHE_HOME ?? path2.join(os2.homedir(), ".cache");
5976
- }
5977
- function getOmoOpenCodeCacheDir() {
5978
- return path2.join(getCacheDir(), CACHE_DIR_NAME);
5979
- }
5980
- function getOpenCodeCacheDir() {
5981
- return path2.join(getCacheDir(), "opencode");
5982
- }
5983
- var init_data_path = __esm(() => {
6035
+ var init_jsonc_parser = __esm(() => {
6036
+ init_main();
5984
6037
  init_plugin_identity();
5985
6038
  });
5986
6039
 
5987
- // src/shared/config-errors.ts
5988
- function getConfigLoadErrors() {
5989
- return configLoadErrors;
5990
- }
5991
- function clearConfigLoadErrors() {
5992
- configLoadErrors = [];
5993
- }
5994
- function addConfigLoadError(error) {
5995
- configLoadErrors.push(error);
5996
- }
5997
- var configLoadErrors;
5998
- var init_config_errors = __esm(() => {
5999
- configLoadErrors = [];
6000
- });
6001
-
6002
- // src/shared/claude-config-dir.ts
6003
- var init_claude_config_dir = () => {};
6004
-
6005
6040
  // src/shared/migration/agent-names.ts
6006
6041
  function migrateAgentNames(agents) {
6007
6042
  const migrated = {};
@@ -6277,9 +6312,9 @@ var init_migration = __esm(() => {
6277
6312
  });
6278
6313
 
6279
6314
  // src/shared/opencode-config-dir.ts
6280
- import { existsSync as existsSync2 } from "fs";
6315
+ import { existsSync as existsSync2, realpathSync as realpathSync2 } from "fs";
6281
6316
  import { homedir as homedir2 } from "os";
6282
- import { join as join4, resolve } from "path";
6317
+ import { join as join5, resolve, win32 } from "path";
6283
6318
  function isDevBuild(version) {
6284
6319
  if (!version)
6285
6320
  return false;
@@ -6289,25 +6324,35 @@ function getTauriConfigDir(identifier) {
6289
6324
  const platform = process.platform;
6290
6325
  switch (platform) {
6291
6326
  case "darwin":
6292
- return join4(homedir2(), "Library", "Application Support", identifier);
6327
+ return join5(homedir2(), "Library", "Application Support", identifier);
6293
6328
  case "win32": {
6294
- const appData = process.env.APPDATA || join4(homedir2(), "AppData", "Roaming");
6295
- return join4(appData, identifier);
6329
+ const appData = process.env.APPDATA || join5(homedir2(), "AppData", "Roaming");
6330
+ return win32.join(appData, identifier);
6296
6331
  }
6297
6332
  case "linux":
6298
6333
  default: {
6299
- const xdgConfig = process.env.XDG_CONFIG_HOME || join4(homedir2(), ".config");
6300
- return join4(xdgConfig, identifier);
6334
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
6335
+ return join5(xdgConfig, identifier);
6301
6336
  }
6302
6337
  }
6303
6338
  }
6339
+ function resolveConfigPath(pathValue) {
6340
+ const resolvedPath = resolve(pathValue);
6341
+ if (!existsSync2(resolvedPath))
6342
+ return resolvedPath;
6343
+ try {
6344
+ return realpathSync2(resolvedPath);
6345
+ } catch {
6346
+ return resolvedPath;
6347
+ }
6348
+ }
6304
6349
  function getCliConfigDir() {
6305
6350
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
6306
6351
  if (envConfigDir) {
6307
- return resolve(envConfigDir);
6352
+ return resolveConfigPath(envConfigDir);
6308
6353
  }
6309
- const xdgConfig = process.env.XDG_CONFIG_HOME || join4(homedir2(), ".config");
6310
- return join4(xdgConfig, "opencode");
6354
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
6355
+ return resolveConfigPath(join5(xdgConfig, "opencode"));
6311
6356
  }
6312
6357
  function getOpenCodeConfigDir(options) {
6313
6358
  const { binary: binary2, version, checkExisting = true } = options;
@@ -6315,11 +6360,12 @@ function getOpenCodeConfigDir(options) {
6315
6360
  return getCliConfigDir();
6316
6361
  }
6317
6362
  const identifier = isDevBuild(version) ? TAURI_APP_IDENTIFIER_DEV : TAURI_APP_IDENTIFIER;
6318
- const tauriDir = getTauriConfigDir(identifier);
6363
+ const tauriDirBase = getTauriConfigDir(identifier);
6364
+ const tauriDir = process.platform === "win32" ? win32.isAbsolute(tauriDirBase) ? win32.normalize(tauriDirBase) : win32.resolve(tauriDirBase) : resolveConfigPath(tauriDirBase);
6319
6365
  if (checkExisting) {
6320
6366
  const legacyDir = getCliConfigDir();
6321
- const legacyConfig = join4(legacyDir, "opencode.json");
6322
- const legacyConfigC = join4(legacyDir, "opencode.jsonc");
6367
+ const legacyConfig = join5(legacyDir, "opencode.json");
6368
+ const legacyConfigC = join5(legacyDir, "opencode.jsonc");
6323
6369
  if (existsSync2(legacyConfig) || existsSync2(legacyConfigC)) {
6324
6370
  return legacyDir;
6325
6371
  }
@@ -6330,10 +6376,10 @@ function getOpenCodeConfigPaths(options) {
6330
6376
  const configDir = getOpenCodeConfigDir(options);
6331
6377
  return {
6332
6378
  configDir,
6333
- configJson: join4(configDir, "opencode.json"),
6334
- configJsonc: join4(configDir, "opencode.jsonc"),
6335
- packageJson: join4(configDir, "package.json"),
6336
- omoConfig: join4(configDir, `${CONFIG_BASENAME}.json`)
6379
+ configJson: join5(configDir, "opencode.json"),
6380
+ configJsonc: join5(configDir, "opencode.jsonc"),
6381
+ packageJson: join5(configDir, "package.json"),
6382
+ omoConfig: join5(configDir, `${CONFIG_BASENAME}.json`)
6337
6383
  };
6338
6384
  }
6339
6385
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
@@ -6342,18 +6388,88 @@ var init_opencode_config_dir = __esm(() => {
6342
6388
  });
6343
6389
 
6344
6390
  // src/shared/opencode-version.ts
6345
- var NOT_CACHED;
6391
+ import { execSync } from "child_process";
6392
+ function parseVersion(version) {
6393
+ const cleaned = version.replace(/^v/, "").split("-")[0];
6394
+ return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
6395
+ }
6396
+ function compareVersions(a, b) {
6397
+ const partsA = parseVersion(a);
6398
+ const partsB = parseVersion(b);
6399
+ const maxLen = Math.max(partsA.length, partsB.length);
6400
+ for (let i2 = 0;i2 < maxLen; i2++) {
6401
+ const numA = partsA[i2] ?? 0;
6402
+ const numB = partsB[i2] ?? 0;
6403
+ if (numA < numB)
6404
+ return -1;
6405
+ if (numA > numB)
6406
+ return 1;
6407
+ }
6408
+ return 0;
6409
+ }
6410
+ function getOpenCodeVersion() {
6411
+ if (cachedVersion !== NOT_CACHED) {
6412
+ return cachedVersion;
6413
+ }
6414
+ try {
6415
+ const result = execSync("opencode --version", {
6416
+ encoding: "utf-8",
6417
+ timeout: 5000,
6418
+ stdio: ["pipe", "pipe", "pipe"]
6419
+ }).trim();
6420
+ const versionMatch = result.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
6421
+ cachedVersion = versionMatch?.[1] ?? null;
6422
+ return cachedVersion;
6423
+ } catch {
6424
+ cachedVersion = null;
6425
+ return null;
6426
+ }
6427
+ }
6428
+ function isOpenCodeVersionAtLeast(version) {
6429
+ const current = getOpenCodeVersion();
6430
+ if (!current)
6431
+ return true;
6432
+ return compareVersions(current, version) >= 0;
6433
+ }
6434
+ var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion;
6346
6435
  var init_opencode_version = __esm(() => {
6347
6436
  NOT_CACHED = Symbol("NOT_CACHED");
6437
+ cachedVersion = NOT_CACHED;
6348
6438
  });
6349
6439
 
6350
6440
  // src/shared/opencode-storage-detection.ts
6351
- var NOT_CACHED2, FALSE_PENDING_RETRY;
6441
+ import { existsSync as existsSync3 } from "fs";
6442
+ import { join as join6 } from "path";
6443
+ function isSqliteBackend() {
6444
+ if (cachedResult === true)
6445
+ return true;
6446
+ if (cachedResult === false)
6447
+ return false;
6448
+ const check = () => {
6449
+ const versionOk = isOpenCodeVersionAtLeast(OPENCODE_SQLITE_VERSION);
6450
+ const dbPath = join6(getDataDir(), "opencode", "opencode.db");
6451
+ return versionOk && existsSync3(dbPath);
6452
+ };
6453
+ if (cachedResult === FALSE_PENDING_RETRY) {
6454
+ const result2 = check();
6455
+ cachedResult = result2;
6456
+ return result2;
6457
+ }
6458
+ const result = check();
6459
+ if (result) {
6460
+ cachedResult = true;
6461
+ } else {
6462
+ cachedResult = FALSE_PENDING_RETRY;
6463
+ }
6464
+ return result;
6465
+ }
6466
+ var NOT_CACHED2, FALSE_PENDING_RETRY, cachedResult;
6352
6467
  var init_opencode_storage_detection = __esm(() => {
6353
6468
  init_data_path();
6354
6469
  init_opencode_version();
6355
6470
  NOT_CACHED2 = Symbol("NOT_CACHED");
6356
6471
  FALSE_PENDING_RETRY = Symbol("FALSE_PENDING_RETRY");
6472
+ cachedResult = NOT_CACHED2;
6357
6473
  });
6358
6474
  // src/shared/external-plugin-detector.ts
6359
6475
  var init_external_plugin_detector = __esm(() => {
@@ -6764,20 +6880,20 @@ function normalizeModelID(modelID) {
6764
6880
  }
6765
6881
 
6766
6882
  // src/shared/json-file-cache-store.ts
6767
- import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6768
- import { join as join5 } from "path";
6883
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6884
+ import { join as join7 } from "path";
6769
6885
  function toLogLabel(cacheLabel) {
6770
6886
  return cacheLabel.toLowerCase();
6771
6887
  }
6772
6888
  function createJsonFileCacheStore(options) {
6773
6889
  let memoryValue;
6774
6890
  function getCacheFilePath() {
6775
- return join5(options.getCacheDir(), options.filename);
6891
+ return join7(options.getCacheDir(), options.filename);
6776
6892
  }
6777
6893
  function ensureCacheDir() {
6778
6894
  const cacheDir = options.getCacheDir();
6779
- if (!existsSync3(cacheDir)) {
6780
- mkdirSync(cacheDir, { recursive: true });
6895
+ if (!existsSync4(cacheDir)) {
6896
+ mkdirSync2(cacheDir, { recursive: true });
6781
6897
  }
6782
6898
  }
6783
6899
  function read() {
@@ -6785,7 +6901,7 @@ function createJsonFileCacheStore(options) {
6785
6901
  return memoryValue;
6786
6902
  }
6787
6903
  const cacheFile = getCacheFilePath();
6788
- if (!existsSync3(cacheFile)) {
6904
+ if (!existsSync4(cacheFile)) {
6789
6905
  memoryValue = null;
6790
6906
  log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
6791
6907
  return null;
@@ -6805,7 +6921,7 @@ function createJsonFileCacheStore(options) {
6805
6921
  }
6806
6922
  }
6807
6923
  function has() {
6808
- return existsSync3(getCacheFilePath());
6924
+ return existsSync4(getCacheFilePath());
6809
6925
  }
6810
6926
  function write(value) {
6811
6927
  ensureCacheDir();
@@ -6974,14 +7090,14 @@ var init_connected_providers_cache = __esm(() => {
6974
7090
  });
6975
7091
 
6976
7092
  // src/shared/model-availability.ts
6977
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
6978
- import { join as join6 } from "path";
7093
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
7094
+ import { join as join8 } from "path";
6979
7095
  function isModelCacheAvailable() {
6980
7096
  if (hasProviderModelsCache()) {
6981
7097
  return true;
6982
7098
  }
6983
- const cacheFile = join6(getOpenCodeCacheDir(), "models.json");
6984
- return existsSync4(cacheFile);
7099
+ const cacheFile = join8(getOpenCodeCacheDir(), "models.json");
7100
+ return existsSync5(cacheFile);
6985
7101
  }
6986
7102
  var init_model_availability = __esm(() => {
6987
7103
  init_logger();
@@ -48294,17 +48410,43 @@ var init_hook_message_injector = __esm(() => {
48294
48410
  });
48295
48411
 
48296
48412
  // src/shared/opencode-storage-paths.ts
48297
- import { join as join7 } from "path";
48413
+ import { join as join9 } from "path";
48298
48414
  var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48299
48415
  var init_opencode_storage_paths = __esm(() => {
48300
48416
  init_data_path();
48301
48417
  OPENCODE_STORAGE = getOpenCodeStorageDir();
48302
- MESSAGE_STORAGE = join7(OPENCODE_STORAGE, "message");
48303
- PART_STORAGE = join7(OPENCODE_STORAGE, "part");
48304
- SESSION_STORAGE = join7(OPENCODE_STORAGE, "session");
48418
+ MESSAGE_STORAGE = join9(OPENCODE_STORAGE, "message");
48419
+ PART_STORAGE = join9(OPENCODE_STORAGE, "part");
48420
+ SESSION_STORAGE = join9(OPENCODE_STORAGE, "session");
48305
48421
  });
48306
48422
 
48307
48423
  // src/shared/opencode-message-dir.ts
48424
+ import { existsSync as existsSync6, readdirSync } from "fs";
48425
+ import { join as join10 } from "path";
48426
+ function getMessageDir(sessionID) {
48427
+ if (!sessionID.startsWith("ses_"))
48428
+ return null;
48429
+ if (/[/\\]|\.\./.test(sessionID))
48430
+ return null;
48431
+ if (!existsSync6(MESSAGE_STORAGE))
48432
+ return null;
48433
+ const directPath = join10(MESSAGE_STORAGE, sessionID);
48434
+ if (existsSync6(directPath)) {
48435
+ return directPath;
48436
+ }
48437
+ try {
48438
+ for (const dir of readdirSync(MESSAGE_STORAGE)) {
48439
+ const sessionPath = join10(MESSAGE_STORAGE, dir, sessionID);
48440
+ if (existsSync6(sessionPath)) {
48441
+ return sessionPath;
48442
+ }
48443
+ }
48444
+ } catch (error) {
48445
+ log("[opencode-message-dir] Failed to scan message directories", { sessionID, error: String(error) });
48446
+ return null;
48447
+ }
48448
+ return null;
48449
+ }
48308
48450
  var init_opencode_message_dir = __esm(() => {
48309
48451
  init_opencode_storage_paths();
48310
48452
  init_logger();
@@ -48591,6 +48733,7 @@ var init_hook_loader = __esm(() => {
48591
48733
  });
48592
48734
 
48593
48735
  // src/features/claude-code-plugin-loader/loader.ts
48736
+ var cachedPluginComponentsByKey;
48594
48737
  var init_loader = __esm(() => {
48595
48738
  init_logger();
48596
48739
  init_discovery();
@@ -48605,6 +48748,7 @@ var init_loader = __esm(() => {
48605
48748
  init_agent_loader();
48606
48749
  init_mcp_server_loader();
48607
48750
  init_hook_loader();
48751
+ cachedPluginComponentsByKey = new Map;
48608
48752
  });
48609
48753
 
48610
48754
  // src/features/claude-code-plugin-loader/index.ts
@@ -48741,16 +48885,15 @@ function getConfigJsonc() {
48741
48885
  return getConfigContext().paths.configJsonc;
48742
48886
  }
48743
48887
  function getOmoConfigPath() {
48888
+ const configDir = getConfigContext().paths.configDir;
48889
+ const detected = detectPluginConfigFile(configDir);
48890
+ if (detected.format !== "none")
48891
+ return detected.path;
48744
48892
  return getConfigContext().paths.omoConfig;
48745
48893
  }
48746
- function getExistingOmoConfigPath() {
48747
- const detected = detectManagedConfigFile(getConfigDir());
48748
- return detected.format === "none" ? null : detected.path;
48749
- }
48750
48894
  var configContext = null;
48751
48895
  var init_config_context = __esm(() => {
48752
48896
  init_shared();
48753
- init_plugin_identity();
48754
48897
  });
48755
48898
 
48756
48899
  // src/cli/config-manager/npm-dist-tags.ts
@@ -48791,17 +48934,17 @@ async function getPluginNameWithVersion(currentVersion, packageName = DEFAULT_PA
48791
48934
  }
48792
48935
  var DEFAULT_PACKAGE_NAME, PRIORITIZED_TAGS;
48793
48936
  var init_plugin_name_with_version = __esm(() => {
48794
- init_plugin_identity();
48937
+ init_shared();
48795
48938
  DEFAULT_PACKAGE_NAME = PLUGIN_NAME;
48796
48939
  PRIORITIZED_TAGS = ["latest", "beta", "next"];
48797
48940
  });
48798
48941
 
48799
48942
  // src/cli/config-manager/ensure-config-directory-exists.ts
48800
- import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
48943
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
48801
48944
  function ensureConfigDirectoryExists() {
48802
48945
  const configDir = getConfigDir();
48803
- if (!existsSync5(configDir)) {
48804
- mkdirSync2(configDir, { recursive: true });
48946
+ if (!existsSync7(configDir)) {
48947
+ mkdirSync3(configDir, { recursive: true });
48805
48948
  }
48806
48949
  }
48807
48950
  var init_ensure_config_directory_exists = __esm(() => {
@@ -48838,14 +48981,14 @@ function formatErrorWithSuggestion(err, context) {
48838
48981
  }
48839
48982
 
48840
48983
  // src/cli/config-manager/opencode-config-format.ts
48841
- import { existsSync as existsSync6 } from "fs";
48984
+ import { existsSync as existsSync8 } from "fs";
48842
48985
  function detectConfigFormat() {
48843
48986
  const configJsonc = getConfigJsonc();
48844
48987
  const configJson = getConfigJson();
48845
- if (existsSync6(configJsonc)) {
48988
+ if (existsSync8(configJsonc)) {
48846
48989
  return { format: "jsonc", path: configJsonc };
48847
48990
  }
48848
- if (existsSync6(configJson)) {
48991
+ if (existsSync8(configJson)) {
48849
48992
  return { format: "json", path: configJson };
48850
48993
  }
48851
48994
  return { format: "none", path: configJson };
@@ -48901,7 +49044,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48901
49044
  };
48902
49045
  }
48903
49046
  const { format: format2, path: path3 } = detectConfigFormat();
48904
- const pluginEntry = await getPluginNameWithVersion(currentVersion, PACKAGE_NAME);
49047
+ const pluginEntry = await getPluginNameWithVersion(currentVersion, PLUGIN_NAME);
48905
49048
  try {
48906
49049
  if (format2 === "none") {
48907
49050
  const config2 = { plugin: [pluginEntry] };
@@ -48919,24 +49062,28 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48919
49062
  }
48920
49063
  const config = parseResult.config;
48921
49064
  const plugins = config.plugin ?? [];
48922
- const existingPlugin = findManagedPluginEntry(plugins);
48923
- if (existingPlugin) {
48924
- if (plugins[existingPlugin.index] === pluginEntry) {
48925
- return { success: true, configPath: path3 };
48926
- }
48927
- plugins[existingPlugin.index] = pluginEntry;
49065
+ const canonicalEntries = plugins.filter((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`));
49066
+ const legacyEntries = plugins.filter((plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`));
49067
+ const otherPlugins = plugins.filter((plugin) => !(plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`)) && !(plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)));
49068
+ const normalizedPlugins = [...otherPlugins];
49069
+ if (canonicalEntries.length > 0) {
49070
+ normalizedPlugins.push(canonicalEntries[0]);
49071
+ } else if (legacyEntries.length > 0) {
49072
+ const versionMatch = legacyEntries[0].match(/@(.+)$/);
49073
+ const preservedVersion = versionMatch ? versionMatch[1] : null;
49074
+ normalizedPlugins.push(preservedVersion ? `${PLUGIN_NAME}@${preservedVersion}` : pluginEntry);
48928
49075
  } else {
48929
- plugins.push(pluginEntry);
49076
+ normalizedPlugins.push(pluginEntry);
48930
49077
  }
48931
- config.plugin = plugins;
49078
+ config.plugin = normalizedPlugins;
48932
49079
  if (format2 === "jsonc") {
48933
49080
  const content = readFileSync5(path3, "utf-8");
48934
- const pluginArrayRegex = /"plugin"\s*:\s*\[([\s\S]*?)\]/;
49081
+ const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
48935
49082
  const match = content.match(pluginArrayRegex);
48936
49083
  if (match) {
48937
- const formattedPlugins = plugins.map((p) => `"${p}"`).join(`,
49084
+ const formattedPlugins = normalizedPlugins.map((p) => `"${p}"`).join(`,
48938
49085
  `);
48939
- const newContent = content.replace(pluginArrayRegex, `"plugin": [
49086
+ const newContent = content.replace(pluginArrayRegex, `$1[
48940
49087
  ${formattedPlugins}
48941
49088
  ]`);
48942
49089
  writeFileSync3(path3, newContent);
@@ -48958,15 +49105,13 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48958
49105
  };
48959
49106
  }
48960
49107
  }
48961
- var PACKAGE_NAME;
48962
49108
  var init_add_plugin_to_opencode_config = __esm(() => {
48963
- init_plugin_identity();
49109
+ init_shared();
48964
49110
  init_config_context();
48965
49111
  init_ensure_config_directory_exists();
48966
49112
  init_opencode_config_format();
48967
49113
  init_parse_opencode_config_file();
48968
49114
  init_plugin_name_with_version();
48969
- PACKAGE_NAME = PLUGIN_NAME;
48970
49115
  });
48971
49116
 
48972
49117
  // src/cli/model-fallback-requirements.ts
@@ -49092,7 +49237,7 @@ function generateModelConfig(config) {
49092
49237
  for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
49093
49238
  if (role === "librarian") {
49094
49239
  if (avail.opencodeGo) {
49095
- agents[role] = { model: "opencode-go/minimax-m2.5" };
49240
+ agents[role] = { model: "opencode-go/minimax-m2.7" };
49096
49241
  } else if (avail.zai) {
49097
49242
  agents[role] = { model: ZAI_MODEL };
49098
49243
  }
@@ -49104,7 +49249,7 @@ function generateModelConfig(config) {
49104
49249
  } else if (avail.opencodeZen) {
49105
49250
  agents[role] = { model: "opencode/claude-haiku-4-5" };
49106
49251
  } else if (avail.opencodeGo) {
49107
- agents[role] = { model: "opencode-go/minimax-m2.5" };
49252
+ agents[role] = { model: "opencode-go/minimax-m2.7" };
49108
49253
  } else if (avail.copilot) {
49109
49254
  agents[role] = { model: "github-copilot/gpt-5-mini" };
49110
49255
  } else {
@@ -49161,13 +49306,11 @@ function generateModelConfig(config) {
49161
49306
  };
49162
49307
  return isOpenAiOnlyAvailability(avail) ? applyOpenAiOnlyModelCatalog(generatedConfig) : generatedConfig;
49163
49308
  }
49164
- var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/glm-4.7-free", SCHEMA_URL;
49309
+ var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/gpt-5-nano", SCHEMA_URL = "https://raw.githubusercontent.com/D4ch1au/evil-oh-my-openagent/dev/assets/evil-omo.schema.json";
49165
49310
  var init_model_fallback = __esm(() => {
49166
49311
  init_model_fallback_requirements();
49167
49312
  init_openai_only_model_catalog();
49168
49313
  init_fallback_chain_resolution();
49169
- init_plugin_identity();
49170
- SCHEMA_URL = `https://raw.githubusercontent.com/D4ch1au/evil-oh-my-openagent/dev/assets/${SCHEMA_FILENAME}`;
49171
49314
  });
49172
49315
 
49173
49316
  // src/cli/config-manager/generate-omo-config.ts
@@ -49196,7 +49339,7 @@ function deepMergeRecord(target, source) {
49196
49339
  }
49197
49340
 
49198
49341
  // src/cli/config-manager/write-omo-config.ts
49199
- import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49342
+ import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49200
49343
  function isEmptyOrWhitespace2(content) {
49201
49344
  return content.trim().length === 0;
49202
49345
  }
@@ -49211,13 +49354,12 @@ function writeOmoConfig(installConfig) {
49211
49354
  };
49212
49355
  }
49213
49356
  const omoConfigPath = getOmoConfigPath();
49214
- const existingConfigPath = getExistingOmoConfigPath() ?? omoConfigPath;
49215
49357
  try {
49216
49358
  const newConfig = generateOmoConfig(installConfig);
49217
- if (existsSync7(existingConfigPath)) {
49359
+ if (existsSync9(omoConfigPath)) {
49218
49360
  try {
49219
- const stat = statSync2(existingConfigPath);
49220
- const content = readFileSync6(existingConfigPath, "utf-8");
49361
+ const stat = statSync2(omoConfigPath);
49362
+ const content = readFileSync6(omoConfigPath, "utf-8");
49221
49363
  if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
49222
49364
  writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49223
49365
  `);
@@ -49230,7 +49372,6 @@ function writeOmoConfig(installConfig) {
49230
49372
  return { success: true, configPath: omoConfigPath };
49231
49373
  }
49232
49374
  const merged = deepMergeRecord(newConfig, existing);
49233
- merged.$schema = newConfig.$schema;
49234
49375
  writeFileSync4(omoConfigPath, JSON.stringify(merged, null, 2) + `
49235
49376
  `);
49236
49377
  } catch (parseErr) {
@@ -49346,7 +49487,7 @@ async function isOpenCodeInstalled() {
49346
49487
  const result = await findOpenCodeBinaryWithVersion();
49347
49488
  return result !== null;
49348
49489
  }
49349
- async function getOpenCodeVersion() {
49490
+ async function getOpenCodeVersion2() {
49350
49491
  const result = await findOpenCodeBinaryWithVersion();
49351
49492
  return result?.version ?? null;
49352
49493
  }
@@ -49358,10 +49499,10 @@ var init_opencode_binary = __esm(() => {
49358
49499
  });
49359
49500
 
49360
49501
  // src/cli/config-manager/detect-current-config.ts
49361
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
49502
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
49362
49503
  function detectProvidersFromOmoConfig() {
49363
- const omoConfigPath = getExistingOmoConfigPath();
49364
- if (!omoConfigPath || !existsSync8(omoConfigPath)) {
49504
+ const omoConfigPath = getOmoConfigPath();
49505
+ if (!existsSync10(omoConfigPath)) {
49365
49506
  return {
49366
49507
  hasOpenAI: true,
49367
49508
  hasOpencodeZen: true,
@@ -49399,6 +49540,9 @@ function detectProvidersFromOmoConfig() {
49399
49540
  };
49400
49541
  }
49401
49542
  }
49543
+ function isOurPlugin(plugin) {
49544
+ return plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) || plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`);
49545
+ }
49402
49546
  function detectCurrentConfig() {
49403
49547
  const result = {
49404
49548
  isInstalled: false,
@@ -49422,7 +49566,7 @@ function detectCurrentConfig() {
49422
49566
  }
49423
49567
  const openCodeConfig = parseResult.config;
49424
49568
  const plugins = openCodeConfig.plugin ?? [];
49425
- result.isInstalled = findManagedPluginEntry(plugins) !== null;
49569
+ result.isInstalled = plugins.some(isOurPlugin);
49426
49570
  if (!result.isInstalled) {
49427
49571
  return result;
49428
49572
  }
@@ -49438,17 +49582,16 @@ function detectCurrentConfig() {
49438
49582
  }
49439
49583
  var init_detect_current_config = __esm(() => {
49440
49584
  init_shared();
49441
- init_plugin_identity();
49442
49585
  init_config_context();
49443
49586
  init_opencode_config_format();
49444
49587
  init_parse_opencode_config_file();
49445
49588
  });
49446
49589
 
49447
49590
  // src/cli/config-manager/bun-install.ts
49448
- import { existsSync as existsSync9 } from "fs";
49449
- import { join as join8 } from "path";
49591
+ import { existsSync as existsSync11 } from "fs";
49592
+ import { join as join11 } from "path";
49450
49593
  function getDefaultWorkspaceDir() {
49451
- return join8(getOpenCodeCacheDir(), "packages");
49594
+ return join11(getOpenCodeCacheDir(), "packages");
49452
49595
  }
49453
49596
  function readProcessOutput(stream) {
49454
49597
  if (!stream) {
@@ -49474,7 +49617,7 @@ async function runBunInstallWithDetails(options) {
49474
49617
  const outputMode = options?.outputMode ?? "pipe";
49475
49618
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
49476
49619
  const packageJsonPath = `${cacheDir}/package.json`;
49477
- if (!existsSync9(packageJsonPath)) {
49620
+ if (!existsSync11(packageJsonPath)) {
49478
49621
  return {
49479
49622
  success: false,
49480
49623
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -49618,37 +49761,42 @@ function getWindowsAppdataDir() {
49618
49761
  return null;
49619
49762
  return process.env.APPDATA ?? path4.join(os3.homedir(), "AppData", "Roaming");
49620
49763
  }
49621
- var PACKAGE_NAME2, NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, USER_CONFIG_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC, INSTALLED_PACKAGE_JSON;
49764
+ function getUserConfigDir() {
49765
+ return getOpenCodeConfigDir({ binary: "opencode" });
49766
+ }
49767
+ function getUserOpencodeConfig() {
49768
+ return path4.join(getUserConfigDir(), "opencode.json");
49769
+ }
49770
+ function getUserOpencodeConfigJsonc() {
49771
+ return path4.join(getUserConfigDir(), "opencode.jsonc");
49772
+ }
49773
+ var PACKAGE_NAME = "oh-my-openagent", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON;
49622
49774
  var init_constants3 = __esm(() => {
49623
49775
  init_data_path();
49624
49776
  init_opencode_config_dir();
49625
- init_plugin_identity();
49626
- PACKAGE_NAME2 = PLUGIN_NAME;
49627
- NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
49777
+ NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
49628
49778
  CACHE_ROOT_DIR = getOpenCodeCacheDir();
49629
49779
  CACHE_DIR = path4.join(CACHE_ROOT_DIR, "packages");
49630
49780
  VERSION_FILE = path4.join(CACHE_ROOT_DIR, "version");
49631
- USER_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" });
49632
- USER_OPENCODE_CONFIG = path4.join(USER_CONFIG_DIR, "opencode.json");
49633
- USER_OPENCODE_CONFIG_JSONC = path4.join(USER_CONFIG_DIR, "opencode.jsonc");
49634
- INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
49781
+ INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
49635
49782
  });
49636
49783
 
49637
49784
  // src/hooks/auto-update-checker/checker/config-paths.ts
49638
49785
  import * as os4 from "os";
49639
49786
  import * as path5 from "path";
49640
49787
  function getConfigPaths(directory) {
49788
+ const userConfigDir = getUserConfigDir();
49641
49789
  const paths = [
49642
49790
  path5.join(directory, ".opencode", "opencode.json"),
49643
49791
  path5.join(directory, ".opencode", "opencode.jsonc"),
49644
- USER_OPENCODE_CONFIG,
49645
- USER_OPENCODE_CONFIG_JSONC
49792
+ getUserOpencodeConfig(),
49793
+ getUserOpencodeConfigJsonc()
49646
49794
  ];
49647
49795
  if (process.platform === "win32") {
49648
49796
  const crossPlatformDir = path5.join(os4.homedir(), ".config");
49649
49797
  const appdataDir = getWindowsAppdataDir();
49650
49798
  if (appdataDir) {
49651
- const alternateDir = USER_CONFIG_DIR === crossPlatformDir ? appdataDir : crossPlatformDir;
49799
+ const alternateDir = userConfigDir === crossPlatformDir ? appdataDir : crossPlatformDir;
49652
49800
  const alternateConfig = path5.join(alternateDir, "opencode", "opencode.json");
49653
49801
  const alternateConfigJsonc = path5.join(alternateDir, "opencode", "opencode.jsonc");
49654
49802
  if (!paths.includes(alternateConfig)) {
@@ -49685,7 +49833,7 @@ function getLocalDevPath(directory) {
49685
49833
  const config2 = JSON.parse(stripJsonComments(content));
49686
49834
  const plugins = config2.plugin ?? [];
49687
49835
  for (const entry of plugins) {
49688
- if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME2)) {
49836
+ if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
49689
49837
  try {
49690
49838
  return fileURLToPath(entry);
49691
49839
  } catch {
@@ -49717,7 +49865,7 @@ function findPackageJsonUp(startPath) {
49717
49865
  try {
49718
49866
  const content = fs5.readFileSync(pkgPath, "utf-8");
49719
49867
  const pkg = JSON.parse(content);
49720
- if (pkg.name === PACKAGE_NAME2)
49868
+ if (pkg.name === PACKAGE_NAME)
49721
49869
  return pkgPath;
49722
49870
  } catch {}
49723
49871
  }
@@ -49765,15 +49913,15 @@ function findPluginEntry(directory) {
49765
49913
  const content = fs7.readFileSync(configPath, "utf-8");
49766
49914
  const config2 = JSON.parse(stripJsonComments(content));
49767
49915
  const plugins = config2.plugin ?? [];
49768
- const managedEntry = findManagedPluginEntry(plugins);
49769
- if (managedEntry) {
49770
- const entry = plugins[managedEntry.index];
49771
- if (entry === managedEntry.packageName) {
49916
+ for (const entry of plugins) {
49917
+ if (entry === PACKAGE_NAME) {
49772
49918
  return { entry, isPinned: false, pinnedVersion: null, configPath };
49773
49919
  }
49774
- const pinnedVersion = entry.slice(managedEntry.packageName.length + 1);
49775
- const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
49776
- return { entry, isPinned, pinnedVersion, configPath };
49920
+ if (entry.startsWith(`${PACKAGE_NAME}@`)) {
49921
+ const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
49922
+ const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
49923
+ return { entry, isPinned, pinnedVersion, configPath };
49924
+ }
49777
49925
  }
49778
49926
  } catch {
49779
49927
  continue;
@@ -49783,7 +49931,7 @@ function findPluginEntry(directory) {
49783
49931
  }
49784
49932
  var EXACT_SEMVER_REGEX;
49785
49933
  var init_plugin_entry = __esm(() => {
49786
- init_plugin_identity();
49934
+ init_constants3();
49787
49935
  init_config_paths();
49788
49936
  EXACT_SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/;
49789
49937
  });
@@ -49993,7 +50141,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
49993
50141
  if (!fs9.existsSync(cachePackageJsonPath)) {
49994
50142
  log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
49995
50143
  return {
49996
- ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME2]: intentVersion } }),
50144
+ ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME]: intentVersion } }),
49997
50145
  message: `Created cache package.json with: ${intentVersion}`
49998
50146
  };
49999
50147
  }
@@ -50011,21 +50159,21 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50011
50159
  log("[auto-update-checker] Failed to parse cache package.json:", err);
50012
50160
  return { synced: false, error: "parse_error", message: "Failed to parse cache package.json (malformed JSON)" };
50013
50161
  }
50014
- if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME2]) {
50162
+ if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME]) {
50015
50163
  log("[auto-update-checker] Plugin missing from cache package.json dependencies, adding dependency", { intentVersion });
50016
50164
  const nextPkgJson = {
50017
50165
  ...pkgJson ?? {},
50018
50166
  dependencies: {
50019
50167
  ...pkgJson?.dependencies ?? {},
50020
- [PACKAGE_NAME2]: intentVersion
50168
+ [PACKAGE_NAME]: intentVersion
50021
50169
  }
50022
50170
  };
50023
50171
  return {
50024
50172
  ...writeCachePackageJson(cachePackageJsonPath, nextPkgJson),
50025
- message: `Added ${PACKAGE_NAME2}: ${intentVersion}`
50173
+ message: `Added ${PACKAGE_NAME}: ${intentVersion}`
50026
50174
  };
50027
50175
  }
50028
- const currentVersion = pkgJson.dependencies[PACKAGE_NAME2];
50176
+ const currentVersion = pkgJson.dependencies[PACKAGE_NAME];
50029
50177
  if (currentVersion === intentVersion) {
50030
50178
  log("[auto-update-checker] Cache package.json already matches intent:", intentVersion);
50031
50179
  return { synced: false, error: null, message: `Already matches intent: ${intentVersion}` };
@@ -50037,7 +50185,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50037
50185
  } else {
50038
50186
  log(`[auto-update-checker] Updating cache package.json: "${currentVersion}" \u2192 "${intentVersion}"`);
50039
50187
  }
50040
- pkgJson.dependencies[PACKAGE_NAME2] = intentVersion;
50188
+ pkgJson.dependencies[PACKAGE_NAME] = intentVersion;
50041
50189
  return {
50042
50190
  ...writeCachePackageJson(cachePackageJsonPath, pkgJson),
50043
50191
  message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"`
@@ -50103,10 +50251,11 @@ function removeFromBunLock(packageName) {
50103
50251
  }
50104
50252
  return false;
50105
50253
  }
50106
- function invalidatePackage(packageName = PACKAGE_NAME2) {
50254
+ function invalidatePackage(packageName = PACKAGE_NAME) {
50107
50255
  try {
50256
+ const userConfigDir = getUserConfigDir();
50108
50257
  const pkgDirs = [
50109
- path9.join(USER_CONFIG_DIR, "node_modules", packageName),
50258
+ path9.join(userConfigDir, "node_modules", packageName),
50110
50259
  path9.join(CACHE_DIR, "node_modules", packageName)
50111
50260
  ];
50112
50261
  let packageRemoved = false;
@@ -50167,8 +50316,8 @@ var init_update_toasts = __esm(() => {
50167
50316
  });
50168
50317
 
50169
50318
  // src/hooks/auto-update-checker/hook/background-update-check.ts
50170
- import { existsSync as existsSync20 } from "fs";
50171
- import { join as join19 } from "path";
50319
+ import { existsSync as existsSync22 } from "fs";
50320
+ import { join as join23 } from "path";
50172
50321
  function getCacheWorkspaceDir(deps) {
50173
50322
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
50174
50323
  }
@@ -50178,8 +50327,8 @@ function getPinnedVersionToastMessage(latestVersion) {
50178
50327
  function resolveActiveInstallWorkspace(deps) {
50179
50328
  const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
50180
50329
  const cacheDir = getCacheWorkspaceDir(deps);
50181
- const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME2, "package.json");
50182
- const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME2, "package.json");
50330
+ const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
50331
+ const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME, "package.json");
50183
50332
  if (deps.existsSync(configInstallPath)) {
50184
50333
  deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50185
50334
  return configPaths.configDir;
@@ -50225,8 +50374,8 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50225
50374
  deps.log("[auto-update-checker] Plugin not found in config");
50226
50375
  return;
50227
50376
  }
50228
- const cachedVersion = deps.getCachedVersion();
50229
- const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
50377
+ const cachedVersion2 = deps.getCachedVersion();
50378
+ const currentVersion = cachedVersion2 ?? pluginInfo.pinnedVersion;
50230
50379
  if (!currentVersion) {
50231
50380
  deps.log("[auto-update-checker] No version found (cached or pinned)");
50232
50381
  return;
@@ -50258,7 +50407,7 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50258
50407
  await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50259
50408
  return;
50260
50409
  }
50261
- deps.invalidatePackage(PACKAGE_NAME2);
50410
+ deps.invalidatePackage(PACKAGE_NAME);
50262
50411
  const activeWorkspace = resolveActiveInstallWorkspace(deps);
50263
50412
  const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
50264
50413
  if (installSuccess) {
@@ -50286,8 +50435,8 @@ var init_background_update_check = __esm(() => {
50286
50435
  init_checker();
50287
50436
  init_update_toasts();
50288
50437
  defaultDeps = {
50289
- existsSync: existsSync20,
50290
- join: join19,
50438
+ existsSync: existsSync22,
50439
+ join: join23,
50291
50440
  runBunInstallWithDetails,
50292
50441
  log,
50293
50442
  getOpenCodeCacheDir,
@@ -50496,9 +50645,9 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
50496
50645
  return;
50497
50646
  hasChecked = true;
50498
50647
  setTimeout(async () => {
50499
- const cachedVersion = getCachedVersion();
50648
+ const cachedVersion2 = getCachedVersion();
50500
50649
  const localDevVersion = getLocalDevVersion(ctx.directory);
50501
- const displayVersion = localDevVersion ?? cachedVersion;
50650
+ const displayVersion = localDevVersion ?? cachedVersion2;
50502
50651
  await showConfigErrorsIfAny(ctx);
50503
50652
  await updateAndShowConnectedProvidersCacheStatus(ctx);
50504
50653
  await refreshModelCapabilitiesOnStartup(modelCapabilities);
@@ -50567,7 +50716,7 @@ var {
50567
50716
  // package.json
50568
50717
  var package_default = {
50569
50718
  name: "evil-omo",
50570
- version: "3.15.2",
50719
+ version: "3.15.3",
50571
50720
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
50572
50721
  main: "./dist/index.js",
50573
50722
  types: "dist/index.d.ts",
@@ -50645,17 +50794,17 @@ var package_default = {
50645
50794
  typescript: "^5.7.3"
50646
50795
  },
50647
50796
  optionalDependencies: {
50648
- "evil-omo-darwin-arm64": "3.15.2",
50649
- "evil-omo-darwin-x64": "3.15.2",
50650
- "evil-omo-darwin-x64-baseline": "3.15.2",
50651
- "evil-omo-linux-x64": "3.15.2",
50652
- "evil-omo-linux-x64-baseline": "3.15.2",
50653
- "evil-omo-linux-arm64": "3.15.2",
50654
- "evil-omo-linux-x64-musl": "3.15.2",
50655
- "evil-omo-linux-x64-musl-baseline": "3.15.2",
50656
- "evil-omo-linux-arm64-musl": "3.15.2",
50657
- "evil-omo-windows-x64": "3.15.2",
50658
- "evil-omo-windows-x64-baseline": "3.15.2"
50797
+ "evil-omo-darwin-arm64": "3.15.3",
50798
+ "evil-omo-darwin-x64": "3.15.3",
50799
+ "evil-omo-darwin-x64-baseline": "3.15.3",
50800
+ "evil-omo-linux-x64": "3.15.3",
50801
+ "evil-omo-linux-x64-baseline": "3.15.3",
50802
+ "evil-omo-linux-arm64": "3.15.3",
50803
+ "evil-omo-linux-x64-musl": "3.15.3",
50804
+ "evil-omo-linux-x64-musl-baseline": "3.15.3",
50805
+ "evil-omo-linux-arm64-musl": "3.15.3",
50806
+ "evil-omo-windows-x64": "3.15.3",
50807
+ "evil-omo-windows-x64-baseline": "3.15.3"
50659
50808
  },
50660
50809
  overrides: {
50661
50810
  "@opencode-ai/sdk": "^1.2.24"
@@ -50668,6 +50817,7 @@ var package_default = {
50668
50817
  };
50669
50818
 
50670
50819
  // src/cli/cli-installer.ts
50820
+ init_shared();
50671
50821
  init_config_manager();
50672
50822
  var import_picocolors2 = __toESM(require_picocolors(), 1);
50673
50823
 
@@ -50826,7 +50976,7 @@ async function runCliInstaller(args, version) {
50826
50976
  console.log(` ${SYMBOLS.bullet} ${err}`);
50827
50977
  }
50828
50978
  console.log();
50829
- printInfo("Usage: bunx evil-omo install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>");
50979
+ printInfo(`Usage: bunx ${PLUGIN_NAME} install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>`);
50830
50980
  console.log();
50831
50981
  return 1;
50832
50982
  }
@@ -50837,7 +50987,7 @@ async function runCliInstaller(args, version) {
50837
50987
  let step = 1;
50838
50988
  printStep(step++, totalSteps, "Checking OpenCode installation...");
50839
50989
  const installed = await isOpenCodeInstalled();
50840
- const openCodeVersion = await getOpenCodeVersion();
50990
+ const openCodeVersion = await getOpenCodeVersion2();
50841
50991
  if (!installed) {
50842
50992
  printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
50843
50993
  printInfo("Visit https://opencode.ai/docs for installation instructions");
@@ -50849,14 +50999,14 @@ async function runCliInstaller(args, version) {
50849
50999
  printInfo(`Current config: Claude=${initial.claude}, Gemini=${initial.gemini}`);
50850
51000
  }
50851
51001
  const config = argsToConfig(args);
50852
- printStep(step++, totalSteps, "Adding evil-omo plugin...");
51002
+ printStep(step++, totalSteps, `Adding ${PLUGIN_NAME} plugin...`);
50853
51003
  const pluginResult = await addPluginToOpenCodeConfig(version);
50854
51004
  if (!pluginResult.success) {
50855
51005
  printError(`Failed: ${pluginResult.error}`);
50856
51006
  return 1;
50857
51007
  }
50858
51008
  printSuccess(`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${import_picocolors2.default.dim(pluginResult.configPath)}`);
50859
- printStep(step++, totalSteps, "Writing evil-omo configuration...");
51009
+ printStep(step++, totalSteps, `Writing ${PLUGIN_NAME} configuration...`);
50860
51010
  const omoResult = writeOmoConfig(config);
50861
51011
  if (!omoResult.success) {
50862
51012
  printError(`Failed: ${omoResult.error}`);
@@ -50884,7 +51034,7 @@ async function runCliInstaller(args, version) {
50884
51034
  console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
50885
51035
  console.log();
50886
51036
  printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
50887
- ` + `All features work like magic\u2014parallel agents, background tasks,
51037
+ ` + `All features work like magic-parallel agents, background tasks,
50888
51038
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
50889
51039
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
50890
51040
  console.log(` ${import_picocolors2.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
@@ -51481,6 +51631,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51481
51631
  };
51482
51632
 
51483
51633
  // src/cli/tui-installer.ts
51634
+ init_shared();
51484
51635
  init_config_manager();
51485
51636
  var import_picocolors4 = __toESM(require_picocolors(), 1);
51486
51637
 
@@ -51611,7 +51762,7 @@ async function runTuiInstaller(args, version) {
51611
51762
  const spinner = Y2();
51612
51763
  spinner.start("Checking OpenCode installation");
51613
51764
  const installed = await isOpenCodeInstalled();
51614
- const openCodeVersion = await getOpenCodeVersion();
51765
+ const openCodeVersion = await getOpenCodeVersion2();
51615
51766
  if (!installed) {
51616
51767
  spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
51617
51768
  M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
@@ -51622,7 +51773,7 @@ async function runTuiInstaller(args, version) {
51622
51773
  const config = await promptInstallConfig(detected);
51623
51774
  if (!config)
51624
51775
  return 1;
51625
- spinner.start("Adding evil-omo to OpenCode config");
51776
+ spinner.start(`Adding ${PLUGIN_NAME} to OpenCode config`);
51626
51777
  const pluginResult = await addPluginToOpenCodeConfig(version);
51627
51778
  if (!pluginResult.success) {
51628
51779
  spinner.stop(`Failed to add plugin: ${pluginResult.error}`);
@@ -51630,7 +51781,7 @@ async function runTuiInstaller(args, version) {
51630
51781
  return 1;
51631
51782
  }
51632
51783
  spinner.stop(`Plugin added to ${import_picocolors4.default.cyan(pluginResult.configPath)}`);
51633
- spinner.start("Writing evil-omo configuration");
51784
+ spinner.start(`Writing ${PLUGIN_NAME} configuration`);
51634
51785
  const omoResult = writeOmoConfig(config);
51635
51786
  if (!omoResult.success) {
51636
51787
  spinner.stop(`Failed to write config: ${omoResult.error}`);
@@ -51658,7 +51809,7 @@ async function runTuiInstaller(args, version) {
51658
51809
  M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51659
51810
  M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
51660
51811
  Me(`Include ${import_picocolors4.default.cyan("ultrawork")} (or ${import_picocolors4.default.cyan("ulw")}) in your prompt.
51661
- ` + `All features work like magic\u2014parallel agents, background tasks,
51812
+ ` + `All features work like magic-parallel agents, background tasks,
51662
51813
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51663
51814
  M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51664
51815
  M2.message(` ${import_picocolors4.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
@@ -66618,7 +66769,7 @@ var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseVa
66618
66769
  if (!response.body)
66619
66770
  throw new Error("No body in SSE response");
66620
66771
  const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
66621
- let buffer = "";
66772
+ let buffer2 = "";
66622
66773
  const abortHandler = () => {
66623
66774
  try {
66624
66775
  reader.cancel();
@@ -66630,11 +66781,11 @@ var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseVa
66630
66781
  const { done, value } = await reader.read();
66631
66782
  if (done)
66632
66783
  break;
66633
- buffer += value;
66634
- const chunks = buffer.split(`
66784
+ buffer2 += value;
66785
+ const chunks = buffer2.split(`
66635
66786
 
66636
66787
  `);
66637
- buffer = chunks.pop() ?? "";
66788
+ buffer2 = chunks.pop() ?? "";
66638
66789
  for (const chunk of chunks) {
66639
66790
  const lines = chunk.split(`
66640
66791
  `);
@@ -68043,7 +68194,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
68043
68194
 
68044
68195
  // src/cli/run/opencode-binary-resolver.ts
68045
68196
  init_spawn_with_windows_hide();
68046
- import { delimiter, dirname, join as join10 } from "path";
68197
+ import { delimiter, dirname, join as join13 } from "path";
68047
68198
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
68048
68199
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
68049
68200
  function getCommandCandidates(platform) {
@@ -68066,7 +68217,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
68066
68217
  }
68067
68218
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
68068
68219
  for (const command of commandCandidates) {
68069
- addCandidate(join10(entry, command));
68220
+ addCandidate(join13(entry, command));
68070
68221
  }
68071
68222
  }
68072
68223
  return candidates;
@@ -68200,7 +68351,6 @@ async function createServerConnection(options) {
68200
68351
 
68201
68352
  // src/cli/run/session-resolver.ts
68202
68353
  var import_picocolors10 = __toESM(require_picocolors(), 1);
68203
- init_plugin_identity();
68204
68354
  var SESSION_CREATE_MAX_RETRIES = 3;
68205
68355
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
68206
68356
  async function resolveSession(options) {
@@ -68218,7 +68368,7 @@ async function resolveSession(options) {
68218
68368
  for (let attempt = 1;attempt <= SESSION_CREATE_MAX_RETRIES; attempt++) {
68219
68369
  const res = await client3.session.create({
68220
68370
  body: {
68221
- title: `${PLUGIN_NAME} run`,
68371
+ title: "evil-omo run",
68222
68372
  permission: [
68223
68373
  { permission: "question", action: "deny", pattern: "*" }
68224
68374
  ]
@@ -68450,15 +68600,15 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68450
68600
  var NOTEPAD_DIR = "notepads";
68451
68601
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68452
68602
  // src/features/boulder-state/storage.ts
68453
- import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3, readdirSync } from "fs";
68454
- import { dirname as dirname2, join as join11, basename } from "path";
68603
+ import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
68604
+ import { dirname as dirname2, join as join14, basename } from "path";
68455
68605
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68456
68606
  function getBoulderFilePath(directory) {
68457
- return join11(directory, BOULDER_DIR, BOULDER_FILE);
68607
+ return join14(directory, BOULDER_DIR, BOULDER_FILE);
68458
68608
  }
68459
68609
  function readBoulderState(directory) {
68460
68610
  const filePath = getBoulderFilePath(directory);
68461
- if (!existsSync11(filePath)) {
68611
+ if (!existsSync13(filePath)) {
68462
68612
  return null;
68463
68613
  }
68464
68614
  try {
@@ -68470,6 +68620,15 @@ function readBoulderState(directory) {
68470
68620
  if (!Array.isArray(parsed.session_ids)) {
68471
68621
  parsed.session_ids = [];
68472
68622
  }
68623
+ if (!parsed.session_origins || typeof parsed.session_origins !== "object" || Array.isArray(parsed.session_origins)) {
68624
+ parsed.session_origins = {};
68625
+ }
68626
+ if (parsed.session_ids.length === 1) {
68627
+ const soleSessionId = parsed.session_ids[0];
68628
+ if (typeof soleSessionId === "string" && parsed.session_origins[soleSessionId] !== "appended" && parsed.session_origins[soleSessionId] !== "direct") {
68629
+ parsed.session_origins[soleSessionId] = "direct";
68630
+ }
68631
+ }
68473
68632
  if (!parsed.task_sessions || typeof parsed.task_sessions !== "object" || Array.isArray(parsed.task_sessions)) {
68474
68633
  parsed.task_sessions = {};
68475
68634
  }
@@ -68479,7 +68638,7 @@ function readBoulderState(directory) {
68479
68638
  }
68480
68639
  }
68481
68640
  function getPlanProgress(planPath) {
68482
- if (!existsSync11(planPath)) {
68641
+ if (!existsSync13(planPath)) {
68483
68642
  return { total: 0, completed: 0, isComplete: true };
68484
68643
  }
68485
68644
  try {
@@ -68497,17 +68656,26 @@ function getPlanProgress(planPath) {
68497
68656
  return { total: 0, completed: 0, isComplete: true };
68498
68657
  }
68499
68658
  }
68659
+ // src/features/claude-code-session-state/state.ts
68660
+ init_agent_display_names();
68661
+ var subagentSessions = new Set;
68662
+ var syncSubagentSessions = new Set;
68663
+ var registeredAgentNames = new Set;
68664
+ var sessionAgentMap = new Map;
68665
+ function getSessionAgent(sessionID) {
68666
+ return sessionAgentMap.get(sessionID);
68667
+ }
68500
68668
  // src/features/run-continuation-state/constants.ts
68501
68669
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68502
68670
  // src/features/run-continuation-state/storage.ts
68503
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync6 } from "fs";
68504
- import { join as join12 } from "path";
68671
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync6 } from "fs";
68672
+ import { join as join15 } from "path";
68505
68673
  function getMarkerPath(directory, sessionID) {
68506
- return join12(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68674
+ return join15(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68507
68675
  }
68508
68676
  function readContinuationMarker(directory, sessionID) {
68509
68677
  const markerPath = getMarkerPath(directory, sessionID);
68510
- if (!existsSync12(markerPath))
68678
+ if (!existsSync14(markerPath))
68511
68679
  return null;
68512
68680
  try {
68513
68681
  const raw = readFileSync10(markerPath, "utf-8");
@@ -68533,10 +68701,113 @@ function getActiveContinuationMarkerReason(marker) {
68533
68701
  const [source, entry] = active;
68534
68702
  return entry.reason ?? `${source} continuation is active`;
68535
68703
  }
68704
+ // src/hooks/atlas/boulder-session-lineage.ts
68705
+ init_logger();
68706
+
68707
+ // src/hooks/atlas/hook-name.ts
68708
+ var HOOK_NAME = "atlas";
68709
+
68710
+ // src/hooks/atlas/boulder-session-lineage.ts
68711
+ async function isSessionInBoulderLineage(input) {
68712
+ const visitedSessionIDs = new Set;
68713
+ let currentSessionID = input.sessionID;
68714
+ while (!visitedSessionIDs.has(currentSessionID)) {
68715
+ visitedSessionIDs.add(currentSessionID);
68716
+ const sessionResult = await input.client.session.get({ path: { id: currentSessionID } }).catch((error48) => {
68717
+ log(`[${HOOK_NAME}] Failed to resolve session lineage`, {
68718
+ sessionID: input.sessionID,
68719
+ currentSessionID,
68720
+ error: error48
68721
+ });
68722
+ return null;
68723
+ });
68724
+ if (!sessionResult || sessionResult.error) {
68725
+ return false;
68726
+ }
68727
+ const parentSessionID = sessionResult.data?.parentID;
68728
+ if (!parentSessionID) {
68729
+ return false;
68730
+ }
68731
+ if (input.boulderSessionIDs.includes(parentSessionID)) {
68732
+ return true;
68733
+ }
68734
+ currentSessionID = parentSessionID;
68735
+ }
68736
+ return false;
68737
+ }
68738
+
68739
+ // src/hooks/atlas/session-last-agent.ts
68740
+ init_shared();
68741
+ import { readFileSync as readFileSync11, readdirSync as readdirSync3 } from "fs";
68742
+ import { join as join16 } from "path";
68743
+ function isCompactionAgent(agent) {
68744
+ return typeof agent === "string" && agent.toLowerCase() === "compaction";
68745
+ }
68746
+ function getLastAgentFromMessageDir(messageDir) {
68747
+ try {
68748
+ const messages = readdirSync3(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
68749
+ try {
68750
+ const content = readFileSync11(join16(messageDir, fileName), "utf-8");
68751
+ const parsed = JSON.parse(content);
68752
+ return {
68753
+ fileName,
68754
+ agent: parsed.agent,
68755
+ createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
68756
+ };
68757
+ } catch {
68758
+ return null;
68759
+ }
68760
+ }).filter((message) => message !== null).sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName));
68761
+ for (const message of messages) {
68762
+ if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
68763
+ return message.agent.toLowerCase();
68764
+ }
68765
+ }
68766
+ } catch {
68767
+ return null;
68768
+ }
68769
+ return null;
68770
+ }
68771
+ async function getLastAgentFromSession(sessionID, client3) {
68772
+ if (isSqliteBackend() && client3) {
68773
+ try {
68774
+ const response = await client3.session.messages({ path: { id: sessionID } });
68775
+ const messages = normalizeSDKResponse(response, [], {
68776
+ preferResponseOnMissingData: true
68777
+ }).sort((left, right) => {
68778
+ const leftTime = left.info?.time?.created ?? Number.NEGATIVE_INFINITY;
68779
+ const rightTime = right.info?.time?.created ?? Number.NEGATIVE_INFINITY;
68780
+ if (leftTime !== rightTime) {
68781
+ return rightTime - leftTime;
68782
+ }
68783
+ const leftId = typeof left.id === "string" ? left.id : "";
68784
+ const rightId = typeof right.id === "string" ? right.id : "";
68785
+ return rightId.localeCompare(leftId);
68786
+ });
68787
+ for (const message of messages) {
68788
+ const agent = message.info?.agent;
68789
+ if (typeof agent === "string" && !isCompactionAgent(agent)) {
68790
+ return agent.toLowerCase();
68791
+ }
68792
+ }
68793
+ } catch {
68794
+ return null;
68795
+ }
68796
+ return null;
68797
+ }
68798
+ const messageDir = getMessageDir(sessionID);
68799
+ if (!messageDir)
68800
+ return null;
68801
+ return getLastAgentFromMessageDir(messageDir);
68802
+ }
68803
+
68804
+ // src/cli/run/continuation-state.ts
68805
+ init_agent_display_names();
68806
+
68536
68807
  // src/hooks/ralph-loop/storage.ts
68537
68808
  init_frontmatter();
68538
- import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync5 } from "fs";
68539
- import { dirname as dirname3, join as join13 } from "path";
68809
+ import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
68810
+ import { dirname as dirname3, join as join17 } from "path";
68540
68811
 
68541
68812
  // src/hooks/ralph-loop/constants.ts
68542
68813
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -68545,15 +68816,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
68545
68816
 
68546
68817
  // src/hooks/ralph-loop/storage.ts
68547
68818
  function getStateFilePath(directory, customPath) {
68548
- return customPath ? join13(directory, customPath) : join13(directory, DEFAULT_STATE_FILE);
68819
+ return customPath ? join17(directory, customPath) : join17(directory, DEFAULT_STATE_FILE);
68549
68820
  }
68550
68821
  function readState(directory, customPath) {
68551
68822
  const filePath = getStateFilePath(directory, customPath);
68552
- if (!existsSync13(filePath)) {
68823
+ if (!existsSync15(filePath)) {
68553
68824
  return null;
68554
68825
  }
68555
68826
  try {
68556
- const content = readFileSync11(filePath, "utf-8");
68827
+ const content = readFileSync12(filePath, "utf-8");
68557
68828
  const { data, body } = parseFrontmatter(content);
68558
68829
  const active = data.active;
68559
68830
  const iteration = data.iteration;
@@ -68593,10 +68864,10 @@ function readState(directory, customPath) {
68593
68864
  }
68594
68865
 
68595
68866
  // src/cli/run/continuation-state.ts
68596
- function getContinuationState(directory, sessionID) {
68867
+ async function getContinuationState(directory, sessionID, client3) {
68597
68868
  const marker = readContinuationMarker(directory, sessionID);
68598
68869
  return {
68599
- hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
68870
+ hasActiveBoulder: await hasActiveBoulderContinuation(directory, sessionID, client3),
68600
68871
  hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
68601
68872
  hasHookMarker: marker !== null,
68602
68873
  hasTodoHookMarker: marker?.sources.todo !== undefined,
@@ -68604,20 +68875,54 @@ function getContinuationState(directory, sessionID) {
68604
68875
  activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
68605
68876
  };
68606
68877
  }
68607
- function hasActiveBoulderContinuation(directory, sessionID) {
68878
+ async function hasActiveBoulderContinuation(directory, sessionID, client3) {
68608
68879
  const boulder = readBoulderState(directory);
68609
68880
  if (!boulder)
68610
68881
  return false;
68611
- if (!boulder.session_ids.includes(sessionID))
68612
- return false;
68613
68882
  const progress = getPlanProgress(boulder.active_plan);
68614
- return !progress.isComplete;
68883
+ if (progress.isComplete)
68884
+ return false;
68885
+ if (!client3)
68886
+ return false;
68887
+ const isTrackedSession = boulder.session_ids.includes(sessionID);
68888
+ const sessionOrigin = boulder.session_origins?.[sessionID];
68889
+ if (!isTrackedSession) {
68890
+ return false;
68891
+ }
68892
+ const isTrackedDescendant = await isTrackedDescendantSession(client3, sessionID, boulder.session_ids);
68893
+ if (isTrackedSession && sessionOrigin === "direct") {
68894
+ return true;
68895
+ }
68896
+ if (isTrackedSession && sessionOrigin !== "direct" && !isTrackedDescendant) {
68897
+ return false;
68898
+ }
68899
+ const sessionAgent = await getLastAgentFromSession(sessionID, client3) ?? getSessionAgent(sessionID);
68900
+ if (!sessionAgent) {
68901
+ return false;
68902
+ }
68903
+ const requiredAgentKey = getAgentConfigKey(boulder.agent ?? "atlas");
68904
+ const sessionAgentKey = getAgentConfigKey(sessionAgent);
68905
+ if (sessionAgentKey !== requiredAgentKey && !(requiredAgentKey === getAgentConfigKey("atlas") && sessionAgentKey === getAgentConfigKey("sisyphus"))) {
68906
+ return false;
68907
+ }
68908
+ return isTrackedSession || isTrackedDescendant;
68909
+ }
68910
+ async function isTrackedDescendantSession(client3, sessionID, trackedSessionIDs) {
68911
+ const ancestorSessionIDs = trackedSessionIDs.filter((trackedSessionID) => trackedSessionID !== sessionID);
68912
+ if (ancestorSessionIDs.length === 0) {
68913
+ return false;
68914
+ }
68915
+ return isSessionInBoulderLineage({
68916
+ client: client3,
68917
+ sessionID,
68918
+ boulderSessionIDs: ancestorSessionIDs
68919
+ });
68615
68920
  }
68616
68921
  function hasActiveRalphLoopContinuation(directory, sessionID) {
68617
- const state = readState(directory);
68618
- if (!state || !state.active)
68922
+ const state2 = readState(directory);
68923
+ if (!state2 || !state2.active)
68619
68924
  return false;
68620
- if (state.session_id && state.session_id !== sessionID) {
68925
+ if (state2.session_id && state2.session_id !== sessionID) {
68621
68926
  return false;
68622
68927
  }
68623
68928
  return true;
@@ -68626,7 +68931,7 @@ function hasActiveRalphLoopContinuation(directory, sessionID) {
68626
68931
  // src/cli/run/completion.ts
68627
68932
  async function checkCompletionConditions(ctx) {
68628
68933
  try {
68629
- const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
68934
+ const continuationState = await getContinuationState(ctx.directory, ctx.sessionID, ctx.client);
68630
68935
  if (continuationState.hasActiveHookMarker) {
68631
68936
  const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
68632
68937
  logWaiting(ctx, reason);
@@ -69221,7 +69526,7 @@ async function getLocalVersion(options = {}) {
69221
69526
  }
69222
69527
  }
69223
69528
  // src/cli/doctor/constants.ts
69224
- init_plugin_identity();
69529
+ init_shared();
69225
69530
  var import_picocolors16 = __toESM(require_picocolors(), 1);
69226
69531
  var SYMBOLS3 = {
69227
69532
  check: import_picocolors16.default.green("\u2713"),
@@ -69255,34 +69560,34 @@ var EXIT_CODES = {
69255
69560
  FAILURE: 1
69256
69561
  };
69257
69562
  var MIN_OPENCODE_VERSION = "1.0.150";
69258
- var PACKAGE_NAME3 = PLUGIN_NAME;
69563
+ var PACKAGE_NAME2 = PLUGIN_NAME;
69259
69564
  var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
69260
69565
 
69261
69566
  // src/cli/doctor/checks/system.ts
69262
- import { existsSync as existsSync24, readFileSync as readFileSync21 } from "fs";
69567
+ import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
69263
69568
 
69264
69569
  // src/cli/doctor/checks/system-binary.ts
69265
69570
  init_spawn_with_windows_hide();
69266
- import { existsSync as existsSync21 } from "fs";
69571
+ import { existsSync as existsSync23 } from "fs";
69267
69572
  import { homedir as homedir5 } from "os";
69268
- import { join as join20 } from "path";
69573
+ import { join as join24 } from "path";
69269
69574
  function getDesktopAppPaths(platform) {
69270
69575
  const home = homedir5();
69271
69576
  switch (platform) {
69272
69577
  case "darwin":
69273
69578
  return [
69274
69579
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
69275
- join20(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69580
+ join24(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69276
69581
  ];
69277
69582
  case "win32": {
69278
69583
  const programFiles = process.env.ProgramFiles;
69279
69584
  const localAppData = process.env.LOCALAPPDATA;
69280
69585
  const paths = [];
69281
69586
  if (programFiles) {
69282
- paths.push(join20(programFiles, "OpenCode", "OpenCode.exe"));
69587
+ paths.push(join24(programFiles, "OpenCode", "OpenCode.exe"));
69283
69588
  }
69284
69589
  if (localAppData) {
69285
- paths.push(join20(localAppData, "OpenCode", "OpenCode.exe"));
69590
+ paths.push(join24(localAppData, "OpenCode", "OpenCode.exe"));
69286
69591
  }
69287
69592
  return paths;
69288
69593
  }
@@ -69290,8 +69595,8 @@ function getDesktopAppPaths(platform) {
69290
69595
  return [
69291
69596
  "/usr/bin/opencode",
69292
69597
  "/usr/lib/opencode/opencode",
69293
- join20(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69294
- join20(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69598
+ join24(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69599
+ join24(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69295
69600
  ];
69296
69601
  default:
69297
69602
  return [];
@@ -69303,7 +69608,7 @@ function buildVersionCommand(binaryPath, platform) {
69303
69608
  }
69304
69609
  return [binaryPath, "--version"];
69305
69610
  }
69306
- function findDesktopBinary(platform = process.platform, checkExists = existsSync21) {
69611
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync23) {
69307
69612
  for (const desktopPath of getDesktopAppPaths(platform)) {
69308
69613
  if (checkExists(desktopPath)) {
69309
69614
  return { binary: "opencode", path: desktopPath };
@@ -69320,7 +69625,7 @@ async function findOpenCodeBinary() {
69320
69625
  }
69321
69626
  return findDesktopBinary();
69322
69627
  }
69323
- async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
69628
+ async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
69324
69629
  try {
69325
69630
  const command = buildVersionCommand(binaryPath, platform);
69326
69631
  const processResult = spawnWithWindowsHide(command, { stdout: "pipe", stderr: "pipe" });
@@ -69333,10 +69638,10 @@ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
69333
69638
  return null;
69334
69639
  }
69335
69640
  }
69336
- function compareVersions(current, minimum) {
69337
- const parseVersion = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
69338
- const currentParts = parseVersion(current);
69339
- const minimumParts = parseVersion(minimum);
69641
+ function compareVersions2(current, minimum) {
69642
+ const parseVersion2 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
69643
+ const currentParts = parseVersion2(current);
69644
+ const minimumParts = parseVersion2(minimum);
69340
69645
  const length = Math.max(currentParts.length, minimumParts.length);
69341
69646
  for (let index = 0;index < length; index++) {
69342
69647
  const currentPart = currentParts[index] ?? 0;
@@ -69351,12 +69656,12 @@ function compareVersions(current, minimum) {
69351
69656
 
69352
69657
  // src/cli/doctor/checks/system-plugin.ts
69353
69658
  init_shared();
69354
- import { existsSync as existsSync22, readFileSync as readFileSync19 } from "fs";
69659
+ import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
69355
69660
  function detectConfigPath() {
69356
69661
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
69357
- if (existsSync22(paths.configJsonc))
69662
+ if (existsSync24(paths.configJsonc))
69358
69663
  return paths.configJsonc;
69359
- if (existsSync22(paths.configJson))
69664
+ if (existsSync24(paths.configJson))
69360
69665
  return paths.configJson;
69361
69666
  return null;
69362
69667
  }
@@ -69402,7 +69707,7 @@ function getPluginInfo() {
69402
69707
  };
69403
69708
  }
69404
69709
  try {
69405
- const content = readFileSync19(configPath, "utf-8");
69710
+ const content = readFileSync20(configPath, "utf-8");
69406
69711
  const parsedConfig = parseJsonc(content);
69407
69712
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
69408
69713
  if (!pluginEntry) {
@@ -69440,37 +69745,37 @@ function getPluginInfo() {
69440
69745
  init_file_utils();
69441
69746
  init_checker();
69442
69747
  init_auto_update_checker();
69443
- import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
69748
+ import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
69444
69749
  import { homedir as homedir6 } from "os";
69445
- import { join as join21 } from "path";
69750
+ import { join as join25 } from "path";
69446
69751
  init_shared();
69447
69752
  function getPlatformDefaultCacheDir(platform = process.platform) {
69448
69753
  if (platform === "darwin")
69449
- return join21(homedir6(), "Library", "Caches");
69754
+ return join25(homedir6(), "Library", "Caches");
69450
69755
  if (platform === "win32")
69451
- return process.env.LOCALAPPDATA ?? join21(homedir6(), "AppData", "Local");
69452
- return join21(homedir6(), ".cache");
69756
+ return process.env.LOCALAPPDATA ?? join25(homedir6(), "AppData", "Local");
69757
+ return join25(homedir6(), ".cache");
69453
69758
  }
69454
69759
  function resolveOpenCodeCacheDir() {
69455
69760
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
69456
69761
  if (xdgCacheHome)
69457
- return join21(xdgCacheHome, "opencode");
69762
+ return join25(xdgCacheHome, "opencode");
69458
69763
  const fromShared = getOpenCodeCacheDir();
69459
- const platformDefault = join21(getPlatformDefaultCacheDir(), "opencode");
69460
- if (existsSync23(fromShared) || !existsSync23(platformDefault))
69764
+ const platformDefault = join25(getPlatformDefaultCacheDir(), "opencode");
69765
+ if (existsSync25(fromShared) || !existsSync25(platformDefault))
69461
69766
  return fromShared;
69462
69767
  return platformDefault;
69463
69768
  }
69464
69769
  function resolveExistingDir(dirPath) {
69465
- if (!existsSync23(dirPath))
69770
+ if (!existsSync25(dirPath))
69466
69771
  return dirPath;
69467
69772
  return resolveSymlink(dirPath);
69468
69773
  }
69469
69774
  function readPackageJson(filePath) {
69470
- if (!existsSync23(filePath))
69775
+ if (!existsSync25(filePath))
69471
69776
  return null;
69472
69777
  try {
69473
- const content = readFileSync20(filePath, "utf-8");
69778
+ const content = readFileSync21(filePath, "utf-8");
69474
69779
  return parseJsonc(content);
69475
69780
  } catch {
69476
69781
  return null;
@@ -69489,20 +69794,20 @@ function getLoadedPluginVersion() {
69489
69794
  const candidates = [
69490
69795
  {
69491
69796
  cacheDir: configDir,
69492
- cachePackagePath: join21(configDir, "package.json"),
69493
- installedPackagePath: join21(configDir, "node_modules", PACKAGE_NAME3, "package.json")
69797
+ cachePackagePath: join25(configDir, "package.json"),
69798
+ installedPackagePath: join25(configDir, "node_modules", PACKAGE_NAME2, "package.json")
69494
69799
  },
69495
69800
  {
69496
69801
  cacheDir,
69497
- cachePackagePath: join21(cacheDir, "package.json"),
69498
- installedPackagePath: join21(cacheDir, "node_modules", PACKAGE_NAME3, "package.json")
69802
+ cachePackagePath: join25(cacheDir, "package.json"),
69803
+ installedPackagePath: join25(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
69499
69804
  }
69500
69805
  ];
69501
- const selectedCandidate = candidates.find((candidate) => existsSync23(candidate.installedPackagePath)) ?? candidates[0];
69806
+ const selectedCandidate = candidates.find((candidate) => existsSync25(candidate.installedPackagePath)) ?? candidates[0];
69502
69807
  const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
69503
69808
  const cachePackage = readPackageJson(cachePackagePath);
69504
69809
  const installedPackage = readPackageJson(installedPackagePath);
69505
- const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME3]);
69810
+ const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME2]);
69506
69811
  const loadedVersion = normalizeVersion(installedPackage?.version);
69507
69812
  return {
69508
69813
  cacheDir: selectedDir,
@@ -69522,13 +69827,14 @@ function getSuggestedInstallTag(currentVersion) {
69522
69827
 
69523
69828
  // src/cli/doctor/checks/system.ts
69524
69829
  init_shared();
69830
+ init_plugin_identity();
69525
69831
  function isConfigValid(configPath) {
69526
69832
  if (!configPath)
69527
69833
  return true;
69528
- if (!existsSync24(configPath))
69834
+ if (!existsSync26(configPath))
69529
69835
  return false;
69530
69836
  try {
69531
- parseJsonc(readFileSync21(configPath, "utf-8"));
69837
+ parseJsonc(readFileSync22(configPath, "utf-8"));
69532
69838
  return true;
69533
69839
  } catch {
69534
69840
  return false;
@@ -69551,7 +69857,7 @@ function buildMessage(status, issues) {
69551
69857
  async function gatherSystemInfo() {
69552
69858
  const [binaryInfo, pluginInfo] = await Promise.all([findOpenCodeBinary(), Promise.resolve(getPluginInfo())]);
69553
69859
  const loadedInfo = getLoadedPluginVersion();
69554
- const opencodeVersion = binaryInfo ? await getOpenCodeVersion2(binaryInfo.path) : null;
69860
+ const opencodeVersion = binaryInfo ? await getOpenCodeVersion3(binaryInfo.path) : null;
69555
69861
  const pluginVersion = pluginInfo.pinnedVersion ?? loadedInfo.expectedVersion ?? loadedInfo.loadedVersion;
69556
69862
  return {
69557
69863
  opencodeVersion,
@@ -69579,7 +69885,7 @@ async function checkSystem() {
69579
69885
  affects: ["doctor", "run"]
69580
69886
  });
69581
69887
  }
69582
- if (systemInfo.opencodeVersion && !compareVersions(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69888
+ if (systemInfo.opencodeVersion && !compareVersions2(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69583
69889
  issues.push({
69584
69890
  title: "OpenCode version below minimum",
69585
69891
  description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
@@ -69590,13 +69896,26 @@ async function checkSystem() {
69590
69896
  }
69591
69897
  if (!pluginInfo.registered) {
69592
69898
  issues.push({
69593
- title: `${PACKAGE_NAME3} is not registered`,
69899
+ title: `${PLUGIN_NAME} is not registered`,
69594
69900
  description: "Plugin entry is missing from OpenCode configuration.",
69595
- fix: `Run: bunx ${PACKAGE_NAME3} install`,
69901
+ fix: `Run: bunx ${PLUGIN_NAME} install`,
69596
69902
  severity: "error",
69597
69903
  affects: ["all agents"]
69598
69904
  });
69599
69905
  }
69906
+ if (pluginInfo.entry && !pluginInfo.isLocalDev) {
69907
+ const isLegacyName = pluginInfo.entry === LEGACY_PLUGIN_NAME || pluginInfo.entry.startsWith(`${LEGACY_PLUGIN_NAME}@`);
69908
+ if (isLegacyName) {
69909
+ const suggestedEntry = pluginInfo.entry.replace(LEGACY_PLUGIN_NAME, PLUGIN_NAME);
69910
+ issues.push({
69911
+ title: "Using legacy package name",
69912
+ description: `Your opencode.json references "${LEGACY_PLUGIN_NAME}" which has been renamed to "${PLUGIN_NAME}". The old name may stop working in a future release.`,
69913
+ fix: `Update your opencode.json plugin entry: "${pluginInfo.entry}" \u2192 "${suggestedEntry}"`,
69914
+ severity: "warning",
69915
+ affects: ["plugin loading"]
69916
+ });
69917
+ }
69918
+ }
69600
69919
  if (loadedInfo.expectedVersion && loadedInfo.loadedVersion && loadedInfo.expectedVersion !== loadedInfo.loadedVersion) {
69601
69920
  issues.push({
69602
69921
  title: "Loaded plugin version mismatch",
@@ -69606,11 +69925,11 @@ async function checkSystem() {
69606
69925
  affects: ["plugin loading"]
69607
69926
  });
69608
69927
  }
69609
- if (systemInfo.loadedVersion && latestVersion && !compareVersions(systemInfo.loadedVersion, latestVersion)) {
69928
+ if (systemInfo.loadedVersion && latestVersion && !compareVersions2(systemInfo.loadedVersion, latestVersion)) {
69610
69929
  issues.push({
69611
69930
  title: "Loaded plugin is outdated",
69612
69931
  description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
69613
- fix: `Update: cd "${loadedInfo.cacheDir}" && bun add ${PACKAGE_NAME3}@${installTag}`,
69932
+ fix: `Update: cd "${loadedInfo.cacheDir}" && bun add ${PLUGIN_NAME}@${installTag}`,
69614
69933
  severity: "warning",
69615
69934
  affects: ["plugin features"]
69616
69935
  });
@@ -69631,29 +69950,28 @@ async function checkSystem() {
69631
69950
  }
69632
69951
 
69633
69952
  // src/cli/doctor/checks/config.ts
69634
- import { readFileSync as readFileSync24 } from "fs";
69635
- import { join as join25 } from "path";
69953
+ import { readFileSync as readFileSync25 } from "fs";
69954
+ import { join as join29 } from "path";
69636
69955
  init_shared();
69637
- init_plugin_identity();
69638
69956
 
69639
69957
  // src/cli/doctor/checks/model-resolution-cache.ts
69640
69958
  init_shared();
69641
- import { existsSync as existsSync25, readFileSync as readFileSync22 } from "fs";
69959
+ import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
69642
69960
  import { homedir as homedir7 } from "os";
69643
- import { join as join22 } from "path";
69961
+ import { join as join26 } from "path";
69644
69962
  function getOpenCodeCacheDir2() {
69645
69963
  const xdgCache = process.env.XDG_CACHE_HOME;
69646
69964
  if (xdgCache)
69647
- return join22(xdgCache, "opencode");
69648
- return join22(homedir7(), ".cache", "opencode");
69965
+ return join26(xdgCache, "opencode");
69966
+ return join26(homedir7(), ".cache", "opencode");
69649
69967
  }
69650
69968
  function loadAvailableModelsFromCache() {
69651
- const cacheFile = join22(getOpenCodeCacheDir2(), "models.json");
69652
- if (!existsSync25(cacheFile)) {
69969
+ const cacheFile = join26(getOpenCodeCacheDir2(), "models.json");
69970
+ if (!existsSync27(cacheFile)) {
69653
69971
  return { providers: [], modelCount: 0, cacheExists: false };
69654
69972
  }
69655
69973
  try {
69656
- const content = readFileSync22(cacheFile, "utf-8");
69974
+ const content = readFileSync23(cacheFile, "utf-8");
69657
69975
  const data = parseJsonc(content);
69658
69976
  const providers = Object.keys(data);
69659
69977
  let modelCount = 0;
@@ -69675,25 +69993,24 @@ init_model_capabilities();
69675
69993
 
69676
69994
  // src/cli/doctor/checks/model-resolution-config.ts
69677
69995
  init_shared();
69678
- init_plugin_identity();
69679
- import { readFileSync as readFileSync23 } from "fs";
69680
- import { join as join23 } from "path";
69681
- var USER_CONFIG_DIR2 = getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir;
69682
- var PROJECT_CONFIG_DIR = join23(process.cwd(), ".opencode");
69996
+ import { readFileSync as readFileSync24 } from "fs";
69997
+ import { join as join27 } from "path";
69998
+ var PROJECT_CONFIG_DIR = join27(process.cwd(), ".opencode");
69683
69999
  function loadOmoConfig() {
69684
- const projectDetected = detectManagedConfigFile(PROJECT_CONFIG_DIR);
70000
+ const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
69685
70001
  if (projectDetected.format !== "none") {
69686
70002
  try {
69687
- const content = readFileSync23(projectDetected.path, "utf-8");
70003
+ const content = readFileSync24(projectDetected.path, "utf-8");
69688
70004
  return parseJsonc(content);
69689
70005
  } catch {
69690
70006
  return null;
69691
70007
  }
69692
70008
  }
69693
- const userDetected = detectManagedConfigFile(USER_CONFIG_DIR2);
70009
+ const userConfigDir = getOpenCodeConfigDir({ binary: "opencode" });
70010
+ const userDetected = detectPluginConfigFile(userConfigDir);
69694
70011
  if (userDetected.format !== "none") {
69695
70012
  try {
69696
- const content = readFileSync23(userDetected.path, "utf-8");
70013
+ const content = readFileSync24(userDetected.path, "utf-8");
69697
70014
  return parseJsonc(content);
69698
70015
  } catch {
69699
70016
  return null;
@@ -69704,7 +70021,7 @@ function loadOmoConfig() {
69704
70021
 
69705
70022
  // src/cli/doctor/checks/model-resolution-details.ts
69706
70023
  init_shared();
69707
- import { join as join24 } from "path";
70024
+ import { join as join28 } from "path";
69708
70025
 
69709
70026
  // src/cli/doctor/checks/model-resolution-variant.ts
69710
70027
  function formatModelWithVariant(model, variant) {
@@ -69746,7 +70063,7 @@ function formatCapabilityResolutionLabel(mode) {
69746
70063
  }
69747
70064
  function buildModelResolutionDetails(options) {
69748
70065
  const details = [];
69749
- const cacheFile = join24(getOpenCodeCacheDir(), "models.json");
70066
+ const cacheFile = join28(getOpenCodeCacheDir(), "models.json");
69750
70067
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
69751
70068
  details.push("");
69752
70069
  if (options.available.cacheExists) {
@@ -69901,11 +70218,13 @@ async function checkModels() {
69901
70218
  }
69902
70219
 
69903
70220
  // src/cli/doctor/checks/config.ts
70221
+ var PROJECT_CONFIG_DIR2 = join29(process.cwd(), ".opencode");
69904
70222
  function findConfigPath() {
69905
- const projectConfig = detectManagedConfigFile(join25(process.cwd(), ".opencode"));
70223
+ const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
69906
70224
  if (projectConfig.format !== "none")
69907
70225
  return projectConfig.path;
69908
- const userConfig = detectManagedConfigFile(getOpenCodeConfigDir({ binary: "opencode" }));
70226
+ const userConfigDir = getOpenCodeConfigDir({ binary: "opencode" });
70227
+ const userConfig = detectPluginConfigFile(userConfigDir);
69909
70228
  if (userConfig.format !== "none")
69910
70229
  return userConfig.path;
69911
70230
  return null;
@@ -69916,7 +70235,7 @@ function validateConfig() {
69916
70235
  return { exists: false, path: null, valid: true, config: null, errors: [] };
69917
70236
  }
69918
70237
  try {
69919
- const content = readFileSync24(configPath, "utf-8");
70238
+ const content = readFileSync25(configPath, "utf-8");
69920
70239
  const rawConfig = parseJsonc(content);
69921
70240
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
69922
70241
  if (!schemaResult.success) {
@@ -70020,9 +70339,9 @@ async function checkConfig() {
70020
70339
 
70021
70340
  // src/cli/doctor/checks/dependencies.ts
70022
70341
  init_spawn_with_windows_hide();
70023
- import { existsSync as existsSync26 } from "fs";
70342
+ import { existsSync as existsSync28 } from "fs";
70024
70343
  import { createRequire } from "module";
70025
- import { dirname as dirname7, join as join26 } from "path";
70344
+ import { dirname as dirname7, join as join30 } from "path";
70026
70345
  async function checkBinaryExists(binary2) {
70027
70346
  try {
70028
70347
  const path10 = Bun.which(binary2);
@@ -70078,15 +70397,15 @@ async function checkAstGrepNapi() {
70078
70397
  path: null
70079
70398
  };
70080
70399
  } catch {
70081
- const { existsSync: existsSync27 } = await import("fs");
70082
- const { join: join27 } = await import("path");
70400
+ const { existsSync: existsSync29 } = await import("fs");
70401
+ const { join: join31 } = await import("path");
70083
70402
  const { homedir: homedir8 } = await import("os");
70084
70403
  const pathsToCheck = [
70085
- join27(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70086
- join27(process.cwd(), "node_modules", "@ast-grep", "napi")
70404
+ join31(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70405
+ join31(process.cwd(), "node_modules", "@ast-grep", "napi")
70087
70406
  ];
70088
70407
  for (const napiPath of pathsToCheck) {
70089
- if (existsSync27(napiPath)) {
70408
+ if (existsSync29(napiPath)) {
70090
70409
  return {
70091
70410
  name: "AST-Grep NAPI",
70092
70411
  required: false,
@@ -70111,8 +70430,8 @@ function findCommentCheckerPackageBinary() {
70111
70430
  try {
70112
70431
  const require2 = createRequire(import.meta.url);
70113
70432
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
70114
- const binaryPath = join26(dirname7(pkgPath), "bin", binaryName);
70115
- if (existsSync26(binaryPath))
70433
+ const binaryPath = join30(dirname7(pkgPath), "bin", binaryName);
70434
+ if (existsSync28(binaryPath))
70116
70435
  return binaryPath;
70117
70436
  } catch {}
70118
70437
  return null;
@@ -70269,16 +70588,15 @@ var BUILTIN_SERVERS = {
70269
70588
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
70270
70589
  };
70271
70590
  // src/tools/lsp/server-config-loader.ts
70272
- import { existsSync as existsSync27, readFileSync as readFileSync25 } from "fs";
70273
- import { join as join27 } from "path";
70591
+ import { existsSync as existsSync29, readFileSync as readFileSync26 } from "fs";
70592
+ import { join as join31 } from "path";
70274
70593
  init_shared();
70275
70594
  init_jsonc_parser();
70276
- init_plugin_identity();
70277
70595
  function loadJsonFile(path10) {
70278
- if (!existsSync27(path10))
70596
+ if (!existsSync29(path10))
70279
70597
  return null;
70280
70598
  try {
70281
- return parseJsonc(readFileSync25(path10, "utf-8"));
70599
+ return parseJsonc(readFileSync26(path10, "utf-8"));
70282
70600
  } catch {
70283
70601
  return null;
70284
70602
  }
@@ -70287,9 +70605,9 @@ function getConfigPaths2() {
70287
70605
  const cwd = process.cwd();
70288
70606
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70289
70607
  return {
70290
- project: detectManagedConfigFile(join27(cwd, ".opencode")).path,
70291
- user: detectManagedConfigFile(configDir).path,
70292
- opencode: detectConfigFile(join27(configDir, "opencode")).path
70608
+ project: detectPluginConfigFile(join31(cwd, ".opencode")).path,
70609
+ user: detectPluginConfigFile(configDir).path,
70610
+ opencode: detectConfigFile(join31(configDir, "opencode")).path
70293
70611
  };
70294
70612
  }
70295
70613
  function loadAllConfigs() {
@@ -70358,21 +70676,21 @@ function getMergedServers() {
70358
70676
  }
70359
70677
 
70360
70678
  // src/tools/lsp/server-installation.ts
70361
- import { existsSync as existsSync28 } from "fs";
70362
- import { delimiter as delimiter2, join as join29 } from "path";
70679
+ import { existsSync as existsSync30 } from "fs";
70680
+ import { delimiter as delimiter2, join as join33 } from "path";
70363
70681
 
70364
70682
  // src/tools/lsp/server-path-bases.ts
70365
70683
  init_shared();
70366
- import { join as join28 } from "path";
70684
+ import { join as join32 } from "path";
70367
70685
  function getLspServerAdditionalPathBases(workingDirectory) {
70368
70686
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70369
- const dataDir = join28(getDataDir(), "opencode");
70687
+ const dataDir = join32(getDataDir(), "opencode");
70370
70688
  return [
70371
- join28(workingDirectory, "node_modules", ".bin"),
70372
- join28(configDir, "bin"),
70373
- join28(configDir, "node_modules", ".bin"),
70374
- join28(dataDir, "bin"),
70375
- join28(dataDir, "bin", "node_modules", ".bin")
70689
+ join32(workingDirectory, "node_modules", ".bin"),
70690
+ join32(configDir, "bin"),
70691
+ join32(configDir, "node_modules", ".bin"),
70692
+ join32(dataDir, "bin"),
70693
+ join32(dataDir, "bin", "node_modules", ".bin")
70376
70694
  ];
70377
70695
  }
70378
70696
 
@@ -70382,7 +70700,7 @@ function isServerInstalled(command) {
70382
70700
  return false;
70383
70701
  const cmd = command[0];
70384
70702
  if (cmd.includes("/") || cmd.includes("\\")) {
70385
- if (existsSync28(cmd))
70703
+ if (existsSync30(cmd))
70386
70704
  return true;
70387
70705
  }
70388
70706
  const isWindows = process.platform === "win32";
@@ -70403,14 +70721,14 @@ function isServerInstalled(command) {
70403
70721
  const paths = pathEnv.split(delimiter2);
70404
70722
  for (const p2 of paths) {
70405
70723
  for (const suffix of exts) {
70406
- if (existsSync28(join29(p2, cmd + suffix))) {
70724
+ if (existsSync30(join33(p2, cmd + suffix))) {
70407
70725
  return true;
70408
70726
  }
70409
70727
  }
70410
70728
  }
70411
70729
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
70412
70730
  for (const suffix of exts) {
70413
- if (existsSync28(join29(base, cmd + suffix))) {
70731
+ if (existsSync30(join33(base, cmd + suffix))) {
70414
70732
  return true;
70415
70733
  }
70416
70734
  }
@@ -70472,24 +70790,24 @@ function getInstalledLspServers() {
70472
70790
 
70473
70791
  // src/cli/doctor/checks/tools-mcp.ts
70474
70792
  init_shared();
70475
- import { existsSync as existsSync29, readFileSync as readFileSync26 } from "fs";
70793
+ import { existsSync as existsSync31, readFileSync as readFileSync27 } from "fs";
70476
70794
  import { homedir as homedir8 } from "os";
70477
- import { join as join30 } from "path";
70795
+ import { join as join34 } from "path";
70478
70796
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
70479
70797
  function getMcpConfigPaths() {
70480
70798
  return [
70481
- join30(homedir8(), ".claude", ".mcp.json"),
70482
- join30(process.cwd(), ".mcp.json"),
70483
- join30(process.cwd(), ".claude", ".mcp.json")
70799
+ join34(homedir8(), ".claude", ".mcp.json"),
70800
+ join34(process.cwd(), ".mcp.json"),
70801
+ join34(process.cwd(), ".claude", ".mcp.json")
70484
70802
  ];
70485
70803
  }
70486
70804
  function loadUserMcpConfig() {
70487
70805
  const servers = {};
70488
70806
  for (const configPath of getMcpConfigPaths()) {
70489
- if (!existsSync29(configPath))
70807
+ if (!existsSync31(configPath))
70490
70808
  continue;
70491
70809
  try {
70492
- const content = readFileSync26(configPath, "utf-8");
70810
+ const content = readFileSync27(configPath, "utf-8");
70493
70811
  const config2 = parseJsonc(content);
70494
70812
  if (config2.mcpServers) {
70495
70813
  Object.assign(servers, config2.mcpServers);
@@ -70689,7 +71007,6 @@ function formatIssue(issue2, index) {
70689
71007
  }
70690
71008
 
70691
71009
  // src/cli/doctor/format-default.ts
70692
- init_plugin_identity();
70693
71010
  function formatDefault(result) {
70694
71011
  const lines = [];
70695
71012
  lines.push(formatHeader());
@@ -70697,7 +71014,7 @@ function formatDefault(result) {
70697
71014
  if (allIssues.length === 0) {
70698
71015
  const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
70699
71016
  const pluginVer = result.systemInfo.pluginVersion ?? "unknown";
70700
- lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 ${PLUGIN_NAME} ${pluginVer})`)}`);
71017
+ lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 evil-omo ${pluginVer})`)}`);
70701
71018
  } else {
70702
71019
  const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
70703
71020
  const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
@@ -70745,7 +71062,6 @@ function formatStatus(result) {
70745
71062
 
70746
71063
  // src/cli/doctor/format-verbose.ts
70747
71064
  var import_picocolors20 = __toESM(require_picocolors(), 1);
70748
- init_plugin_identity();
70749
71065
  function formatVerbose(result) {
70750
71066
  const lines = [];
70751
71067
  lines.push(formatHeader());
@@ -70753,7 +71069,7 @@ function formatVerbose(result) {
70753
71069
  lines.push(`${import_picocolors20.default.bold("System Information")}`);
70754
71070
  lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
70755
71071
  lines.push(` ${formatStatusSymbol("pass")} opencode ${systemInfo.opencodeVersion ?? "unknown"}`);
70756
- lines.push(` ${formatStatusSymbol("pass")} ${PLUGIN_NAME} ${systemInfo.pluginVersion ?? "unknown"}`);
71072
+ lines.push(` ${formatStatusSymbol("pass")} evil-omo ${systemInfo.pluginVersion ?? "unknown"}`);
70757
71073
  if (systemInfo.loadedVersion) {
70758
71074
  lines.push(` ${formatStatusSymbol("pass")} loaded ${systemInfo.loadedVersion}`);
70759
71075
  }
@@ -70910,13 +71226,45 @@ async function doctor(options = { mode: "default" }) {
70910
71226
  return result.exitCode;
70911
71227
  }
70912
71228
 
71229
+ // src/cli/refresh-model-capabilities.ts
71230
+ init_model_capabilities_cache();
71231
+ async function refreshModelCapabilities(options, deps = {}) {
71232
+ const directory = options.directory ?? process.cwd();
71233
+ const loadConfig = deps.loadConfig ?? loadPluginConfig;
71234
+ const refreshCache = deps.refreshCache ?? refreshModelCapabilitiesCache;
71235
+ const stdout = deps.stdout ?? process.stdout;
71236
+ const stderr = deps.stderr ?? process.stderr;
71237
+ try {
71238
+ const config2 = loadConfig(directory, null);
71239
+ const sourceUrl = options.sourceUrl ?? config2.model_capabilities?.source_url;
71240
+ const snapshot = await refreshCache({ sourceUrl });
71241
+ const summary = {
71242
+ sourceUrl: snapshot.sourceUrl,
71243
+ generatedAt: snapshot.generatedAt,
71244
+ modelCount: Object.keys(snapshot.models).length
71245
+ };
71246
+ if (options.json) {
71247
+ stdout.write(`${JSON.stringify(summary, null, 2)}
71248
+ `);
71249
+ } else {
71250
+ stdout.write(`Refreshed model capabilities cache (${summary.modelCount} models) from ${summary.sourceUrl}
71251
+ `);
71252
+ }
71253
+ return 0;
71254
+ } catch (error48) {
71255
+ stderr.write(`Failed to refresh model capabilities cache: ${String(error48)}
71256
+ `);
71257
+ return 1;
71258
+ }
71259
+ }
71260
+
70913
71261
  // src/features/mcp-oauth/storage.ts
70914
71262
  init_shared();
70915
- import { chmodSync, existsSync as existsSync30, mkdirSync as mkdirSync7, readFileSync as readFileSync27, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
70916
- import { dirname as dirname8, join as join31 } from "path";
71263
+ import { chmodSync, existsSync as existsSync32, mkdirSync as mkdirSync8, readFileSync as readFileSync28, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
71264
+ import { dirname as dirname8, join as join35 } from "path";
70917
71265
  var STORAGE_FILE_NAME = "mcp-oauth.json";
70918
71266
  function getMcpOauthStoragePath() {
70919
- return join31(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71267
+ return join35(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
70920
71268
  }
70921
71269
  function normalizeHost(serverHost) {
70922
71270
  let host = serverHost.trim();
@@ -70953,11 +71301,11 @@ function buildKey(serverHost, resource) {
70953
71301
  }
70954
71302
  function readStore() {
70955
71303
  const filePath = getMcpOauthStoragePath();
70956
- if (!existsSync30(filePath)) {
71304
+ if (!existsSync32(filePath)) {
70957
71305
  return null;
70958
71306
  }
70959
71307
  try {
70960
- const content = readFileSync27(filePath, "utf-8");
71308
+ const content = readFileSync28(filePath, "utf-8");
70961
71309
  return JSON.parse(content);
70962
71310
  } catch {
70963
71311
  return null;
@@ -70967,8 +71315,8 @@ function writeStore(store2) {
70967
71315
  const filePath = getMcpOauthStoragePath();
70968
71316
  try {
70969
71317
  const dir = dirname8(filePath);
70970
- if (!existsSync30(dir)) {
70971
- mkdirSync7(dir, { recursive: true });
71318
+ if (!existsSync32(dir)) {
71319
+ mkdirSync8(dir, { recursive: true });
70972
71320
  }
70973
71321
  writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
70974
71322
  chmodSync(filePath, 384);
@@ -71002,7 +71350,7 @@ function deleteToken(serverHost, resource) {
71002
71350
  if (Object.keys(store2).length === 0) {
71003
71351
  try {
71004
71352
  const filePath = getMcpOauthStoragePath();
71005
- if (existsSync30(filePath)) {
71353
+ if (existsSync32(filePath)) {
71006
71354
  unlinkSync4(filePath);
71007
71355
  }
71008
71356
  return true;
@@ -71225,7 +71573,7 @@ function startCallbackServer(port) {
71225
71573
  clearTimeout(timeoutId);
71226
71574
  const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
71227
71575
  const code = requestUrl.searchParams.get("code");
71228
- const state = requestUrl.searchParams.get("state");
71576
+ const state2 = requestUrl.searchParams.get("state");
71229
71577
  const error48 = requestUrl.searchParams.get("error");
71230
71578
  if (error48) {
71231
71579
  const errorDescription = requestUrl.searchParams.get("error_description") ?? error48;
@@ -71235,7 +71583,7 @@ function startCallbackServer(port) {
71235
71583
  reject(new Error(`OAuth authorization error: ${errorDescription}`));
71236
71584
  return;
71237
71585
  }
71238
- if (!code || !state) {
71586
+ if (!code || !state2) {
71239
71587
  response.writeHead(400, { "content-type": "text/html" });
71240
71588
  response.end("<html><body><h1>Missing code or state</h1></body></html>");
71241
71589
  server2.close();
@@ -71245,7 +71593,7 @@ function startCallbackServer(port) {
71245
71593
  response.writeHead(200, { "content-type": "text/html" });
71246
71594
  response.end("<html><body><h1>Authorization successful. You can close this tab.</h1></body></html>");
71247
71595
  server2.close();
71248
- resolve2({ code, state });
71596
+ resolve2({ code, state: state2 });
71249
71597
  });
71250
71598
  timeoutId = setTimeout(() => {
71251
71599
  server2.close();
@@ -71281,27 +71629,25 @@ function openBrowser(url2) {
71281
71629
  async function runAuthorizationCodeRedirect(options) {
71282
71630
  const verifier = generateCodeVerifier();
71283
71631
  const challenge = generateCodeChallenge(verifier);
71284
- const state = randomBytes2(16).toString("hex");
71632
+ const state2 = randomBytes2(16).toString("hex");
71285
71633
  const authorizationUrl = buildAuthorizationUrl(options.authorizationEndpoint, {
71286
71634
  clientId: options.clientId,
71287
71635
  redirectUri: options.redirectUri,
71288
71636
  codeChallenge: challenge,
71289
- state,
71637
+ state: state2,
71290
71638
  scopes: options.scopes,
71291
71639
  resource: options.resource
71292
71640
  });
71293
71641
  const callbackPromise = startCallbackServer(options.callbackPort);
71294
71642
  openBrowser(authorizationUrl);
71295
71643
  const result = await callbackPromise;
71296
- if (result.state !== state) {
71644
+ if (result.state !== state2) {
71297
71645
  throw new Error("OAuth state mismatch");
71298
71646
  }
71299
71647
  return { code: result.code, verifier };
71300
71648
  }
71301
71649
 
71302
71650
  // src/features/mcp-oauth/provider.ts
71303
- init_plugin_identity();
71304
-
71305
71651
  class McpOAuthProvider {
71306
71652
  serverUrl;
71307
71653
  configClientId;
@@ -71369,7 +71715,7 @@ class McpOAuthProvider {
71369
71715
  const clientInfo = await getOrRegisterClient({
71370
71716
  registrationEndpoint: metadata.registrationEndpoint,
71371
71717
  serverIdentifier: this.serverUrl,
71372
- clientName: PLUGIN_NAME,
71718
+ clientName: "evil-omo",
71373
71719
  redirectUris: [this.redirectUrl()],
71374
71720
  tokenEndpointAuthMethod: "none",
71375
71721
  clientId: this.configClientId,
@@ -71560,7 +71906,7 @@ Examples:
71560
71906
  Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
71561
71907
  Claude Native anthropic/ models (Opus, Sonnet, Haiku)
71562
71908
  OpenAI Native openai/ models (GPT-5.4 for Oracle)
71563
- Gemini Native google/ models (Gemini 3 Pro, Flash)
71909
+ Gemini Native google/ models (Gemini 3.1 Pro, Flash)
71564
71910
  Copilot github-copilot/ models (fallback)
71565
71911
  OpenCode Zen opencode/ models (opencode/claude-opus-4-6, etc.)
71566
71912
  Z.ai zai-coding-plan/glm-5 (visual-engineering fallback)
@@ -71660,6 +72006,14 @@ Examples:
71660
72006
  const exitCode = await doctor(doctorOptions);
71661
72007
  process.exit(exitCode);
71662
72008
  });
72009
+ program2.command("refresh-model-capabilities").description("Refresh the cached models.dev-based model capabilities snapshot").option("-d, --directory <path>", "Working directory to read evil-omo config from").option("--source-url <url>", "Override the models.dev source URL").option("--json", "Output refresh summary as JSON").action(async (options) => {
72010
+ const exitCode = await refreshModelCapabilities({
72011
+ directory: options.directory,
72012
+ sourceUrl: options.sourceUrl,
72013
+ json: options.json ?? false
72014
+ });
72015
+ process.exit(exitCode);
72016
+ });
71663
72017
  program2.command("version").description("Show version information").action(() => {
71664
72018
  console.log(`evil-omo v${VERSION2}`);
71665
72019
  });