oh-my-opencode 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
@@ -6367,18 +6367,88 @@ var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai
6367
6367
  var init_opencode_config_dir = () => {};
6368
6368
 
6369
6369
  // src/shared/opencode-version.ts
6370
- var NOT_CACHED;
6370
+ import { execSync } from "child_process";
6371
+ function parseVersion(version) {
6372
+ const cleaned = version.replace(/^v/, "").split("-")[0];
6373
+ return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
6374
+ }
6375
+ function compareVersions(a, b) {
6376
+ const partsA = parseVersion(a);
6377
+ const partsB = parseVersion(b);
6378
+ const maxLen = Math.max(partsA.length, partsB.length);
6379
+ for (let i2 = 0;i2 < maxLen; i2++) {
6380
+ const numA = partsA[i2] ?? 0;
6381
+ const numB = partsB[i2] ?? 0;
6382
+ if (numA < numB)
6383
+ return -1;
6384
+ if (numA > numB)
6385
+ return 1;
6386
+ }
6387
+ return 0;
6388
+ }
6389
+ function getOpenCodeVersion() {
6390
+ if (cachedVersion !== NOT_CACHED) {
6391
+ return cachedVersion;
6392
+ }
6393
+ try {
6394
+ const result = execSync("opencode --version", {
6395
+ encoding: "utf-8",
6396
+ timeout: 5000,
6397
+ stdio: ["pipe", "pipe", "pipe"]
6398
+ }).trim();
6399
+ const versionMatch = result.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
6400
+ cachedVersion = versionMatch?.[1] ?? null;
6401
+ return cachedVersion;
6402
+ } catch {
6403
+ cachedVersion = null;
6404
+ return null;
6405
+ }
6406
+ }
6407
+ function isOpenCodeVersionAtLeast(version) {
6408
+ const current = getOpenCodeVersion();
6409
+ if (!current)
6410
+ return true;
6411
+ return compareVersions(current, version) >= 0;
6412
+ }
6413
+ var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion;
6371
6414
  var init_opencode_version = __esm(() => {
6372
6415
  NOT_CACHED = Symbol("NOT_CACHED");
6416
+ cachedVersion = NOT_CACHED;
6373
6417
  });
6374
6418
 
6375
6419
  // src/shared/opencode-storage-detection.ts
6376
- var NOT_CACHED2, FALSE_PENDING_RETRY;
6420
+ import { existsSync as existsSync3 } from "fs";
6421
+ import { join as join5 } from "path";
6422
+ function isSqliteBackend() {
6423
+ if (cachedResult === true)
6424
+ return true;
6425
+ if (cachedResult === false)
6426
+ return false;
6427
+ const check = () => {
6428
+ const versionOk = isOpenCodeVersionAtLeast(OPENCODE_SQLITE_VERSION);
6429
+ const dbPath = join5(getDataDir(), "opencode", "opencode.db");
6430
+ return versionOk && existsSync3(dbPath);
6431
+ };
6432
+ if (cachedResult === FALSE_PENDING_RETRY) {
6433
+ const result2 = check();
6434
+ cachedResult = result2;
6435
+ return result2;
6436
+ }
6437
+ const result = check();
6438
+ if (result) {
6439
+ cachedResult = true;
6440
+ } else {
6441
+ cachedResult = FALSE_PENDING_RETRY;
6442
+ }
6443
+ return result;
6444
+ }
6445
+ var NOT_CACHED2, FALSE_PENDING_RETRY, cachedResult;
6377
6446
  var init_opencode_storage_detection = __esm(() => {
6378
6447
  init_data_path();
6379
6448
  init_opencode_version();
6380
6449
  NOT_CACHED2 = Symbol("NOT_CACHED");
6381
6450
  FALSE_PENDING_RETRY = Symbol("FALSE_PENDING_RETRY");
6451
+ cachedResult = NOT_CACHED2;
6382
6452
  });
6383
6453
  // src/shared/load-opencode-plugins.ts
6384
6454
  var init_load_opencode_plugins = __esm(() => {
@@ -6793,19 +6863,19 @@ function normalizeModelID(modelID) {
6793
6863
  }
6794
6864
 
6795
6865
  // src/shared/json-file-cache-store.ts
6796
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6797
- import { join as join5 } from "path";
6866
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6867
+ import { join as join6 } from "path";
6798
6868
  function toLogLabel(cacheLabel) {
6799
6869
  return cacheLabel.toLowerCase();
6800
6870
  }
6801
6871
  function createJsonFileCacheStore(options) {
6802
6872
  let memoryValue;
6803
6873
  function getCacheFilePath() {
6804
- return join5(options.getCacheDir(), options.filename);
6874
+ return join6(options.getCacheDir(), options.filename);
6805
6875
  }
6806
6876
  function ensureCacheDir() {
6807
6877
  const cacheDir = options.getCacheDir();
6808
- if (!existsSync3(cacheDir)) {
6878
+ if (!existsSync4(cacheDir)) {
6809
6879
  mkdirSync2(cacheDir, { recursive: true });
6810
6880
  }
6811
6881
  }
@@ -6814,7 +6884,7 @@ function createJsonFileCacheStore(options) {
6814
6884
  return memoryValue;
6815
6885
  }
6816
6886
  const cacheFile = getCacheFilePath();
6817
- if (!existsSync3(cacheFile)) {
6887
+ if (!existsSync4(cacheFile)) {
6818
6888
  memoryValue = null;
6819
6889
  log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
6820
6890
  return null;
@@ -6834,7 +6904,7 @@ function createJsonFileCacheStore(options) {
6834
6904
  }
6835
6905
  }
6836
6906
  function has() {
6837
- return existsSync3(getCacheFilePath());
6907
+ return existsSync4(getCacheFilePath());
6838
6908
  }
6839
6909
  function write(value) {
6840
6910
  ensureCacheDir();
@@ -7003,14 +7073,14 @@ var init_connected_providers_cache = __esm(() => {
7003
7073
  });
7004
7074
 
7005
7075
  // src/shared/model-availability.ts
7006
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
7007
- import { join as join6 } from "path";
7076
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
7077
+ import { join as join7 } from "path";
7008
7078
  function isModelCacheAvailable() {
7009
7079
  if (hasProviderModelsCache()) {
7010
7080
  return true;
7011
7081
  }
7012
- const cacheFile = join6(getOpenCodeCacheDir(), "models.json");
7013
- return existsSync4(cacheFile);
7082
+ const cacheFile = join7(getOpenCodeCacheDir(), "models.json");
7083
+ return existsSync5(cacheFile);
7014
7084
  }
7015
7085
  var init_model_availability = __esm(() => {
7016
7086
  init_logger();
@@ -48323,17 +48393,43 @@ var init_hook_message_injector = __esm(() => {
48323
48393
  });
48324
48394
 
48325
48395
  // src/shared/opencode-storage-paths.ts
48326
- import { join as join7 } from "path";
48396
+ import { join as join8 } from "path";
48327
48397
  var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48328
48398
  var init_opencode_storage_paths = __esm(() => {
48329
48399
  init_data_path();
48330
48400
  OPENCODE_STORAGE = getOpenCodeStorageDir();
48331
- MESSAGE_STORAGE = join7(OPENCODE_STORAGE, "message");
48332
- PART_STORAGE = join7(OPENCODE_STORAGE, "part");
48333
- SESSION_STORAGE = join7(OPENCODE_STORAGE, "session");
48401
+ MESSAGE_STORAGE = join8(OPENCODE_STORAGE, "message");
48402
+ PART_STORAGE = join8(OPENCODE_STORAGE, "part");
48403
+ SESSION_STORAGE = join8(OPENCODE_STORAGE, "session");
48334
48404
  });
48335
48405
 
48336
48406
  // src/shared/opencode-message-dir.ts
48407
+ import { existsSync as existsSync6, readdirSync } from "fs";
48408
+ import { join as join9 } from "path";
48409
+ function getMessageDir(sessionID) {
48410
+ if (!sessionID.startsWith("ses_"))
48411
+ return null;
48412
+ if (/[/\\]|\.\./.test(sessionID))
48413
+ return null;
48414
+ if (!existsSync6(MESSAGE_STORAGE))
48415
+ return null;
48416
+ const directPath = join9(MESSAGE_STORAGE, sessionID);
48417
+ if (existsSync6(directPath)) {
48418
+ return directPath;
48419
+ }
48420
+ try {
48421
+ for (const dir of readdirSync(MESSAGE_STORAGE)) {
48422
+ const sessionPath = join9(MESSAGE_STORAGE, dir, sessionID);
48423
+ if (existsSync6(sessionPath)) {
48424
+ return sessionPath;
48425
+ }
48426
+ }
48427
+ } catch (error) {
48428
+ log("[opencode-message-dir] Failed to scan message directories", { sessionID, error: String(error) });
48429
+ return null;
48430
+ }
48431
+ return null;
48432
+ }
48337
48433
  var init_opencode_message_dir = __esm(() => {
48338
48434
  init_opencode_storage_paths();
48339
48435
  init_logger();
@@ -48821,10 +48917,10 @@ var init_plugin_name_with_version = __esm(() => {
48821
48917
  });
48822
48918
 
48823
48919
  // src/cli/config-manager/ensure-config-directory-exists.ts
48824
- import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
48920
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
48825
48921
  function ensureConfigDirectoryExists() {
48826
48922
  const configDir = getConfigDir();
48827
- if (!existsSync5(configDir)) {
48923
+ if (!existsSync7(configDir)) {
48828
48924
  mkdirSync3(configDir, { recursive: true });
48829
48925
  }
48830
48926
  }
@@ -48862,14 +48958,14 @@ function formatErrorWithSuggestion(err, context) {
48862
48958
  }
48863
48959
 
48864
48960
  // src/cli/config-manager/opencode-config-format.ts
48865
- import { existsSync as existsSync6 } from "fs";
48961
+ import { existsSync as existsSync8 } from "fs";
48866
48962
  function detectConfigFormat() {
48867
48963
  const configJsonc = getConfigJsonc();
48868
48964
  const configJson = getConfigJson();
48869
- if (existsSync6(configJsonc)) {
48965
+ if (existsSync8(configJsonc)) {
48870
48966
  return { format: "jsonc", path: configJsonc };
48871
48967
  }
48872
- if (existsSync6(configJson)) {
48968
+ if (existsSync8(configJson)) {
48873
48969
  return { format: "json", path: configJson };
48874
48970
  }
48875
48971
  return { format: "none", path: configJson };
@@ -49220,7 +49316,7 @@ function deepMergeRecord(target, source) {
49220
49316
  }
49221
49317
 
49222
49318
  // src/cli/config-manager/write-omo-config.ts
49223
- import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49319
+ import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49224
49320
  function isEmptyOrWhitespace2(content) {
49225
49321
  return content.trim().length === 0;
49226
49322
  }
@@ -49237,7 +49333,7 @@ function writeOmoConfig(installConfig) {
49237
49333
  const omoConfigPath = getOmoConfigPath();
49238
49334
  try {
49239
49335
  const newConfig = generateOmoConfig(installConfig);
49240
- if (existsSync7(omoConfigPath)) {
49336
+ if (existsSync9(omoConfigPath)) {
49241
49337
  try {
49242
49338
  const stat = statSync2(omoConfigPath);
49243
49339
  const content = readFileSync6(omoConfigPath, "utf-8");
@@ -49368,7 +49464,7 @@ async function isOpenCodeInstalled() {
49368
49464
  const result = await findOpenCodeBinaryWithVersion();
49369
49465
  return result !== null;
49370
49466
  }
49371
- async function getOpenCodeVersion() {
49467
+ async function getOpenCodeVersion2() {
49372
49468
  const result = await findOpenCodeBinaryWithVersion();
49373
49469
  return result?.version ?? null;
49374
49470
  }
@@ -49380,10 +49476,10 @@ var init_opencode_binary = __esm(() => {
49380
49476
  });
49381
49477
 
49382
49478
  // src/cli/config-manager/detect-current-config.ts
49383
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
49479
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
49384
49480
  function detectProvidersFromOmoConfig() {
49385
49481
  const omoConfigPath = getOmoConfigPath();
49386
- if (!existsSync8(omoConfigPath)) {
49482
+ if (!existsSync10(omoConfigPath)) {
49387
49483
  return {
49388
49484
  hasOpenAI: true,
49389
49485
  hasOpencodeZen: true,
@@ -49469,10 +49565,10 @@ var init_detect_current_config = __esm(() => {
49469
49565
  });
49470
49566
 
49471
49567
  // src/cli/config-manager/bun-install.ts
49472
- import { existsSync as existsSync9 } from "fs";
49473
- import { join as join8 } from "path";
49568
+ import { existsSync as existsSync11 } from "fs";
49569
+ import { join as join10 } from "path";
49474
49570
  function getDefaultWorkspaceDir() {
49475
- return join8(getOpenCodeCacheDir(), "packages");
49571
+ return join10(getOpenCodeCacheDir(), "packages");
49476
49572
  }
49477
49573
  function readProcessOutput(stream) {
49478
49574
  if (!stream) {
@@ -49498,7 +49594,7 @@ async function runBunInstallWithDetails(options) {
49498
49594
  const outputMode = options?.outputMode ?? "pipe";
49499
49595
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
49500
49596
  const packageJsonPath = `${cacheDir}/package.json`;
49501
- if (!existsSync9(packageJsonPath)) {
49597
+ if (!existsSync11(packageJsonPath)) {
49502
49598
  return {
49503
49599
  success: false,
49504
49600
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -50197,8 +50293,8 @@ var init_update_toasts = __esm(() => {
50197
50293
  });
50198
50294
 
50199
50295
  // src/hooks/auto-update-checker/hook/background-update-check.ts
50200
- import { existsSync as existsSync21 } from "fs";
50201
- import { join as join20 } from "path";
50296
+ import { existsSync as existsSync23 } from "fs";
50297
+ import { join as join23 } from "path";
50202
50298
  function getCacheWorkspaceDir(deps) {
50203
50299
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
50204
50300
  }
@@ -50255,8 +50351,8 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50255
50351
  deps.log("[auto-update-checker] Plugin not found in config");
50256
50352
  return;
50257
50353
  }
50258
- const cachedVersion = deps.getCachedVersion();
50259
- const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
50354
+ const cachedVersion2 = deps.getCachedVersion();
50355
+ const currentVersion = cachedVersion2 ?? pluginInfo.pinnedVersion;
50260
50356
  if (!currentVersion) {
50261
50357
  deps.log("[auto-update-checker] No version found (cached or pinned)");
50262
50358
  return;
@@ -50316,8 +50412,8 @@ var init_background_update_check = __esm(() => {
50316
50412
  init_checker();
50317
50413
  init_update_toasts();
50318
50414
  defaultDeps = {
50319
- existsSync: existsSync21,
50320
- join: join20,
50415
+ existsSync: existsSync23,
50416
+ join: join23,
50321
50417
  runBunInstallWithDetails,
50322
50418
  log,
50323
50419
  getOpenCodeCacheDir,
@@ -50526,9 +50622,9 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
50526
50622
  return;
50527
50623
  hasChecked = true;
50528
50624
  setTimeout(async () => {
50529
- const cachedVersion = getCachedVersion();
50625
+ const cachedVersion2 = getCachedVersion();
50530
50626
  const localDevVersion = getLocalDevVersion(ctx.directory);
50531
- const displayVersion = localDevVersion ?? cachedVersion;
50627
+ const displayVersion = localDevVersion ?? cachedVersion2;
50532
50628
  await showConfigErrorsIfAny(ctx);
50533
50629
  await updateAndShowConnectedProvidersCacheStatus(ctx);
50534
50630
  await refreshModelCapabilitiesOnStartup(modelCapabilities);
@@ -50597,7 +50693,7 @@ var {
50597
50693
  // package.json
50598
50694
  var package_default = {
50599
50695
  name: "oh-my-opencode",
50600
- version: "3.15.2",
50696
+ version: "3.15.3",
50601
50697
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
50602
50698
  main: "./dist/index.js",
50603
50699
  types: "dist/index.d.ts",
@@ -50675,17 +50771,17 @@ var package_default = {
50675
50771
  typescript: "^5.7.3"
50676
50772
  },
50677
50773
  optionalDependencies: {
50678
- "oh-my-opencode-darwin-arm64": "3.15.2",
50679
- "oh-my-opencode-darwin-x64": "3.15.2",
50680
- "oh-my-opencode-darwin-x64-baseline": "3.15.2",
50681
- "oh-my-opencode-linux-arm64": "3.15.2",
50682
- "oh-my-opencode-linux-arm64-musl": "3.15.2",
50683
- "oh-my-opencode-linux-x64": "3.15.2",
50684
- "oh-my-opencode-linux-x64-baseline": "3.15.2",
50685
- "oh-my-opencode-linux-x64-musl": "3.15.2",
50686
- "oh-my-opencode-linux-x64-musl-baseline": "3.15.2",
50687
- "oh-my-opencode-windows-x64": "3.15.2",
50688
- "oh-my-opencode-windows-x64-baseline": "3.15.2"
50774
+ "oh-my-opencode-darwin-arm64": "3.15.3",
50775
+ "oh-my-opencode-darwin-x64": "3.15.3",
50776
+ "oh-my-opencode-darwin-x64-baseline": "3.15.3",
50777
+ "oh-my-opencode-linux-arm64": "3.15.3",
50778
+ "oh-my-opencode-linux-arm64-musl": "3.15.3",
50779
+ "oh-my-opencode-linux-x64": "3.15.3",
50780
+ "oh-my-opencode-linux-x64-baseline": "3.15.3",
50781
+ "oh-my-opencode-linux-x64-musl": "3.15.3",
50782
+ "oh-my-opencode-linux-x64-musl-baseline": "3.15.3",
50783
+ "oh-my-opencode-windows-x64": "3.15.3",
50784
+ "oh-my-opencode-windows-x64-baseline": "3.15.3"
50689
50785
  },
50690
50786
  overrides: {
50691
50787
  "@opencode-ai/sdk": "^1.2.24"
@@ -50868,7 +50964,7 @@ async function runCliInstaller(args, version) {
50868
50964
  let step = 1;
50869
50965
  printStep(step++, totalSteps, "Checking OpenCode installation...");
50870
50966
  const installed = await isOpenCodeInstalled();
50871
- const openCodeVersion = await getOpenCodeVersion();
50967
+ const openCodeVersion = await getOpenCodeVersion2();
50872
50968
  if (!installed) {
50873
50969
  printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
50874
50970
  printInfo("Visit https://opencode.ai/docs for installation instructions");
@@ -51643,7 +51739,7 @@ async function runTuiInstaller(args, version) {
51643
51739
  const spinner = Y2();
51644
51740
  spinner.start("Checking OpenCode installation");
51645
51741
  const installed = await isOpenCodeInstalled();
51646
- const openCodeVersion = await getOpenCodeVersion();
51742
+ const openCodeVersion = await getOpenCodeVersion2();
51647
51743
  if (!installed) {
51648
51744
  spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
51649
51745
  M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
@@ -66488,12 +66584,12 @@ init_shared();
66488
66584
  // src/shared/migrate-legacy-config-file.ts
66489
66585
  init_logger();
66490
66586
  init_write_file_atomically();
66491
- import { existsSync as existsSync10, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
66492
- import { join as join9, dirname, basename } from "path";
66587
+ import { existsSync as existsSync12, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
66588
+ import { join as join11, dirname, basename } from "path";
66493
66589
  function buildCanonicalPath(legacyPath) {
66494
66590
  const dir = dirname(legacyPath);
66495
66591
  const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
66496
- return join9(dir, `${CONFIG_BASENAME}${ext}`);
66592
+ return join11(dir, `${CONFIG_BASENAME}${ext}`);
66497
66593
  }
66498
66594
  function archiveLegacyConfigFile(legacyPath) {
66499
66595
  const backupPath = `${legacyPath}.bak`;
@@ -66525,12 +66621,12 @@ function archiveLegacyConfigFile(legacyPath) {
66525
66621
  }
66526
66622
  }
66527
66623
  function migrateLegacyConfigFile(legacyPath) {
66528
- if (!existsSync10(legacyPath))
66624
+ if (!existsSync12(legacyPath))
66529
66625
  return false;
66530
66626
  if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
66531
66627
  return false;
66532
66628
  const canonicalPath = buildCanonicalPath(legacyPath);
66533
- if (existsSync10(canonicalPath))
66629
+ if (existsSync12(canonicalPath))
66534
66630
  return false;
66535
66631
  try {
66536
66632
  const content = readFileSync8(legacyPath, "utf-8");
@@ -68173,7 +68269,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
68173
68269
 
68174
68270
  // src/cli/run/opencode-binary-resolver.ts
68175
68271
  init_spawn_with_windows_hide();
68176
- import { delimiter, dirname as dirname3, join as join11 } from "path";
68272
+ import { delimiter, dirname as dirname3, join as join13 } from "path";
68177
68273
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
68178
68274
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
68179
68275
  function getCommandCandidates(platform) {
@@ -68196,7 +68292,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
68196
68292
  }
68197
68293
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
68198
68294
  for (const command of commandCandidates) {
68199
- addCandidate(join11(entry, command));
68295
+ addCandidate(join13(entry, command));
68200
68296
  }
68201
68297
  }
68202
68298
  return candidates;
@@ -68579,15 +68675,15 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68579
68675
  var NOTEPAD_DIR = "notepads";
68580
68676
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68581
68677
  // src/features/boulder-state/storage.ts
68582
- import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync } from "fs";
68583
- import { dirname as dirname4, join as join12, basename as basename3 } from "path";
68678
+ import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
68679
+ import { dirname as dirname4, join as join14, basename as basename3 } from "path";
68584
68680
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68585
68681
  function getBoulderFilePath(directory) {
68586
- return join12(directory, BOULDER_DIR, BOULDER_FILE);
68682
+ return join14(directory, BOULDER_DIR, BOULDER_FILE);
68587
68683
  }
68588
68684
  function readBoulderState(directory) {
68589
68685
  const filePath = getBoulderFilePath(directory);
68590
- if (!existsSync12(filePath)) {
68686
+ if (!existsSync14(filePath)) {
68591
68687
  return null;
68592
68688
  }
68593
68689
  try {
@@ -68599,6 +68695,15 @@ function readBoulderState(directory) {
68599
68695
  if (!Array.isArray(parsed.session_ids)) {
68600
68696
  parsed.session_ids = [];
68601
68697
  }
68698
+ if (!parsed.session_origins || typeof parsed.session_origins !== "object" || Array.isArray(parsed.session_origins)) {
68699
+ parsed.session_origins = {};
68700
+ }
68701
+ if (parsed.session_ids.length === 1) {
68702
+ const soleSessionId = parsed.session_ids[0];
68703
+ if (typeof soleSessionId === "string" && parsed.session_origins[soleSessionId] !== "appended" && parsed.session_origins[soleSessionId] !== "direct") {
68704
+ parsed.session_origins[soleSessionId] = "direct";
68705
+ }
68706
+ }
68602
68707
  if (!parsed.task_sessions || typeof parsed.task_sessions !== "object" || Array.isArray(parsed.task_sessions)) {
68603
68708
  parsed.task_sessions = {};
68604
68709
  }
@@ -68608,7 +68713,7 @@ function readBoulderState(directory) {
68608
68713
  }
68609
68714
  }
68610
68715
  function getPlanProgress(planPath) {
68611
- if (!existsSync12(planPath)) {
68716
+ if (!existsSync14(planPath)) {
68612
68717
  return { total: 0, completed: 0, isComplete: true };
68613
68718
  }
68614
68719
  try {
@@ -68626,17 +68731,26 @@ function getPlanProgress(planPath) {
68626
68731
  return { total: 0, completed: 0, isComplete: true };
68627
68732
  }
68628
68733
  }
68734
+ // src/features/claude-code-session-state/state.ts
68735
+ init_agent_display_names();
68736
+ var subagentSessions = new Set;
68737
+ var syncSubagentSessions = new Set;
68738
+ var registeredAgentNames = new Set;
68739
+ var sessionAgentMap = new Map;
68740
+ function getSessionAgent(sessionID) {
68741
+ return sessionAgentMap.get(sessionID);
68742
+ }
68629
68743
  // src/features/run-continuation-state/constants.ts
68630
68744
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68631
68745
  // src/features/run-continuation-state/storage.ts
68632
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
68633
- import { join as join13 } from "path";
68746
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
68747
+ import { join as join15 } from "path";
68634
68748
  function getMarkerPath(directory, sessionID) {
68635
- return join13(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68749
+ return join15(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68636
68750
  }
68637
68751
  function readContinuationMarker(directory, sessionID) {
68638
68752
  const markerPath = getMarkerPath(directory, sessionID);
68639
- if (!existsSync13(markerPath))
68753
+ if (!existsSync15(markerPath))
68640
68754
  return null;
68641
68755
  try {
68642
68756
  const raw = readFileSync11(markerPath, "utf-8");
@@ -68662,10 +68776,113 @@ function getActiveContinuationMarkerReason(marker) {
68662
68776
  const [source, entry] = active;
68663
68777
  return entry.reason ?? `${source} continuation is active`;
68664
68778
  }
68779
+ // src/hooks/atlas/boulder-session-lineage.ts
68780
+ init_logger();
68781
+
68782
+ // src/hooks/atlas/hook-name.ts
68783
+ var HOOK_NAME = "atlas";
68784
+
68785
+ // src/hooks/atlas/boulder-session-lineage.ts
68786
+ async function isSessionInBoulderLineage(input) {
68787
+ const visitedSessionIDs = new Set;
68788
+ let currentSessionID = input.sessionID;
68789
+ while (!visitedSessionIDs.has(currentSessionID)) {
68790
+ visitedSessionIDs.add(currentSessionID);
68791
+ const sessionResult = await input.client.session.get({ path: { id: currentSessionID } }).catch((error48) => {
68792
+ log(`[${HOOK_NAME}] Failed to resolve session lineage`, {
68793
+ sessionID: input.sessionID,
68794
+ currentSessionID,
68795
+ error: error48
68796
+ });
68797
+ return null;
68798
+ });
68799
+ if (!sessionResult || sessionResult.error) {
68800
+ return false;
68801
+ }
68802
+ const parentSessionID = sessionResult.data?.parentID;
68803
+ if (!parentSessionID) {
68804
+ return false;
68805
+ }
68806
+ if (input.boulderSessionIDs.includes(parentSessionID)) {
68807
+ return true;
68808
+ }
68809
+ currentSessionID = parentSessionID;
68810
+ }
68811
+ return false;
68812
+ }
68813
+
68814
+ // src/hooks/atlas/session-last-agent.ts
68815
+ init_shared();
68816
+ import { readFileSync as readFileSync12, readdirSync as readdirSync3 } from "fs";
68817
+ import { join as join16 } from "path";
68818
+ function isCompactionAgent(agent) {
68819
+ return typeof agent === "string" && agent.toLowerCase() === "compaction";
68820
+ }
68821
+ function getLastAgentFromMessageDir(messageDir) {
68822
+ try {
68823
+ const messages = readdirSync3(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
68824
+ try {
68825
+ const content = readFileSync12(join16(messageDir, fileName), "utf-8");
68826
+ const parsed = JSON.parse(content);
68827
+ return {
68828
+ fileName,
68829
+ agent: parsed.agent,
68830
+ createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
68831
+ };
68832
+ } catch {
68833
+ return null;
68834
+ }
68835
+ }).filter((message) => message !== null).sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName));
68836
+ for (const message of messages) {
68837
+ if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
68838
+ return message.agent.toLowerCase();
68839
+ }
68840
+ }
68841
+ } catch {
68842
+ return null;
68843
+ }
68844
+ return null;
68845
+ }
68846
+ async function getLastAgentFromSession(sessionID, client3) {
68847
+ if (isSqliteBackend() && client3) {
68848
+ try {
68849
+ const response = await client3.session.messages({ path: { id: sessionID } });
68850
+ const messages = normalizeSDKResponse(response, [], {
68851
+ preferResponseOnMissingData: true
68852
+ }).sort((left, right) => {
68853
+ const leftTime = left.info?.time?.created ?? Number.NEGATIVE_INFINITY;
68854
+ const rightTime = right.info?.time?.created ?? Number.NEGATIVE_INFINITY;
68855
+ if (leftTime !== rightTime) {
68856
+ return rightTime - leftTime;
68857
+ }
68858
+ const leftId = typeof left.id === "string" ? left.id : "";
68859
+ const rightId = typeof right.id === "string" ? right.id : "";
68860
+ return rightId.localeCompare(leftId);
68861
+ });
68862
+ for (const message of messages) {
68863
+ const agent = message.info?.agent;
68864
+ if (typeof agent === "string" && !isCompactionAgent(agent)) {
68865
+ return agent.toLowerCase();
68866
+ }
68867
+ }
68868
+ } catch {
68869
+ return null;
68870
+ }
68871
+ return null;
68872
+ }
68873
+ const messageDir = getMessageDir(sessionID);
68874
+ if (!messageDir)
68875
+ return null;
68876
+ return getLastAgentFromMessageDir(messageDir);
68877
+ }
68878
+
68879
+ // src/cli/run/continuation-state.ts
68880
+ init_agent_display_names();
68881
+
68665
68882
  // src/hooks/ralph-loop/storage.ts
68666
68883
  init_frontmatter();
68667
- import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
68668
- import { dirname as dirname5, join as join14 } from "path";
68884
+ import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
68885
+ import { dirname as dirname5, join as join17 } from "path";
68669
68886
 
68670
68887
  // src/hooks/ralph-loop/constants.ts
68671
68888
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -68674,15 +68891,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
68674
68891
 
68675
68892
  // src/hooks/ralph-loop/storage.ts
68676
68893
  function getStateFilePath(directory, customPath) {
68677
- return customPath ? join14(directory, customPath) : join14(directory, DEFAULT_STATE_FILE);
68894
+ return customPath ? join17(directory, customPath) : join17(directory, DEFAULT_STATE_FILE);
68678
68895
  }
68679
68896
  function readState(directory, customPath) {
68680
68897
  const filePath = getStateFilePath(directory, customPath);
68681
- if (!existsSync14(filePath)) {
68898
+ if (!existsSync16(filePath)) {
68682
68899
  return null;
68683
68900
  }
68684
68901
  try {
68685
- const content = readFileSync12(filePath, "utf-8");
68902
+ const content = readFileSync13(filePath, "utf-8");
68686
68903
  const { data, body } = parseFrontmatter(content);
68687
68904
  const active = data.active;
68688
68905
  const iteration = data.iteration;
@@ -68722,10 +68939,10 @@ function readState(directory, customPath) {
68722
68939
  }
68723
68940
 
68724
68941
  // src/cli/run/continuation-state.ts
68725
- function getContinuationState(directory, sessionID) {
68942
+ async function getContinuationState(directory, sessionID, client3) {
68726
68943
  const marker = readContinuationMarker(directory, sessionID);
68727
68944
  return {
68728
- hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
68945
+ hasActiveBoulder: await hasActiveBoulderContinuation(directory, sessionID, client3),
68729
68946
  hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
68730
68947
  hasHookMarker: marker !== null,
68731
68948
  hasTodoHookMarker: marker?.sources.todo !== undefined,
@@ -68733,20 +68950,54 @@ function getContinuationState(directory, sessionID) {
68733
68950
  activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
68734
68951
  };
68735
68952
  }
68736
- function hasActiveBoulderContinuation(directory, sessionID) {
68953
+ async function hasActiveBoulderContinuation(directory, sessionID, client3) {
68737
68954
  const boulder = readBoulderState(directory);
68738
68955
  if (!boulder)
68739
68956
  return false;
68740
- if (!boulder.session_ids.includes(sessionID))
68741
- return false;
68742
68957
  const progress = getPlanProgress(boulder.active_plan);
68743
- return !progress.isComplete;
68958
+ if (progress.isComplete)
68959
+ return false;
68960
+ if (!client3)
68961
+ return false;
68962
+ const isTrackedSession = boulder.session_ids.includes(sessionID);
68963
+ const sessionOrigin = boulder.session_origins?.[sessionID];
68964
+ if (!isTrackedSession) {
68965
+ return false;
68966
+ }
68967
+ const isTrackedDescendant = await isTrackedDescendantSession(client3, sessionID, boulder.session_ids);
68968
+ if (isTrackedSession && sessionOrigin === "direct") {
68969
+ return true;
68970
+ }
68971
+ if (isTrackedSession && sessionOrigin !== "direct" && !isTrackedDescendant) {
68972
+ return false;
68973
+ }
68974
+ const sessionAgent = await getLastAgentFromSession(sessionID, client3) ?? getSessionAgent(sessionID);
68975
+ if (!sessionAgent) {
68976
+ return false;
68977
+ }
68978
+ const requiredAgentKey = getAgentConfigKey(boulder.agent ?? "atlas");
68979
+ const sessionAgentKey = getAgentConfigKey(sessionAgent);
68980
+ if (sessionAgentKey !== requiredAgentKey && !(requiredAgentKey === getAgentConfigKey("atlas") && sessionAgentKey === getAgentConfigKey("sisyphus"))) {
68981
+ return false;
68982
+ }
68983
+ return isTrackedSession || isTrackedDescendant;
68984
+ }
68985
+ async function isTrackedDescendantSession(client3, sessionID, trackedSessionIDs) {
68986
+ const ancestorSessionIDs = trackedSessionIDs.filter((trackedSessionID) => trackedSessionID !== sessionID);
68987
+ if (ancestorSessionIDs.length === 0) {
68988
+ return false;
68989
+ }
68990
+ return isSessionInBoulderLineage({
68991
+ client: client3,
68992
+ sessionID,
68993
+ boulderSessionIDs: ancestorSessionIDs
68994
+ });
68744
68995
  }
68745
68996
  function hasActiveRalphLoopContinuation(directory, sessionID) {
68746
- const state = readState(directory);
68747
- if (!state || !state.active)
68997
+ const state2 = readState(directory);
68998
+ if (!state2 || !state2.active)
68748
68999
  return false;
68749
- if (state.session_id && state.session_id !== sessionID) {
69000
+ if (state2.session_id && state2.session_id !== sessionID) {
68750
69001
  return false;
68751
69002
  }
68752
69003
  return true;
@@ -68755,7 +69006,7 @@ function hasActiveRalphLoopContinuation(directory, sessionID) {
68755
69006
  // src/cli/run/completion.ts
68756
69007
  async function checkCompletionConditions(ctx) {
68757
69008
  try {
68758
- const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
69009
+ const continuationState = await getContinuationState(ctx.directory, ctx.sessionID, ctx.client);
68759
69010
  if (continuationState.hasActiveHookMarker) {
68760
69011
  const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
68761
69012
  logWaiting(ctx, reason);
@@ -69388,30 +69639,30 @@ var PACKAGE_NAME2 = PLUGIN_NAME;
69388
69639
  var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
69389
69640
 
69390
69641
  // src/cli/doctor/checks/system.ts
69391
- import { existsSync as existsSync25, readFileSync as readFileSync22 } from "fs";
69642
+ import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
69392
69643
 
69393
69644
  // src/cli/doctor/checks/system-binary.ts
69394
69645
  init_spawn_with_windows_hide();
69395
- import { existsSync as existsSync22 } from "fs";
69646
+ import { existsSync as existsSync24 } from "fs";
69396
69647
  import { homedir as homedir5 } from "os";
69397
- import { join as join21 } from "path";
69648
+ import { join as join24 } from "path";
69398
69649
  function getDesktopAppPaths(platform) {
69399
69650
  const home = homedir5();
69400
69651
  switch (platform) {
69401
69652
  case "darwin":
69402
69653
  return [
69403
69654
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
69404
- join21(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69655
+ join24(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69405
69656
  ];
69406
69657
  case "win32": {
69407
69658
  const programFiles = process.env.ProgramFiles;
69408
69659
  const localAppData = process.env.LOCALAPPDATA;
69409
69660
  const paths = [];
69410
69661
  if (programFiles) {
69411
- paths.push(join21(programFiles, "OpenCode", "OpenCode.exe"));
69662
+ paths.push(join24(programFiles, "OpenCode", "OpenCode.exe"));
69412
69663
  }
69413
69664
  if (localAppData) {
69414
- paths.push(join21(localAppData, "OpenCode", "OpenCode.exe"));
69665
+ paths.push(join24(localAppData, "OpenCode", "OpenCode.exe"));
69415
69666
  }
69416
69667
  return paths;
69417
69668
  }
@@ -69419,8 +69670,8 @@ function getDesktopAppPaths(platform) {
69419
69670
  return [
69420
69671
  "/usr/bin/opencode",
69421
69672
  "/usr/lib/opencode/opencode",
69422
- join21(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69423
- join21(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69673
+ join24(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69674
+ join24(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69424
69675
  ];
69425
69676
  default:
69426
69677
  return [];
@@ -69432,7 +69683,7 @@ function buildVersionCommand(binaryPath, platform) {
69432
69683
  }
69433
69684
  return [binaryPath, "--version"];
69434
69685
  }
69435
- function findDesktopBinary(platform = process.platform, checkExists = existsSync22) {
69686
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync24) {
69436
69687
  for (const desktopPath of getDesktopAppPaths(platform)) {
69437
69688
  if (checkExists(desktopPath)) {
69438
69689
  return { binary: "opencode", path: desktopPath };
@@ -69449,7 +69700,7 @@ async function findOpenCodeBinary() {
69449
69700
  }
69450
69701
  return findDesktopBinary();
69451
69702
  }
69452
- async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
69703
+ async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
69453
69704
  try {
69454
69705
  const command = buildVersionCommand(binaryPath, platform);
69455
69706
  const processResult = spawnWithWindowsHide(command, { stdout: "pipe", stderr: "pipe" });
@@ -69462,10 +69713,10 @@ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
69462
69713
  return null;
69463
69714
  }
69464
69715
  }
69465
- function compareVersions(current, minimum) {
69466
- const parseVersion = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
69467
- const currentParts = parseVersion(current);
69468
- const minimumParts = parseVersion(minimum);
69716
+ function compareVersions2(current, minimum) {
69717
+ const parseVersion2 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
69718
+ const currentParts = parseVersion2(current);
69719
+ const minimumParts = parseVersion2(minimum);
69469
69720
  const length = Math.max(currentParts.length, minimumParts.length);
69470
69721
  for (let index = 0;index < length; index++) {
69471
69722
  const currentPart = currentParts[index] ?? 0;
@@ -69480,12 +69731,12 @@ function compareVersions(current, minimum) {
69480
69731
 
69481
69732
  // src/cli/doctor/checks/system-plugin.ts
69482
69733
  init_shared();
69483
- import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
69734
+ import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
69484
69735
  function detectConfigPath() {
69485
69736
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
69486
- if (existsSync23(paths.configJsonc))
69737
+ if (existsSync25(paths.configJsonc))
69487
69738
  return paths.configJsonc;
69488
- if (existsSync23(paths.configJson))
69739
+ if (existsSync25(paths.configJson))
69489
69740
  return paths.configJson;
69490
69741
  return null;
69491
69742
  }
@@ -69531,7 +69782,7 @@ function getPluginInfo() {
69531
69782
  };
69532
69783
  }
69533
69784
  try {
69534
- const content = readFileSync20(configPath, "utf-8");
69785
+ const content = readFileSync21(configPath, "utf-8");
69535
69786
  const parsedConfig = parseJsonc(content);
69536
69787
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
69537
69788
  if (!pluginEntry) {
@@ -69569,37 +69820,37 @@ function getPluginInfo() {
69569
69820
  init_file_utils();
69570
69821
  init_checker();
69571
69822
  init_auto_update_checker();
69572
- import { existsSync as existsSync24, readFileSync as readFileSync21 } from "fs";
69823
+ import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
69573
69824
  import { homedir as homedir6 } from "os";
69574
- import { join as join22 } from "path";
69825
+ import { join as join25 } from "path";
69575
69826
  init_shared();
69576
69827
  function getPlatformDefaultCacheDir(platform = process.platform) {
69577
69828
  if (platform === "darwin")
69578
- return join22(homedir6(), "Library", "Caches");
69829
+ return join25(homedir6(), "Library", "Caches");
69579
69830
  if (platform === "win32")
69580
- return process.env.LOCALAPPDATA ?? join22(homedir6(), "AppData", "Local");
69581
- return join22(homedir6(), ".cache");
69831
+ return process.env.LOCALAPPDATA ?? join25(homedir6(), "AppData", "Local");
69832
+ return join25(homedir6(), ".cache");
69582
69833
  }
69583
69834
  function resolveOpenCodeCacheDir() {
69584
69835
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
69585
69836
  if (xdgCacheHome)
69586
- return join22(xdgCacheHome, "opencode");
69837
+ return join25(xdgCacheHome, "opencode");
69587
69838
  const fromShared = getOpenCodeCacheDir();
69588
- const platformDefault = join22(getPlatformDefaultCacheDir(), "opencode");
69589
- if (existsSync24(fromShared) || !existsSync24(platformDefault))
69839
+ const platformDefault = join25(getPlatformDefaultCacheDir(), "opencode");
69840
+ if (existsSync26(fromShared) || !existsSync26(platformDefault))
69590
69841
  return fromShared;
69591
69842
  return platformDefault;
69592
69843
  }
69593
69844
  function resolveExistingDir(dirPath) {
69594
- if (!existsSync24(dirPath))
69845
+ if (!existsSync26(dirPath))
69595
69846
  return dirPath;
69596
69847
  return resolveSymlink(dirPath);
69597
69848
  }
69598
69849
  function readPackageJson(filePath) {
69599
- if (!existsSync24(filePath))
69850
+ if (!existsSync26(filePath))
69600
69851
  return null;
69601
69852
  try {
69602
- const content = readFileSync21(filePath, "utf-8");
69853
+ const content = readFileSync22(filePath, "utf-8");
69603
69854
  return parseJsonc(content);
69604
69855
  } catch {
69605
69856
  return null;
@@ -69618,16 +69869,16 @@ function getLoadedPluginVersion() {
69618
69869
  const candidates = [
69619
69870
  {
69620
69871
  cacheDir: configDir,
69621
- cachePackagePath: join22(configDir, "package.json"),
69622
- installedPackagePath: join22(configDir, "node_modules", PACKAGE_NAME2, "package.json")
69872
+ cachePackagePath: join25(configDir, "package.json"),
69873
+ installedPackagePath: join25(configDir, "node_modules", PACKAGE_NAME2, "package.json")
69623
69874
  },
69624
69875
  {
69625
69876
  cacheDir,
69626
- cachePackagePath: join22(cacheDir, "package.json"),
69627
- installedPackagePath: join22(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
69877
+ cachePackagePath: join25(cacheDir, "package.json"),
69878
+ installedPackagePath: join25(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
69628
69879
  }
69629
69880
  ];
69630
- const selectedCandidate = candidates.find((candidate) => existsSync24(candidate.installedPackagePath)) ?? candidates[0];
69881
+ const selectedCandidate = candidates.find((candidate) => existsSync26(candidate.installedPackagePath)) ?? candidates[0];
69631
69882
  const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
69632
69883
  const cachePackage = readPackageJson(cachePackagePath);
69633
69884
  const installedPackage = readPackageJson(installedPackagePath);
@@ -69654,10 +69905,10 @@ init_shared();
69654
69905
  function isConfigValid(configPath) {
69655
69906
  if (!configPath)
69656
69907
  return true;
69657
- if (!existsSync25(configPath))
69908
+ if (!existsSync27(configPath))
69658
69909
  return false;
69659
69910
  try {
69660
- parseJsonc(readFileSync22(configPath, "utf-8"));
69911
+ parseJsonc(readFileSync23(configPath, "utf-8"));
69661
69912
  return true;
69662
69913
  } catch {
69663
69914
  return false;
@@ -69680,7 +69931,7 @@ function buildMessage(status, issues) {
69680
69931
  async function gatherSystemInfo() {
69681
69932
  const [binaryInfo, pluginInfo] = await Promise.all([findOpenCodeBinary(), Promise.resolve(getPluginInfo())]);
69682
69933
  const loadedInfo = getLoadedPluginVersion();
69683
- const opencodeVersion = binaryInfo ? await getOpenCodeVersion2(binaryInfo.path) : null;
69934
+ const opencodeVersion = binaryInfo ? await getOpenCodeVersion3(binaryInfo.path) : null;
69684
69935
  const pluginVersion = pluginInfo.pinnedVersion ?? loadedInfo.expectedVersion ?? loadedInfo.loadedVersion;
69685
69936
  return {
69686
69937
  opencodeVersion,
@@ -69708,7 +69959,7 @@ async function checkSystem() {
69708
69959
  affects: ["doctor", "run"]
69709
69960
  });
69710
69961
  }
69711
- if (systemInfo.opencodeVersion && !compareVersions(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69962
+ if (systemInfo.opencodeVersion && !compareVersions2(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69712
69963
  issues.push({
69713
69964
  title: "OpenCode version below minimum",
69714
69965
  description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
@@ -69748,7 +69999,7 @@ async function checkSystem() {
69748
69999
  affects: ["plugin loading"]
69749
70000
  });
69750
70001
  }
69751
- if (systemInfo.loadedVersion && latestVersion && !compareVersions(systemInfo.loadedVersion, latestVersion)) {
70002
+ if (systemInfo.loadedVersion && latestVersion && !compareVersions2(systemInfo.loadedVersion, latestVersion)) {
69752
70003
  issues.push({
69753
70004
  title: "Loaded plugin is outdated",
69754
70005
  description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
@@ -69773,28 +70024,28 @@ async function checkSystem() {
69773
70024
  }
69774
70025
 
69775
70026
  // src/cli/doctor/checks/config.ts
69776
- import { readFileSync as readFileSync25 } from "fs";
69777
- import { join as join26 } from "path";
70027
+ import { readFileSync as readFileSync26 } from "fs";
70028
+ import { join as join29 } from "path";
69778
70029
  init_shared();
69779
70030
 
69780
70031
  // src/cli/doctor/checks/model-resolution-cache.ts
69781
70032
  init_shared();
69782
- import { existsSync as existsSync26, readFileSync as readFileSync23 } from "fs";
70033
+ import { existsSync as existsSync28, readFileSync as readFileSync24 } from "fs";
69783
70034
  import { homedir as homedir7 } from "os";
69784
- import { join as join23 } from "path";
70035
+ import { join as join26 } from "path";
69785
70036
  function getOpenCodeCacheDir2() {
69786
70037
  const xdgCache = process.env.XDG_CACHE_HOME;
69787
70038
  if (xdgCache)
69788
- return join23(xdgCache, "opencode");
69789
- return join23(homedir7(), ".cache", "opencode");
70039
+ return join26(xdgCache, "opencode");
70040
+ return join26(homedir7(), ".cache", "opencode");
69790
70041
  }
69791
70042
  function loadAvailableModelsFromCache() {
69792
- const cacheFile = join23(getOpenCodeCacheDir2(), "models.json");
69793
- if (!existsSync26(cacheFile)) {
70043
+ const cacheFile = join26(getOpenCodeCacheDir2(), "models.json");
70044
+ if (!existsSync28(cacheFile)) {
69794
70045
  return { providers: [], modelCount: 0, cacheExists: false };
69795
70046
  }
69796
70047
  try {
69797
- const content = readFileSync23(cacheFile, "utf-8");
70048
+ const content = readFileSync24(cacheFile, "utf-8");
69798
70049
  const data = parseJsonc(content);
69799
70050
  const providers = Object.keys(data);
69800
70051
  let modelCount = 0;
@@ -69816,14 +70067,14 @@ init_model_capabilities();
69816
70067
 
69817
70068
  // src/cli/doctor/checks/model-resolution-config.ts
69818
70069
  init_shared();
69819
- import { readFileSync as readFileSync24 } from "fs";
69820
- import { join as join24 } from "path";
69821
- var PROJECT_CONFIG_DIR = join24(process.cwd(), ".opencode");
70070
+ import { readFileSync as readFileSync25 } from "fs";
70071
+ import { join as join27 } from "path";
70072
+ var PROJECT_CONFIG_DIR = join27(process.cwd(), ".opencode");
69822
70073
  function loadOmoConfig() {
69823
70074
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
69824
70075
  if (projectDetected.format !== "none") {
69825
70076
  try {
69826
- const content = readFileSync24(projectDetected.path, "utf-8");
70077
+ const content = readFileSync25(projectDetected.path, "utf-8");
69827
70078
  return parseJsonc(content);
69828
70079
  } catch {
69829
70080
  return null;
@@ -69833,7 +70084,7 @@ function loadOmoConfig() {
69833
70084
  const userDetected = detectPluginConfigFile(userConfigDir);
69834
70085
  if (userDetected.format !== "none") {
69835
70086
  try {
69836
- const content = readFileSync24(userDetected.path, "utf-8");
70087
+ const content = readFileSync25(userDetected.path, "utf-8");
69837
70088
  return parseJsonc(content);
69838
70089
  } catch {
69839
70090
  return null;
@@ -69844,7 +70095,7 @@ function loadOmoConfig() {
69844
70095
 
69845
70096
  // src/cli/doctor/checks/model-resolution-details.ts
69846
70097
  init_shared();
69847
- import { join as join25 } from "path";
70098
+ import { join as join28 } from "path";
69848
70099
 
69849
70100
  // src/cli/doctor/checks/model-resolution-variant.ts
69850
70101
  function formatModelWithVariant(model, variant) {
@@ -69886,7 +70137,7 @@ function formatCapabilityResolutionLabel(mode) {
69886
70137
  }
69887
70138
  function buildModelResolutionDetails(options) {
69888
70139
  const details = [];
69889
- const cacheFile = join25(getOpenCodeCacheDir(), "models.json");
70140
+ const cacheFile = join28(getOpenCodeCacheDir(), "models.json");
69890
70141
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
69891
70142
  details.push("");
69892
70143
  if (options.available.cacheExists) {
@@ -70041,7 +70292,7 @@ async function checkModels() {
70041
70292
  }
70042
70293
 
70043
70294
  // src/cli/doctor/checks/config.ts
70044
- var PROJECT_CONFIG_DIR2 = join26(process.cwd(), ".opencode");
70295
+ var PROJECT_CONFIG_DIR2 = join29(process.cwd(), ".opencode");
70045
70296
  function findConfigPath() {
70046
70297
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
70047
70298
  if (projectConfig.format !== "none")
@@ -70058,7 +70309,7 @@ function validateConfig() {
70058
70309
  return { exists: false, path: null, valid: true, config: null, errors: [] };
70059
70310
  }
70060
70311
  try {
70061
- const content = readFileSync25(configPath, "utf-8");
70312
+ const content = readFileSync26(configPath, "utf-8");
70062
70313
  const rawConfig = parseJsonc(content);
70063
70314
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
70064
70315
  if (!schemaResult.success) {
@@ -70162,9 +70413,9 @@ async function checkConfig() {
70162
70413
 
70163
70414
  // src/cli/doctor/checks/dependencies.ts
70164
70415
  init_spawn_with_windows_hide();
70165
- import { existsSync as existsSync27 } from "fs";
70416
+ import { existsSync as existsSync29 } from "fs";
70166
70417
  import { createRequire } from "module";
70167
- import { dirname as dirname9, join as join27 } from "path";
70418
+ import { dirname as dirname9, join as join30 } from "path";
70168
70419
  async function checkBinaryExists(binary2) {
70169
70420
  try {
70170
70421
  const path10 = Bun.which(binary2);
@@ -70220,15 +70471,15 @@ async function checkAstGrepNapi() {
70220
70471
  path: null
70221
70472
  };
70222
70473
  } catch {
70223
- const { existsSync: existsSync28 } = await import("fs");
70224
- const { join: join28 } = await import("path");
70474
+ const { existsSync: existsSync30 } = await import("fs");
70475
+ const { join: join31 } = await import("path");
70225
70476
  const { homedir: homedir8 } = await import("os");
70226
70477
  const pathsToCheck = [
70227
- join28(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70228
- join28(process.cwd(), "node_modules", "@ast-grep", "napi")
70478
+ join31(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70479
+ join31(process.cwd(), "node_modules", "@ast-grep", "napi")
70229
70480
  ];
70230
70481
  for (const napiPath of pathsToCheck) {
70231
- if (existsSync28(napiPath)) {
70482
+ if (existsSync30(napiPath)) {
70232
70483
  return {
70233
70484
  name: "AST-Grep NAPI",
70234
70485
  required: false,
@@ -70253,8 +70504,8 @@ function findCommentCheckerPackageBinary() {
70253
70504
  try {
70254
70505
  const require2 = createRequire(import.meta.url);
70255
70506
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
70256
- const binaryPath = join27(dirname9(pkgPath), "bin", binaryName);
70257
- if (existsSync27(binaryPath))
70507
+ const binaryPath = join30(dirname9(pkgPath), "bin", binaryName);
70508
+ if (existsSync29(binaryPath))
70258
70509
  return binaryPath;
70259
70510
  } catch {}
70260
70511
  return null;
@@ -70411,15 +70662,15 @@ var BUILTIN_SERVERS = {
70411
70662
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
70412
70663
  };
70413
70664
  // src/tools/lsp/server-config-loader.ts
70414
- import { existsSync as existsSync28, readFileSync as readFileSync26 } from "fs";
70415
- import { join as join28 } from "path";
70665
+ import { existsSync as existsSync30, readFileSync as readFileSync27 } from "fs";
70666
+ import { join as join31 } from "path";
70416
70667
  init_shared();
70417
70668
  init_jsonc_parser();
70418
70669
  function loadJsonFile(path10) {
70419
- if (!existsSync28(path10))
70670
+ if (!existsSync30(path10))
70420
70671
  return null;
70421
70672
  try {
70422
- return parseJsonc(readFileSync26(path10, "utf-8"));
70673
+ return parseJsonc(readFileSync27(path10, "utf-8"));
70423
70674
  } catch {
70424
70675
  return null;
70425
70676
  }
@@ -70428,9 +70679,9 @@ function getConfigPaths2() {
70428
70679
  const cwd = process.cwd();
70429
70680
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70430
70681
  return {
70431
- project: detectPluginConfigFile(join28(cwd, ".opencode")).path,
70682
+ project: detectPluginConfigFile(join31(cwd, ".opencode")).path,
70432
70683
  user: detectPluginConfigFile(configDir).path,
70433
- opencode: detectConfigFile(join28(configDir, "opencode")).path
70684
+ opencode: detectConfigFile(join31(configDir, "opencode")).path
70434
70685
  };
70435
70686
  }
70436
70687
  function loadAllConfigs() {
@@ -70499,21 +70750,21 @@ function getMergedServers() {
70499
70750
  }
70500
70751
 
70501
70752
  // src/tools/lsp/server-installation.ts
70502
- import { existsSync as existsSync29 } from "fs";
70503
- import { delimiter as delimiter2, join as join30 } from "path";
70753
+ import { existsSync as existsSync31 } from "fs";
70754
+ import { delimiter as delimiter2, join as join33 } from "path";
70504
70755
 
70505
70756
  // src/tools/lsp/server-path-bases.ts
70506
70757
  init_shared();
70507
- import { join as join29 } from "path";
70758
+ import { join as join32 } from "path";
70508
70759
  function getLspServerAdditionalPathBases(workingDirectory) {
70509
70760
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70510
- const dataDir = join29(getDataDir(), "opencode");
70761
+ const dataDir = join32(getDataDir(), "opencode");
70511
70762
  return [
70512
- join29(workingDirectory, "node_modules", ".bin"),
70513
- join29(configDir, "bin"),
70514
- join29(configDir, "node_modules", ".bin"),
70515
- join29(dataDir, "bin"),
70516
- join29(dataDir, "bin", "node_modules", ".bin")
70763
+ join32(workingDirectory, "node_modules", ".bin"),
70764
+ join32(configDir, "bin"),
70765
+ join32(configDir, "node_modules", ".bin"),
70766
+ join32(dataDir, "bin"),
70767
+ join32(dataDir, "bin", "node_modules", ".bin")
70517
70768
  ];
70518
70769
  }
70519
70770
 
@@ -70523,7 +70774,7 @@ function isServerInstalled(command) {
70523
70774
  return false;
70524
70775
  const cmd = command[0];
70525
70776
  if (cmd.includes("/") || cmd.includes("\\")) {
70526
- if (existsSync29(cmd))
70777
+ if (existsSync31(cmd))
70527
70778
  return true;
70528
70779
  }
70529
70780
  const isWindows = process.platform === "win32";
@@ -70544,14 +70795,14 @@ function isServerInstalled(command) {
70544
70795
  const paths = pathEnv.split(delimiter2);
70545
70796
  for (const p2 of paths) {
70546
70797
  for (const suffix of exts) {
70547
- if (existsSync29(join30(p2, cmd + suffix))) {
70798
+ if (existsSync31(join33(p2, cmd + suffix))) {
70548
70799
  return true;
70549
70800
  }
70550
70801
  }
70551
70802
  }
70552
70803
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
70553
70804
  for (const suffix of exts) {
70554
- if (existsSync29(join30(base, cmd + suffix))) {
70805
+ if (existsSync31(join33(base, cmd + suffix))) {
70555
70806
  return true;
70556
70807
  }
70557
70808
  }
@@ -70613,24 +70864,24 @@ function getInstalledLspServers() {
70613
70864
 
70614
70865
  // src/cli/doctor/checks/tools-mcp.ts
70615
70866
  init_shared();
70616
- import { existsSync as existsSync30, readFileSync as readFileSync27 } from "fs";
70867
+ import { existsSync as existsSync32, readFileSync as readFileSync28 } from "fs";
70617
70868
  import { homedir as homedir8 } from "os";
70618
- import { join as join31 } from "path";
70869
+ import { join as join34 } from "path";
70619
70870
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
70620
70871
  function getMcpConfigPaths() {
70621
70872
  return [
70622
- join31(homedir8(), ".claude", ".mcp.json"),
70623
- join31(process.cwd(), ".mcp.json"),
70624
- join31(process.cwd(), ".claude", ".mcp.json")
70873
+ join34(homedir8(), ".claude", ".mcp.json"),
70874
+ join34(process.cwd(), ".mcp.json"),
70875
+ join34(process.cwd(), ".claude", ".mcp.json")
70625
70876
  ];
70626
70877
  }
70627
70878
  function loadUserMcpConfig() {
70628
70879
  const servers = {};
70629
70880
  for (const configPath of getMcpConfigPaths()) {
70630
- if (!existsSync30(configPath))
70881
+ if (!existsSync32(configPath))
70631
70882
  continue;
70632
70883
  try {
70633
- const content = readFileSync27(configPath, "utf-8");
70884
+ const content = readFileSync28(configPath, "utf-8");
70634
70885
  const config2 = parseJsonc(content);
70635
70886
  if (config2.mcpServers) {
70636
70887
  Object.assign(servers, config2.mcpServers);
@@ -71083,11 +71334,11 @@ async function refreshModelCapabilities(options, deps = {}) {
71083
71334
 
71084
71335
  // src/features/mcp-oauth/storage.ts
71085
71336
  init_shared();
71086
- import { chmodSync, existsSync as existsSync31, mkdirSync as mkdirSync8, readFileSync as readFileSync28, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
71087
- import { dirname as dirname10, join as join32 } from "path";
71337
+ import { chmodSync, existsSync as existsSync33, mkdirSync as mkdirSync8, readFileSync as readFileSync29, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
71338
+ import { dirname as dirname10, join as join35 } from "path";
71088
71339
  var STORAGE_FILE_NAME = "mcp-oauth.json";
71089
71340
  function getMcpOauthStoragePath() {
71090
- return join32(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71341
+ return join35(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71091
71342
  }
71092
71343
  function normalizeHost(serverHost) {
71093
71344
  let host = serverHost.trim();
@@ -71124,11 +71375,11 @@ function buildKey(serverHost, resource) {
71124
71375
  }
71125
71376
  function readStore() {
71126
71377
  const filePath = getMcpOauthStoragePath();
71127
- if (!existsSync31(filePath)) {
71378
+ if (!existsSync33(filePath)) {
71128
71379
  return null;
71129
71380
  }
71130
71381
  try {
71131
- const content = readFileSync28(filePath, "utf-8");
71382
+ const content = readFileSync29(filePath, "utf-8");
71132
71383
  return JSON.parse(content);
71133
71384
  } catch {
71134
71385
  return null;
@@ -71138,7 +71389,7 @@ function writeStore(store2) {
71138
71389
  const filePath = getMcpOauthStoragePath();
71139
71390
  try {
71140
71391
  const dir = dirname10(filePath);
71141
- if (!existsSync31(dir)) {
71392
+ if (!existsSync33(dir)) {
71142
71393
  mkdirSync8(dir, { recursive: true });
71143
71394
  }
71144
71395
  writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
@@ -71173,7 +71424,7 @@ function deleteToken(serverHost, resource) {
71173
71424
  if (Object.keys(store2).length === 0) {
71174
71425
  try {
71175
71426
  const filePath = getMcpOauthStoragePath();
71176
- if (existsSync31(filePath)) {
71427
+ if (existsSync33(filePath)) {
71177
71428
  unlinkSync4(filePath);
71178
71429
  }
71179
71430
  return true;
@@ -71396,7 +71647,7 @@ function startCallbackServer(port) {
71396
71647
  clearTimeout(timeoutId);
71397
71648
  const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
71398
71649
  const code = requestUrl.searchParams.get("code");
71399
- const state = requestUrl.searchParams.get("state");
71650
+ const state2 = requestUrl.searchParams.get("state");
71400
71651
  const error48 = requestUrl.searchParams.get("error");
71401
71652
  if (error48) {
71402
71653
  const errorDescription = requestUrl.searchParams.get("error_description") ?? error48;
@@ -71406,7 +71657,7 @@ function startCallbackServer(port) {
71406
71657
  reject(new Error(`OAuth authorization error: ${errorDescription}`));
71407
71658
  return;
71408
71659
  }
71409
- if (!code || !state) {
71660
+ if (!code || !state2) {
71410
71661
  response.writeHead(400, { "content-type": "text/html" });
71411
71662
  response.end("<html><body><h1>Missing code or state</h1></body></html>");
71412
71663
  server2.close();
@@ -71416,7 +71667,7 @@ function startCallbackServer(port) {
71416
71667
  response.writeHead(200, { "content-type": "text/html" });
71417
71668
  response.end("<html><body><h1>Authorization successful. You can close this tab.</h1></body></html>");
71418
71669
  server2.close();
71419
- resolve2({ code, state });
71670
+ resolve2({ code, state: state2 });
71420
71671
  });
71421
71672
  timeoutId = setTimeout(() => {
71422
71673
  server2.close();
@@ -71452,19 +71703,19 @@ function openBrowser(url2) {
71452
71703
  async function runAuthorizationCodeRedirect(options) {
71453
71704
  const verifier = generateCodeVerifier();
71454
71705
  const challenge = generateCodeChallenge(verifier);
71455
- const state = randomBytes2(16).toString("hex");
71706
+ const state2 = randomBytes2(16).toString("hex");
71456
71707
  const authorizationUrl = buildAuthorizationUrl(options.authorizationEndpoint, {
71457
71708
  clientId: options.clientId,
71458
71709
  redirectUri: options.redirectUri,
71459
71710
  codeChallenge: challenge,
71460
- state,
71711
+ state: state2,
71461
71712
  scopes: options.scopes,
71462
71713
  resource: options.resource
71463
71714
  });
71464
71715
  const callbackPromise = startCallbackServer(options.callbackPort);
71465
71716
  openBrowser(authorizationUrl);
71466
71717
  const result = await callbackPromise;
71467
- if (result.state !== state) {
71718
+ if (result.state !== state2) {
71468
71719
  throw new Error("OAuth state mismatch");
71469
71720
  }
71470
71721
  return { code: result.code, verifier };