oh-my-opencode 3.15.2 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/agents/dynamic-agent-core-sections.d.ts +7 -0
  2. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -1
  3. package/dist/cli/config-manager/backup-config.d.ts +6 -0
  4. package/dist/cli/config-manager/version-compatibility.d.ts +9 -0
  5. package/dist/cli/config-manager.d.ts +4 -0
  6. package/dist/cli/doctor/constants.d.ts +1 -1
  7. package/dist/cli/index.js +1691 -552
  8. package/dist/cli/minimum-opencode-version.d.ts +1 -0
  9. package/dist/cli/model-fallback-types.d.ts +3 -0
  10. package/dist/cli/run/continuation-state.d.ts +2 -1
  11. package/dist/cli/types.d.ts +1 -0
  12. package/dist/create-managers.d.ts +14 -0
  13. package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +5 -2
  14. package/dist/features/boulder-state/storage.d.ts +8 -1
  15. package/dist/features/boulder-state/types.d.ts +1 -0
  16. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +1 -1
  17. package/dist/features/claude-code-mcp-loader/env-expander.d.ts +5 -2
  18. package/dist/features/claude-code-plugin-loader/loader.d.ts +15 -0
  19. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +2 -0
  20. package/dist/features/claude-code-plugin-loader/types.d.ts +11 -0
  21. package/dist/features/claude-code-session-state/state.d.ts +1 -0
  22. package/dist/features/mcp-oauth/provider.d.ts +1 -0
  23. package/dist/features/mcp-oauth/refresh-mutex.d.ts +26 -0
  24. package/dist/features/skill-mcp-manager/error-redaction.d.ts +10 -0
  25. package/dist/features/skill-mcp-manager/oauth-handler.d.ts +7 -0
  26. package/dist/features/skill-mcp-manager/types.d.ts +3 -1
  27. package/dist/hooks/atlas/background-launch-session-tracking.d.ts +11 -0
  28. package/dist/hooks/atlas/boulder-continuation-injector.d.ts +2 -1
  29. package/dist/hooks/atlas/task-context.d.ts +7 -0
  30. package/dist/hooks/atlas/types.d.ts +2 -0
  31. package/dist/hooks/auto-update-checker/constants.d.ts +2 -2
  32. package/dist/hooks/keyword-detector/hook.d.ts +2 -1
  33. package/dist/hooks/ralph-loop/constants.d.ts +1 -0
  34. package/dist/hooks/ralph-loop/oracle-verification-detector.d.ts +8 -0
  35. package/dist/hooks/read-image-resizer/png-fallback-resizer.d.ts +2 -0
  36. package/dist/hooks/runtime-fallback/auto-retry-signal.d.ts +4 -0
  37. package/dist/hooks/runtime-fallback/error-classifier.d.ts +1 -5
  38. package/dist/hooks/session-recovery/types.d.ts +2 -0
  39. package/dist/hooks/todo-continuation-enforcer/pending-question-detection.d.ts +1 -1
  40. package/dist/hooks/todo-continuation-enforcer/token-limit-detection.d.ts +4 -0
  41. package/dist/hooks/todo-continuation-enforcer/types.d.ts +7 -0
  42. package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
  43. package/dist/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.d.ts +2 -0
  44. package/dist/index.js +2439 -1222
  45. package/dist/plugin/chat-params.d.ts +1 -0
  46. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  47. package/dist/shared/agent-display-names.d.ts +10 -2
  48. package/dist/shared/compaction-marker.d.ts +12 -0
  49. package/dist/shared/index.d.ts +1 -0
  50. package/dist/shared/internal-initiator-marker.d.ts +1 -0
  51. package/dist/shared/session-prompt-params-state.d.ts +1 -0
  52. package/dist/tools/background-task/constants.d.ts +1 -1
  53. package/dist/tools/delegate-task/resolve-call-id.d.ts +2 -0
  54. package/package.json +16 -18
  55. package/postinstall.mjs +63 -1
package/dist/cli/index.js CHANGED
@@ -5977,9 +5977,13 @@ var PLUGIN_NAME = "oh-my-openagent", LEGACY_PLUGIN_NAME = "oh-my-opencode", CONF
5977
5977
  // src/shared/jsonc-parser.ts
5978
5978
  import { existsSync, readFileSync } from "fs";
5979
5979
  import { join as join3 } from "path";
5980
+ function stripBom(content) {
5981
+ return content.charCodeAt(0) === 65279 ? content.slice(1) : content;
5982
+ }
5980
5983
  function parseJsonc(content) {
5984
+ content = content.replace(/^\uFEFF/, "");
5981
5985
  const errors = [];
5982
- const result = parse2(content, errors, {
5986
+ const result = parse2(stripBom(content), errors, {
5983
5987
  allowTrailingComma: true,
5984
5988
  disallowComments: false
5985
5989
  });
@@ -6042,15 +6046,15 @@ var init_agent_names = __esm(() => {
6042
6046
  "omo-plan": "prometheus",
6043
6047
  "Planner-Sisyphus": "prometheus",
6044
6048
  "planner-sisyphus": "prometheus",
6045
- "Prometheus (Planner)": "prometheus",
6049
+ "Prometheus - Plan Builder": "prometheus",
6046
6050
  prometheus: "prometheus",
6047
6051
  "orchestrator-sisyphus": "atlas",
6048
6052
  Atlas: "atlas",
6049
6053
  atlas: "atlas",
6050
6054
  "plan-consultant": "metis",
6051
- "Metis (Plan Consultant)": "metis",
6055
+ "Metis - Plan Consultant": "metis",
6052
6056
  metis: "metis",
6053
- "Momus (Plan Reviewer)": "momus",
6057
+ "Momus - Plan Critic": "momus",
6054
6058
  momus: "momus",
6055
6059
  "Sisyphus-Junior": "sisyphus-junior",
6056
6060
  "sisyphus-junior": "sisyphus-junior",
@@ -6367,18 +6371,88 @@ var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai
6367
6371
  var init_opencode_config_dir = () => {};
6368
6372
 
6369
6373
  // src/shared/opencode-version.ts
6370
- var NOT_CACHED;
6374
+ import { execSync } from "child_process";
6375
+ function parseVersion(version) {
6376
+ const cleaned = version.replace(/^v/, "").split("-")[0];
6377
+ return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
6378
+ }
6379
+ function compareVersions(a, b) {
6380
+ const partsA = parseVersion(a);
6381
+ const partsB = parseVersion(b);
6382
+ const maxLen = Math.max(partsA.length, partsB.length);
6383
+ for (let i2 = 0;i2 < maxLen; i2++) {
6384
+ const numA = partsA[i2] ?? 0;
6385
+ const numB = partsB[i2] ?? 0;
6386
+ if (numA < numB)
6387
+ return -1;
6388
+ if (numA > numB)
6389
+ return 1;
6390
+ }
6391
+ return 0;
6392
+ }
6393
+ function getOpenCodeVersion() {
6394
+ if (cachedVersion !== NOT_CACHED) {
6395
+ return cachedVersion;
6396
+ }
6397
+ try {
6398
+ const result = execSync("opencode --version", {
6399
+ encoding: "utf-8",
6400
+ timeout: 5000,
6401
+ stdio: ["pipe", "pipe", "pipe"]
6402
+ }).trim();
6403
+ const versionMatch = result.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
6404
+ cachedVersion = versionMatch?.[1] ?? null;
6405
+ return cachedVersion;
6406
+ } catch {
6407
+ cachedVersion = null;
6408
+ return null;
6409
+ }
6410
+ }
6411
+ function isOpenCodeVersionAtLeast(version) {
6412
+ const current = getOpenCodeVersion();
6413
+ if (!current)
6414
+ return true;
6415
+ return compareVersions(current, version) >= 0;
6416
+ }
6417
+ var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion;
6371
6418
  var init_opencode_version = __esm(() => {
6372
6419
  NOT_CACHED = Symbol("NOT_CACHED");
6420
+ cachedVersion = NOT_CACHED;
6373
6421
  });
6374
6422
 
6375
6423
  // src/shared/opencode-storage-detection.ts
6376
- var NOT_CACHED2, FALSE_PENDING_RETRY;
6424
+ import { existsSync as existsSync3 } from "fs";
6425
+ import { join as join5 } from "path";
6426
+ function isSqliteBackend() {
6427
+ if (cachedResult === true)
6428
+ return true;
6429
+ if (cachedResult === false)
6430
+ return false;
6431
+ const check = () => {
6432
+ const versionOk = isOpenCodeVersionAtLeast(OPENCODE_SQLITE_VERSION);
6433
+ const dbPath = join5(getDataDir(), "opencode", "opencode.db");
6434
+ return versionOk && existsSync3(dbPath);
6435
+ };
6436
+ if (cachedResult === FALSE_PENDING_RETRY) {
6437
+ const result2 = check();
6438
+ cachedResult = result2;
6439
+ return result2;
6440
+ }
6441
+ const result = check();
6442
+ if (result) {
6443
+ cachedResult = true;
6444
+ } else {
6445
+ cachedResult = FALSE_PENDING_RETRY;
6446
+ }
6447
+ return result;
6448
+ }
6449
+ var NOT_CACHED2, FALSE_PENDING_RETRY, cachedResult;
6377
6450
  var init_opencode_storage_detection = __esm(() => {
6378
6451
  init_data_path();
6379
6452
  init_opencode_version();
6380
6453
  NOT_CACHED2 = Symbol("NOT_CACHED");
6381
6454
  FALSE_PENDING_RETRY = Symbol("FALSE_PENDING_RETRY");
6455
+ cachedResult = NOT_CACHED2;
6382
6456
  });
6383
6457
  // src/shared/load-opencode-plugins.ts
6384
6458
  var init_load_opencode_plugins = __esm(() => {
@@ -6793,19 +6867,19 @@ function normalizeModelID(modelID) {
6793
6867
  }
6794
6868
 
6795
6869
  // 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";
6870
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6871
+ import { join as join6 } from "path";
6798
6872
  function toLogLabel(cacheLabel) {
6799
6873
  return cacheLabel.toLowerCase();
6800
6874
  }
6801
6875
  function createJsonFileCacheStore(options) {
6802
6876
  let memoryValue;
6803
6877
  function getCacheFilePath() {
6804
- return join5(options.getCacheDir(), options.filename);
6878
+ return join6(options.getCacheDir(), options.filename);
6805
6879
  }
6806
6880
  function ensureCacheDir() {
6807
6881
  const cacheDir = options.getCacheDir();
6808
- if (!existsSync3(cacheDir)) {
6882
+ if (!existsSync4(cacheDir)) {
6809
6883
  mkdirSync2(cacheDir, { recursive: true });
6810
6884
  }
6811
6885
  }
@@ -6814,7 +6888,7 @@ function createJsonFileCacheStore(options) {
6814
6888
  return memoryValue;
6815
6889
  }
6816
6890
  const cacheFile = getCacheFilePath();
6817
- if (!existsSync3(cacheFile)) {
6891
+ if (!existsSync4(cacheFile)) {
6818
6892
  memoryValue = null;
6819
6893
  log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
6820
6894
  return null;
@@ -6834,7 +6908,7 @@ function createJsonFileCacheStore(options) {
6834
6908
  }
6835
6909
  }
6836
6910
  function has() {
6837
- return existsSync3(getCacheFilePath());
6911
+ return existsSync4(getCacheFilePath());
6838
6912
  }
6839
6913
  function write(value) {
6840
6914
  ensureCacheDir();
@@ -7003,14 +7077,14 @@ var init_connected_providers_cache = __esm(() => {
7003
7077
  });
7004
7078
 
7005
7079
  // src/shared/model-availability.ts
7006
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
7007
- import { join as join6 } from "path";
7080
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
7081
+ import { join as join7 } from "path";
7008
7082
  function isModelCacheAvailable() {
7009
7083
  if (hasProviderModelsCache()) {
7010
7084
  return true;
7011
7085
  }
7012
- const cacheFile = join6(getOpenCodeCacheDir(), "models.json");
7013
- return existsSync4(cacheFile);
7086
+ const cacheFile = join7(getOpenCodeCacheDir(), "models.json");
7087
+ return existsSync5(cacheFile);
7014
7088
  }
7015
7089
  var init_model_availability = __esm(() => {
7016
7090
  init_logger();
@@ -48305,6 +48379,57 @@ var init_constants = __esm(() => {
48305
48379
  init_shared();
48306
48380
  });
48307
48381
 
48382
+ // src/shared/opencode-storage-paths.ts
48383
+ import { join as join8 } from "path";
48384
+ var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48385
+ var init_opencode_storage_paths = __esm(() => {
48386
+ init_data_path();
48387
+ OPENCODE_STORAGE = getOpenCodeStorageDir();
48388
+ MESSAGE_STORAGE = join8(OPENCODE_STORAGE, "message");
48389
+ PART_STORAGE = join8(OPENCODE_STORAGE, "part");
48390
+ SESSION_STORAGE = join8(OPENCODE_STORAGE, "session");
48391
+ });
48392
+
48393
+ // src/shared/compaction-marker.ts
48394
+ import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync4 } from "fs";
48395
+ import { join as join9 } from "path";
48396
+ function isCompactionPart(part) {
48397
+ return typeof part === "object" && part !== null && part.type === "compaction";
48398
+ }
48399
+ function isCompactionAgent(agent) {
48400
+ return typeof agent === "string" && agent.trim().toLowerCase() === "compaction";
48401
+ }
48402
+ function hasCompactionPart(parts) {
48403
+ return Array.isArray(parts) && parts.some((part) => isCompactionPart(part));
48404
+ }
48405
+ function isCompactionMessage(message) {
48406
+ return isCompactionAgent(message.info?.agent ?? message.agent) || hasCompactionPart(message.parts);
48407
+ }
48408
+ function hasCompactionPartInStorage(messageID) {
48409
+ if (!messageID) {
48410
+ return false;
48411
+ }
48412
+ const partDir = join9(PART_STORAGE, messageID);
48413
+ if (!existsSync6(partDir)) {
48414
+ return false;
48415
+ }
48416
+ try {
48417
+ return readdirSync(partDir).filter((fileName) => fileName.endsWith(".json")).some((fileName) => {
48418
+ try {
48419
+ const content = readFileSync4(join9(partDir, fileName), "utf-8");
48420
+ return isCompactionPart(JSON.parse(content));
48421
+ } catch {
48422
+ return false;
48423
+ }
48424
+ });
48425
+ } catch {
48426
+ return false;
48427
+ }
48428
+ }
48429
+ var init_compaction_marker = __esm(() => {
48430
+ init_opencode_storage_paths();
48431
+ });
48432
+
48308
48433
  // src/features/hook-message-injector/injector.ts
48309
48434
  import { randomBytes } from "crypto";
48310
48435
  var processPrefix;
@@ -48313,6 +48438,7 @@ var init_injector = __esm(() => {
48313
48438
  init_logger();
48314
48439
  init_opencode_storage_detection();
48315
48440
  init_shared();
48441
+ init_compaction_marker();
48316
48442
  processPrefix = randomBytes(4).toString("hex");
48317
48443
  });
48318
48444
 
@@ -48322,18 +48448,33 @@ var init_hook_message_injector = __esm(() => {
48322
48448
  init_constants();
48323
48449
  });
48324
48450
 
48325
- // src/shared/opencode-storage-paths.ts
48326
- import { join as join7 } from "path";
48327
- var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48328
- var init_opencode_storage_paths = __esm(() => {
48329
- init_data_path();
48330
- OPENCODE_STORAGE = getOpenCodeStorageDir();
48331
- MESSAGE_STORAGE = join7(OPENCODE_STORAGE, "message");
48332
- PART_STORAGE = join7(OPENCODE_STORAGE, "part");
48333
- SESSION_STORAGE = join7(OPENCODE_STORAGE, "session");
48334
- });
48335
-
48336
48451
  // src/shared/opencode-message-dir.ts
48452
+ import { existsSync as existsSync7, readdirSync as readdirSync2 } from "fs";
48453
+ import { join as join10 } from "path";
48454
+ function getMessageDir(sessionID) {
48455
+ if (!sessionID.startsWith("ses_"))
48456
+ return null;
48457
+ if (/[/\\]|\.\./.test(sessionID))
48458
+ return null;
48459
+ if (!existsSync7(MESSAGE_STORAGE))
48460
+ return null;
48461
+ const directPath = join10(MESSAGE_STORAGE, sessionID);
48462
+ if (existsSync7(directPath)) {
48463
+ return directPath;
48464
+ }
48465
+ try {
48466
+ for (const dir of readdirSync2(MESSAGE_STORAGE)) {
48467
+ const sessionPath = join10(MESSAGE_STORAGE, dir, sessionID);
48468
+ if (existsSync7(sessionPath)) {
48469
+ return sessionPath;
48470
+ }
48471
+ }
48472
+ } catch (error) {
48473
+ log("[opencode-message-dir] Failed to scan message directories", { sessionID, error: String(error) });
48474
+ return null;
48475
+ }
48476
+ return null;
48477
+ }
48337
48478
  var init_opencode_message_dir = __esm(() => {
48338
48479
  init_opencode_storage_paths();
48339
48480
  init_logger();
@@ -48359,22 +48500,25 @@ function getAgentConfigKey(agentName) {
48359
48500
  const reversed = REVERSE_DISPLAY_NAMES[lower];
48360
48501
  if (reversed !== undefined)
48361
48502
  return reversed;
48503
+ const legacy = LEGACY_DISPLAY_NAMES[lower];
48504
+ if (legacy !== undefined)
48505
+ return legacy;
48362
48506
  if (AGENT_DISPLAY_NAMES[lower] !== undefined)
48363
48507
  return lower;
48364
48508
  return lower;
48365
48509
  }
48366
- var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES;
48510
+ var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
48367
48511
  var init_agent_display_names = __esm(() => {
48368
48512
  AGENT_DISPLAY_NAMES = {
48369
- sisyphus: "Sisyphus (Ultraworker)",
48370
- hephaestus: "Hephaestus (Deep Agent)",
48371
- prometheus: "Prometheus (Plan Builder)",
48372
- atlas: "Atlas (Plan Executor)",
48513
+ sisyphus: "Sisyphus - Ultraworker",
48514
+ hephaestus: "Hephaestus - Deep Agent",
48515
+ prometheus: "Prometheus - Plan Builder",
48516
+ atlas: "Atlas - Plan Executor",
48373
48517
  "sisyphus-junior": "Sisyphus-Junior",
48374
- metis: "Metis (Plan Consultant)",
48375
- momus: "Momus (Plan Critic)",
48376
- athena: "Athena (Council)",
48377
- "athena-junior": "Athena-Junior (Council)",
48518
+ metis: "Metis - Plan Consultant",
48519
+ momus: "Momus - Plan Critic",
48520
+ athena: "Athena - Council",
48521
+ "athena-junior": "Athena-Junior - Council",
48378
48522
  oracle: "oracle",
48379
48523
  librarian: "librarian",
48380
48524
  explore: "explore",
@@ -48382,6 +48526,16 @@ var init_agent_display_names = __esm(() => {
48382
48526
  "council-member": "council-member"
48383
48527
  };
48384
48528
  REVERSE_DISPLAY_NAMES = Object.fromEntries(Object.entries(AGENT_DISPLAY_NAMES).map(([key, displayName]) => [displayName.toLowerCase(), key]));
48529
+ LEGACY_DISPLAY_NAMES = {
48530
+ "sisyphus (ultraworker)": "sisyphus",
48531
+ "hephaestus (deep agent)": "hephaestus",
48532
+ "prometheus (plan builder)": "prometheus",
48533
+ "atlas (plan executor)": "atlas",
48534
+ "metis (plan consultant)": "metis",
48535
+ "momus (plan critic)": "momus",
48536
+ "athena (council)": "athena",
48537
+ "athena-junior (council)": "athena-junior"
48538
+ };
48385
48539
  });
48386
48540
 
48387
48541
  // src/shared/session-utils.ts
@@ -48545,9 +48699,18 @@ var init_session_tools_store = __esm(() => {
48545
48699
  var init_prompt_tools = __esm(() => {
48546
48700
  init_session_tools_store();
48547
48701
  });
48702
+
48703
+ // src/shared/internal-initiator-marker.ts
48704
+ var init_internal_initiator_marker = () => {};
48705
+ // src/features/claude-code-plugin-loader/scope-filter.ts
48706
+ var init_scope_filter = __esm(() => {
48707
+ init_contains_path();
48708
+ });
48709
+
48548
48710
  // src/features/claude-code-plugin-loader/discovery.ts
48549
48711
  var init_discovery = __esm(() => {
48550
48712
  init_logger();
48713
+ init_scope_filter();
48551
48714
  });
48552
48715
 
48553
48716
  // src/features/claude-code-plugin-loader/command-loader.ts
@@ -48598,7 +48761,7 @@ var init_env_expander = __esm(() => {
48598
48761
  });
48599
48762
 
48600
48763
  // src/features/claude-code-mcp-loader/scope-filter.ts
48601
- var init_scope_filter = __esm(() => {
48764
+ var init_scope_filter2 = __esm(() => {
48602
48765
  init_contains_path();
48603
48766
  });
48604
48767
 
@@ -48609,7 +48772,7 @@ var init_transformer = __esm(() => {
48609
48772
  // src/features/claude-code-plugin-loader/mcp-server-loader.ts
48610
48773
  var init_mcp_server_loader = __esm(() => {
48611
48774
  init_env_expander();
48612
- init_scope_filter();
48775
+ init_scope_filter2();
48613
48776
  init_transformer();
48614
48777
  init_logger();
48615
48778
  });
@@ -48740,6 +48903,8 @@ var init_shared = __esm(() => {
48740
48903
  init_project_discovery_dirs();
48741
48904
  init_session_directory_resolver();
48742
48905
  init_prompt_tools();
48906
+ init_compaction_marker();
48907
+ init_internal_initiator_marker();
48743
48908
  init_plugin_command_discovery();
48744
48909
  init_log_legacy_plugin_startup_warning();
48745
48910
  });
@@ -48820,12 +48985,37 @@ var init_plugin_name_with_version = __esm(() => {
48820
48985
  PRIORITIZED_TAGS = ["latest", "beta", "next"];
48821
48986
  });
48822
48987
 
48988
+ // src/cli/config-manager/backup-config.ts
48989
+ import { copyFileSync as copyFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync3 } from "fs";
48990
+ import { dirname } from "path";
48991
+ function backupConfigFile(configPath) {
48992
+ if (!existsSync8(configPath)) {
48993
+ return { success: true };
48994
+ }
48995
+ const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
48996
+ const backupPath = `${configPath}.backup-${timestamp2}`;
48997
+ try {
48998
+ const dir = dirname(backupPath);
48999
+ if (!existsSync8(dir)) {
49000
+ mkdirSync3(dir, { recursive: true });
49001
+ }
49002
+ copyFileSync2(configPath, backupPath);
49003
+ return { success: true, backupPath };
49004
+ } catch (err) {
49005
+ return {
49006
+ success: false,
49007
+ error: err instanceof Error ? err.message : "Failed to create backup"
49008
+ };
49009
+ }
49010
+ }
49011
+ var init_backup_config = () => {};
49012
+
48823
49013
  // src/cli/config-manager/ensure-config-directory-exists.ts
48824
- import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
49014
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
48825
49015
  function ensureConfigDirectoryExists() {
48826
49016
  const configDir = getConfigDir();
48827
- if (!existsSync5(configDir)) {
48828
- mkdirSync3(configDir, { recursive: true });
49017
+ if (!existsSync9(configDir)) {
49018
+ mkdirSync4(configDir, { recursive: true });
48829
49019
  }
48830
49020
  }
48831
49021
  var init_ensure_config_directory_exists = __esm(() => {
@@ -48862,14 +49052,14 @@ function formatErrorWithSuggestion(err, context) {
48862
49052
  }
48863
49053
 
48864
49054
  // src/cli/config-manager/opencode-config-format.ts
48865
- import { existsSync as existsSync6 } from "fs";
49055
+ import { existsSync as existsSync10 } from "fs";
48866
49056
  function detectConfigFormat() {
48867
49057
  const configJsonc = getConfigJsonc();
48868
49058
  const configJson = getConfigJson();
48869
- if (existsSync6(configJsonc)) {
49059
+ if (existsSync10(configJsonc)) {
48870
49060
  return { format: "jsonc", path: configJsonc };
48871
49061
  }
48872
- if (existsSync6(configJson)) {
49062
+ if (existsSync10(configJson)) {
48873
49063
  return { format: "json", path: configJson };
48874
49064
  }
48875
49065
  return { format: "none", path: configJson };
@@ -48879,7 +49069,7 @@ var init_opencode_config_format = __esm(() => {
48879
49069
  });
48880
49070
 
48881
49071
  // src/cli/config-manager/parse-opencode-config-file.ts
48882
- import { readFileSync as readFileSync4, statSync } from "fs";
49072
+ import { readFileSync as readFileSync5, statSync } from "fs";
48883
49073
  function isEmptyOrWhitespace(content) {
48884
49074
  return content.trim().length === 0;
48885
49075
  }
@@ -48889,7 +49079,7 @@ function parseOpenCodeConfigFileWithError(path3) {
48889
49079
  if (stat.size === 0) {
48890
49080
  return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
48891
49081
  }
48892
- const content = readFileSync4(path3, "utf-8");
49082
+ const content = readFileSync5(path3, "utf-8");
48893
49083
  if (isEmptyOrWhitespace(content)) {
48894
49084
  return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
48895
49085
  }
@@ -48912,8 +49102,90 @@ var init_parse_opencode_config_file = __esm(() => {
48912
49102
  init_shared();
48913
49103
  });
48914
49104
 
49105
+ // src/cli/config-manager/version-compatibility.ts
49106
+ function parseVersion2(version) {
49107
+ const clean = version.replace(/^v/, "").split("-")[0];
49108
+ return clean.split(".").map(Number);
49109
+ }
49110
+ function compareVersions2(a, b) {
49111
+ const partsA = parseVersion2(a);
49112
+ const partsB = parseVersion2(b);
49113
+ const maxLen = Math.max(partsA.length, partsB.length);
49114
+ for (let i2 = 0;i2 < maxLen; i2++) {
49115
+ const numA = partsA[i2] ?? 0;
49116
+ const numB = partsB[i2] ?? 0;
49117
+ if (numA !== numB) {
49118
+ return numA - numB;
49119
+ }
49120
+ }
49121
+ return 0;
49122
+ }
49123
+ function checkVersionCompatibility(currentVersion, newVersion) {
49124
+ if (!currentVersion) {
49125
+ return {
49126
+ canUpgrade: true,
49127
+ isDowngrade: false,
49128
+ isMajorBump: false,
49129
+ requiresMigration: false
49130
+ };
49131
+ }
49132
+ const cleanCurrent = currentVersion.replace(/^v/, "");
49133
+ const cleanNew = newVersion.replace(/^v/, "");
49134
+ try {
49135
+ const comparison = compareVersions2(cleanNew, cleanCurrent);
49136
+ if (comparison < 0) {
49137
+ return {
49138
+ canUpgrade: false,
49139
+ reason: `Downgrade from ${currentVersion} to ${newVersion} is not allowed`,
49140
+ isDowngrade: true,
49141
+ isMajorBump: false,
49142
+ requiresMigration: false
49143
+ };
49144
+ }
49145
+ if (comparison === 0) {
49146
+ return {
49147
+ canUpgrade: true,
49148
+ reason: `Version ${newVersion} is already installed`,
49149
+ isDowngrade: false,
49150
+ isMajorBump: false,
49151
+ requiresMigration: false
49152
+ };
49153
+ }
49154
+ const currentMajor = cleanCurrent.split(".")[0];
49155
+ const newMajor = cleanNew.split(".")[0];
49156
+ const isMajorBump = currentMajor !== newMajor;
49157
+ if (isMajorBump) {
49158
+ return {
49159
+ canUpgrade: true,
49160
+ reason: `Major version upgrade from ${currentVersion} to ${newVersion} - configuration migration may be required`,
49161
+ isDowngrade: false,
49162
+ isMajorBump: true,
49163
+ requiresMigration: true
49164
+ };
49165
+ }
49166
+ return {
49167
+ canUpgrade: true,
49168
+ isDowngrade: false,
49169
+ isMajorBump: false,
49170
+ requiresMigration: false
49171
+ };
49172
+ } catch {
49173
+ return {
49174
+ canUpgrade: true,
49175
+ reason: `Unable to compare versions ${currentVersion} and ${newVersion} - proceeding with caution`,
49176
+ isDowngrade: false,
49177
+ isMajorBump: false,
49178
+ requiresMigration: false
49179
+ };
49180
+ }
49181
+ }
49182
+ function extractVersionFromPluginEntry(entry) {
49183
+ const match = entry.match(/@(.+)$/);
49184
+ return match ? match[1] : null;
49185
+ }
49186
+
48915
49187
  // src/cli/config-manager/add-plugin-to-opencode-config.ts
48916
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
49188
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
48917
49189
  async function addPluginToOpenCodeConfig(currentVersion) {
48918
49190
  try {
48919
49191
  ensureConfigDirectoryExists();
@@ -48946,19 +49218,35 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48946
49218
  const canonicalEntries = plugins.filter((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`));
48947
49219
  const legacyEntries = plugins.filter((plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`));
48948
49220
  const otherPlugins = plugins.filter((plugin) => !(plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`)) && !(plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)));
49221
+ const existingEntry = canonicalEntries[0] ?? legacyEntries[0];
49222
+ if (existingEntry) {
49223
+ const installedVersion = extractVersionFromPluginEntry(existingEntry);
49224
+ const compatibility = checkVersionCompatibility(installedVersion, currentVersion);
49225
+ if (!compatibility.canUpgrade) {
49226
+ return {
49227
+ success: false,
49228
+ configPath: path3,
49229
+ error: compatibility.reason ?? "Version compatibility check failed"
49230
+ };
49231
+ }
49232
+ const backupResult = backupConfigFile(path3);
49233
+ if (!backupResult.success) {
49234
+ return {
49235
+ success: false,
49236
+ configPath: path3,
49237
+ error: `Failed to create backup: ${backupResult.error}`
49238
+ };
49239
+ }
49240
+ }
48949
49241
  const normalizedPlugins = [...otherPlugins];
48950
- if (canonicalEntries.length > 0) {
48951
- normalizedPlugins.push(canonicalEntries[0]);
48952
- } else if (legacyEntries.length > 0) {
48953
- const versionMatch = legacyEntries[0].match(/@(.+)$/);
48954
- const preservedVersion = versionMatch ? versionMatch[1] : null;
48955
- normalizedPlugins.push(preservedVersion ? `${PLUGIN_NAME}@${preservedVersion}` : pluginEntry);
49242
+ if (canonicalEntries.length > 0 || legacyEntries.length > 0) {
49243
+ normalizedPlugins.push(pluginEntry);
48956
49244
  } else {
48957
49245
  normalizedPlugins.push(pluginEntry);
48958
49246
  }
48959
49247
  config.plugin = normalizedPlugins;
48960
49248
  if (format2 === "jsonc") {
48961
- const content = readFileSync5(path3, "utf-8");
49249
+ const content = readFileSync6(path3, "utf-8");
48962
49250
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
48963
49251
  const match = content.match(pluginArrayRegex);
48964
49252
  if (match) {
@@ -48988,6 +49276,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48988
49276
  }
48989
49277
  var init_add_plugin_to_opencode_config = __esm(() => {
48990
49278
  init_shared();
49279
+ init_backup_config();
48991
49280
  init_config_context();
48992
49281
  init_ensure_config_directory_exists();
48993
49282
  init_opencode_config_format();
@@ -49103,6 +49392,47 @@ var init_fallback_chain_resolution = __esm(() => {
49103
49392
  });
49104
49393
 
49105
49394
  // src/cli/model-fallback.ts
49395
+ function toFallbackModelObject(entry, provider) {
49396
+ return {
49397
+ model: `${provider}/${transformModelForProvider(provider, entry.model)}`,
49398
+ ...entry.variant ? { variant: entry.variant } : {},
49399
+ ...entry.reasoningEffort ? { reasoningEffort: entry.reasoningEffort } : {},
49400
+ ...entry.temperature !== undefined ? { temperature: entry.temperature } : {},
49401
+ ...entry.top_p !== undefined ? { top_p: entry.top_p } : {},
49402
+ ...entry.maxTokens !== undefined ? { maxTokens: entry.maxTokens } : {},
49403
+ ...entry.thinking ? { thinking: entry.thinking } : {}
49404
+ };
49405
+ }
49406
+ function collectAvailableFallbacks(fallbackChain, availability) {
49407
+ const expandedFallbacks = fallbackChain.flatMap((entry) => entry.providers.filter((provider) => isProviderAvailable(provider, availability)).map((provider) => toFallbackModelObject(entry, provider)));
49408
+ return expandedFallbacks.filter((entry, index, allEntries) => allEntries.findIndex((candidate) => candidate.model === entry.model && candidate.variant === entry.variant) === index);
49409
+ }
49410
+ function attachFallbackModels(config, fallbackChain, availability) {
49411
+ const uniqueFallbacks = collectAvailableFallbacks(fallbackChain, availability);
49412
+ const primaryIndex = uniqueFallbacks.findIndex((entry) => entry.model === config.model);
49413
+ if (primaryIndex === -1) {
49414
+ return config;
49415
+ }
49416
+ const fallbackModels = uniqueFallbacks.slice(primaryIndex + 1);
49417
+ if (fallbackModels.length === 0) {
49418
+ return config;
49419
+ }
49420
+ return {
49421
+ ...config,
49422
+ fallback_models: fallbackModels
49423
+ };
49424
+ }
49425
+ function attachAllFallbackModels(config, fallbackChain, availability) {
49426
+ const uniqueFallbacks = collectAvailableFallbacks(fallbackChain, availability);
49427
+ const fallbackModels = uniqueFallbacks.filter((entry) => entry.model !== config.model);
49428
+ if (fallbackModels.length === 0) {
49429
+ return config;
49430
+ }
49431
+ return {
49432
+ ...config,
49433
+ fallback_models: fallbackModels
49434
+ };
49435
+ }
49106
49436
  function generateModelConfig(config) {
49107
49437
  const avail = toProviderAvailability(config);
49108
49438
  const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai || avail.kimiForCoding || avail.opencodeGo;
@@ -49117,25 +49447,31 @@ function generateModelConfig(config) {
49117
49447
  const categories = {};
49118
49448
  for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
49119
49449
  if (role === "librarian") {
49450
+ let agentConfig;
49120
49451
  if (avail.opencodeGo) {
49121
- agents[role] = { model: "opencode-go/minimax-m2.7" };
49452
+ agentConfig = { model: "opencode-go/minimax-m2.7" };
49122
49453
  } else if (avail.zai) {
49123
- agents[role] = { model: ZAI_MODEL };
49454
+ agentConfig = { model: ZAI_MODEL };
49455
+ }
49456
+ if (agentConfig) {
49457
+ agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
49124
49458
  }
49125
49459
  continue;
49126
49460
  }
49127
49461
  if (role === "explore") {
49462
+ let agentConfig;
49128
49463
  if (avail.native.claude) {
49129
- agents[role] = { model: "anthropic/claude-haiku-4-5" };
49464
+ agentConfig = { model: "anthropic/claude-haiku-4-5" };
49130
49465
  } else if (avail.opencodeZen) {
49131
- agents[role] = { model: "opencode/claude-haiku-4-5" };
49466
+ agentConfig = { model: "opencode/claude-haiku-4-5" };
49132
49467
  } else if (avail.opencodeGo) {
49133
- agents[role] = { model: "opencode-go/minimax-m2.7" };
49468
+ agentConfig = { model: "opencode-go/minimax-m2.7" };
49134
49469
  } else if (avail.copilot) {
49135
- agents[role] = { model: "github-copilot/gpt-5-mini" };
49470
+ agentConfig = { model: "github-copilot/gpt-5-mini" };
49136
49471
  } else {
49137
- agents[role] = { model: "opencode/gpt-5-nano" };
49472
+ agentConfig = { model: "opencode/gpt-5-nano" };
49138
49473
  }
49474
+ agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
49139
49475
  continue;
49140
49476
  }
49141
49477
  if (role === "sisyphus") {
@@ -49146,7 +49482,8 @@ function generateModelConfig(config) {
49146
49482
  const resolved2 = resolveModelFromChain(fallbackChain, avail);
49147
49483
  if (resolved2) {
49148
49484
  const variant = resolved2.variant ?? req.variant;
49149
- agents[role] = variant ? { model: resolved2.model, variant } : { model: resolved2.model };
49485
+ const agentConfig = variant ? { model: resolved2.model, variant } : { model: resolved2.model };
49486
+ agents[role] = attachFallbackModels(agentConfig, fallbackChain, avail);
49150
49487
  }
49151
49488
  continue;
49152
49489
  }
@@ -49159,7 +49496,8 @@ function generateModelConfig(config) {
49159
49496
  const resolved = resolveModelFromChain(req.fallbackChain, avail);
49160
49497
  if (resolved) {
49161
49498
  const variant = resolved.variant ?? req.variant;
49162
- agents[role] = variant ? { model: resolved.model, variant } : { model: resolved.model };
49499
+ const agentConfig = variant ? { model: resolved.model, variant } : { model: resolved.model };
49500
+ agents[role] = attachFallbackModels(agentConfig, req.fallbackChain, avail);
49163
49501
  } else {
49164
49502
  agents[role] = { model: ULTIMATE_FALLBACK };
49165
49503
  }
@@ -49175,7 +49513,8 @@ function generateModelConfig(config) {
49175
49513
  const resolved = resolveModelFromChain(fallbackChain, avail);
49176
49514
  if (resolved) {
49177
49515
  const variant = resolved.variant ?? req.variant;
49178
- categories[cat] = variant ? { model: resolved.model, variant } : { model: resolved.model };
49516
+ const categoryConfig = variant ? { model: resolved.model, variant } : { model: resolved.model };
49517
+ categories[cat] = attachFallbackModels(categoryConfig, fallbackChain, avail);
49179
49518
  } else {
49180
49519
  categories[cat] = { model: ULTIMATE_FALLBACK };
49181
49520
  }
@@ -49192,6 +49531,7 @@ var init_model_fallback = __esm(() => {
49192
49531
  init_model_fallback_requirements();
49193
49532
  init_openai_only_model_catalog();
49194
49533
  init_fallback_chain_resolution();
49534
+ init_provider_model_id_transform();
49195
49535
  });
49196
49536
 
49197
49537
  // src/cli/config-manager/generate-omo-config.ts
@@ -49220,7 +49560,7 @@ function deepMergeRecord(target, source) {
49220
49560
  }
49221
49561
 
49222
49562
  // src/cli/config-manager/write-omo-config.ts
49223
- import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49563
+ import { existsSync as existsSync11, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49224
49564
  function isEmptyOrWhitespace2(content) {
49225
49565
  return content.trim().length === 0;
49226
49566
  }
@@ -49237,10 +49577,18 @@ function writeOmoConfig(installConfig) {
49237
49577
  const omoConfigPath = getOmoConfigPath();
49238
49578
  try {
49239
49579
  const newConfig = generateOmoConfig(installConfig);
49240
- if (existsSync7(omoConfigPath)) {
49580
+ if (existsSync11(omoConfigPath)) {
49581
+ const backupResult = backupConfigFile(omoConfigPath);
49582
+ if (!backupResult.success) {
49583
+ return {
49584
+ success: false,
49585
+ configPath: omoConfigPath,
49586
+ error: `Failed to create backup: ${backupResult.error}`
49587
+ };
49588
+ }
49241
49589
  try {
49242
49590
  const stat = statSync2(omoConfigPath);
49243
- const content = readFileSync6(omoConfigPath, "utf-8");
49591
+ const content = readFileSync7(omoConfigPath, "utf-8");
49244
49592
  if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
49245
49593
  writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49246
49594
  `);
@@ -49278,6 +49626,7 @@ function writeOmoConfig(installConfig) {
49278
49626
  }
49279
49627
  var init_write_omo_config = __esm(() => {
49280
49628
  init_shared();
49629
+ init_backup_config();
49281
49630
  init_config_context();
49282
49631
  init_ensure_config_directory_exists();
49283
49632
  init_generate_omo_config();
@@ -49368,7 +49717,7 @@ async function isOpenCodeInstalled() {
49368
49717
  const result = await findOpenCodeBinaryWithVersion();
49369
49718
  return result !== null;
49370
49719
  }
49371
- async function getOpenCodeVersion() {
49720
+ async function getOpenCodeVersion2() {
49372
49721
  const result = await findOpenCodeBinaryWithVersion();
49373
49722
  return result?.version ?? null;
49374
49723
  }
@@ -49380,10 +49729,10 @@ var init_opencode_binary = __esm(() => {
49380
49729
  });
49381
49730
 
49382
49731
  // src/cli/config-manager/detect-current-config.ts
49383
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
49732
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
49384
49733
  function detectProvidersFromOmoConfig() {
49385
49734
  const omoConfigPath = getOmoConfigPath();
49386
- if (!existsSync8(omoConfigPath)) {
49735
+ if (!existsSync12(omoConfigPath)) {
49387
49736
  return {
49388
49737
  hasOpenAI: true,
49389
49738
  hasOpencodeZen: true,
@@ -49393,7 +49742,7 @@ function detectProvidersFromOmoConfig() {
49393
49742
  };
49394
49743
  }
49395
49744
  try {
49396
- const content = readFileSync7(omoConfigPath, "utf-8");
49745
+ const content = readFileSync8(omoConfigPath, "utf-8");
49397
49746
  const omoConfig = parseJsonc(content);
49398
49747
  if (!omoConfig || typeof omoConfig !== "object") {
49399
49748
  return {
@@ -49424,9 +49773,13 @@ function detectProvidersFromOmoConfig() {
49424
49773
  function isOurPlugin(plugin) {
49425
49774
  return plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) || plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`);
49426
49775
  }
49776
+ function findOurPluginEntry(plugins) {
49777
+ return plugins.find(isOurPlugin) ?? null;
49778
+ }
49427
49779
  function detectCurrentConfig() {
49428
49780
  const result = {
49429
49781
  isInstalled: false,
49782
+ installedVersion: null,
49430
49783
  hasClaude: true,
49431
49784
  isMax20: true,
49432
49785
  hasOpenAI: true,
@@ -49447,7 +49800,11 @@ function detectCurrentConfig() {
49447
49800
  }
49448
49801
  const openCodeConfig = parseResult.config;
49449
49802
  const plugins = openCodeConfig.plugin ?? [];
49450
- result.isInstalled = plugins.some(isOurPlugin);
49803
+ const ourPluginEntry = findOurPluginEntry(plugins);
49804
+ result.isInstalled = !!ourPluginEntry;
49805
+ if (ourPluginEntry) {
49806
+ result.installedVersion = extractVersionFromPluginEntry(ourPluginEntry);
49807
+ }
49451
49808
  if (!result.isInstalled) {
49452
49809
  return result;
49453
49810
  }
@@ -49469,10 +49826,10 @@ var init_detect_current_config = __esm(() => {
49469
49826
  });
49470
49827
 
49471
49828
  // src/cli/config-manager/bun-install.ts
49472
- import { existsSync as existsSync9 } from "fs";
49473
- import { join as join8 } from "path";
49829
+ import { existsSync as existsSync13 } from "fs";
49830
+ import { join as join11 } from "path";
49474
49831
  function getDefaultWorkspaceDir() {
49475
- return join8(getOpenCodeCacheDir(), "packages");
49832
+ return join11(getOpenCodeCacheDir(), "packages");
49476
49833
  }
49477
49834
  function readProcessOutput(stream) {
49478
49835
  if (!stream) {
@@ -49498,7 +49855,7 @@ async function runBunInstallWithDetails(options) {
49498
49855
  const outputMode = options?.outputMode ?? "pipe";
49499
49856
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
49500
49857
  const packageJsonPath = `${cacheDir}/package.json`;
49501
- if (!existsSync9(packageJsonPath)) {
49858
+ if (!existsSync13(packageJsonPath)) {
49502
49859
  return {
49503
49860
  success: false,
49504
49861
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -49574,6 +49931,7 @@ var init_config_manager = __esm(() => {
49574
49931
  init_opencode_binary();
49575
49932
  init_detect_current_config();
49576
49933
  init_bun_install();
49934
+ init_backup_config();
49577
49935
  });
49578
49936
 
49579
49937
  // node_modules/sisteransi/src/index.js
@@ -49634,6 +49992,462 @@ var require_src = __commonJS((exports, module) => {
49634
49992
  module.exports = { cursor, scroll, erase, beep };
49635
49993
  });
49636
49994
 
49995
+ // node_modules/isexe/windows.js
49996
+ var require_windows = __commonJS((exports, module) => {
49997
+ module.exports = isexe;
49998
+ isexe.sync = sync;
49999
+ var fs4 = __require("fs");
50000
+ function checkPathExt(path4, options) {
50001
+ var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
50002
+ if (!pathext) {
50003
+ return true;
50004
+ }
50005
+ pathext = pathext.split(";");
50006
+ if (pathext.indexOf("") !== -1) {
50007
+ return true;
50008
+ }
50009
+ for (var i2 = 0;i2 < pathext.length; i2++) {
50010
+ var p2 = pathext[i2].toLowerCase();
50011
+ if (p2 && path4.substr(-p2.length).toLowerCase() === p2) {
50012
+ return true;
50013
+ }
50014
+ }
50015
+ return false;
50016
+ }
50017
+ function checkStat(stat, path4, options) {
50018
+ if (!stat.isSymbolicLink() && !stat.isFile()) {
50019
+ return false;
50020
+ }
50021
+ return checkPathExt(path4, options);
50022
+ }
50023
+ function isexe(path4, options, cb) {
50024
+ fs4.stat(path4, function(er, stat) {
50025
+ cb(er, er ? false : checkStat(stat, path4, options));
50026
+ });
50027
+ }
50028
+ function sync(path4, options) {
50029
+ return checkStat(fs4.statSync(path4), path4, options);
50030
+ }
50031
+ });
50032
+
50033
+ // node_modules/isexe/mode.js
50034
+ var require_mode = __commonJS((exports, module) => {
50035
+ module.exports = isexe;
50036
+ isexe.sync = sync;
50037
+ var fs4 = __require("fs");
50038
+ function isexe(path4, options, cb) {
50039
+ fs4.stat(path4, function(er, stat) {
50040
+ cb(er, er ? false : checkStat(stat, options));
50041
+ });
50042
+ }
50043
+ function sync(path4, options) {
50044
+ return checkStat(fs4.statSync(path4), options);
50045
+ }
50046
+ function checkStat(stat, options) {
50047
+ return stat.isFile() && checkMode(stat, options);
50048
+ }
50049
+ function checkMode(stat, options) {
50050
+ var mod = stat.mode;
50051
+ var uid = stat.uid;
50052
+ var gid = stat.gid;
50053
+ var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
50054
+ var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
50055
+ var u2 = parseInt("100", 8);
50056
+ var g2 = parseInt("010", 8);
50057
+ var o2 = parseInt("001", 8);
50058
+ var ug = u2 | g2;
50059
+ var ret = mod & o2 || mod & g2 && gid === myGid || mod & u2 && uid === myUid || mod & ug && myUid === 0;
50060
+ return ret;
50061
+ }
50062
+ });
50063
+
50064
+ // node_modules/isexe/index.js
50065
+ var require_isexe = __commonJS((exports, module) => {
50066
+ var fs4 = __require("fs");
50067
+ var core3;
50068
+ if (process.platform === "win32" || global.TESTING_WINDOWS) {
50069
+ core3 = require_windows();
50070
+ } else {
50071
+ core3 = require_mode();
50072
+ }
50073
+ module.exports = isexe;
50074
+ isexe.sync = sync;
50075
+ function isexe(path4, options, cb) {
50076
+ if (typeof options === "function") {
50077
+ cb = options;
50078
+ options = {};
50079
+ }
50080
+ if (!cb) {
50081
+ if (typeof Promise !== "function") {
50082
+ throw new TypeError("callback not provided");
50083
+ }
50084
+ return new Promise(function(resolve2, reject) {
50085
+ isexe(path4, options || {}, function(er, is) {
50086
+ if (er) {
50087
+ reject(er);
50088
+ } else {
50089
+ resolve2(is);
50090
+ }
50091
+ });
50092
+ });
50093
+ }
50094
+ core3(path4, options || {}, function(er, is) {
50095
+ if (er) {
50096
+ if (er.code === "EACCES" || options && options.ignoreErrors) {
50097
+ er = null;
50098
+ is = false;
50099
+ }
50100
+ }
50101
+ cb(er, is);
50102
+ });
50103
+ }
50104
+ function sync(path4, options) {
50105
+ try {
50106
+ return core3.sync(path4, options || {});
50107
+ } catch (er) {
50108
+ if (options && options.ignoreErrors || er.code === "EACCES") {
50109
+ return false;
50110
+ } else {
50111
+ throw er;
50112
+ }
50113
+ }
50114
+ }
50115
+ });
50116
+
50117
+ // node_modules/which/which.js
50118
+ var require_which = __commonJS((exports, module) => {
50119
+ var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
50120
+ var path4 = __require("path");
50121
+ var COLON = isWindows ? ";" : ":";
50122
+ var isexe = require_isexe();
50123
+ var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
50124
+ var getPathInfo = (cmd, opt) => {
50125
+ const colon = opt.colon || COLON;
50126
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
50127
+ ...isWindows ? [process.cwd()] : [],
50128
+ ...(opt.path || process.env.PATH || "").split(colon)
50129
+ ];
50130
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
50131
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
50132
+ if (isWindows) {
50133
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
50134
+ pathExt.unshift("");
50135
+ }
50136
+ return {
50137
+ pathEnv,
50138
+ pathExt,
50139
+ pathExtExe
50140
+ };
50141
+ };
50142
+ var which = (cmd, opt, cb) => {
50143
+ if (typeof opt === "function") {
50144
+ cb = opt;
50145
+ opt = {};
50146
+ }
50147
+ if (!opt)
50148
+ opt = {};
50149
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
50150
+ const found = [];
50151
+ const step = (i2) => new Promise((resolve2, reject) => {
50152
+ if (i2 === pathEnv.length)
50153
+ return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
50154
+ const ppRaw = pathEnv[i2];
50155
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
50156
+ const pCmd = path4.join(pathPart, cmd);
50157
+ const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
50158
+ resolve2(subStep(p2, i2, 0));
50159
+ });
50160
+ const subStep = (p2, i2, ii) => new Promise((resolve2, reject) => {
50161
+ if (ii === pathExt.length)
50162
+ return resolve2(step(i2 + 1));
50163
+ const ext = pathExt[ii];
50164
+ isexe(p2 + ext, { pathExt: pathExtExe }, (er, is) => {
50165
+ if (!er && is) {
50166
+ if (opt.all)
50167
+ found.push(p2 + ext);
50168
+ else
50169
+ return resolve2(p2 + ext);
50170
+ }
50171
+ return resolve2(subStep(p2, i2, ii + 1));
50172
+ });
50173
+ });
50174
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
50175
+ };
50176
+ var whichSync = (cmd, opt) => {
50177
+ opt = opt || {};
50178
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
50179
+ const found = [];
50180
+ for (let i2 = 0;i2 < pathEnv.length; i2++) {
50181
+ const ppRaw = pathEnv[i2];
50182
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
50183
+ const pCmd = path4.join(pathPart, cmd);
50184
+ const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
50185
+ for (let j2 = 0;j2 < pathExt.length; j2++) {
50186
+ const cur = p2 + pathExt[j2];
50187
+ try {
50188
+ const is = isexe.sync(cur, { pathExt: pathExtExe });
50189
+ if (is) {
50190
+ if (opt.all)
50191
+ found.push(cur);
50192
+ else
50193
+ return cur;
50194
+ }
50195
+ } catch (ex) {}
50196
+ }
50197
+ }
50198
+ if (opt.all && found.length)
50199
+ return found;
50200
+ if (opt.nothrow)
50201
+ return null;
50202
+ throw getNotFoundError(cmd);
50203
+ };
50204
+ module.exports = which;
50205
+ which.sync = whichSync;
50206
+ });
50207
+
50208
+ // node_modules/path-key/index.js
50209
+ var require_path_key = __commonJS((exports, module) => {
50210
+ var pathKey = (options = {}) => {
50211
+ const environment = options.env || process.env;
50212
+ const platform = options.platform || process.platform;
50213
+ if (platform !== "win32") {
50214
+ return "PATH";
50215
+ }
50216
+ return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
50217
+ };
50218
+ module.exports = pathKey;
50219
+ module.exports.default = pathKey;
50220
+ });
50221
+
50222
+ // node_modules/cross-spawn/lib/util/resolveCommand.js
50223
+ var require_resolveCommand = __commonJS((exports, module) => {
50224
+ var path4 = __require("path");
50225
+ var which = require_which();
50226
+ var getPathKey = require_path_key();
50227
+ function resolveCommandAttempt(parsed, withoutPathExt) {
50228
+ const env = parsed.options.env || process.env;
50229
+ const cwd = process.cwd();
50230
+ const hasCustomCwd = parsed.options.cwd != null;
50231
+ const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
50232
+ if (shouldSwitchCwd) {
50233
+ try {
50234
+ process.chdir(parsed.options.cwd);
50235
+ } catch (err) {}
50236
+ }
50237
+ let resolved;
50238
+ try {
50239
+ resolved = which.sync(parsed.command, {
50240
+ path: env[getPathKey({ env })],
50241
+ pathExt: withoutPathExt ? path4.delimiter : undefined
50242
+ });
50243
+ } catch (e2) {} finally {
50244
+ if (shouldSwitchCwd) {
50245
+ process.chdir(cwd);
50246
+ }
50247
+ }
50248
+ if (resolved) {
50249
+ resolved = path4.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
50250
+ }
50251
+ return resolved;
50252
+ }
50253
+ function resolveCommand(parsed) {
50254
+ return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
50255
+ }
50256
+ module.exports = resolveCommand;
50257
+ });
50258
+
50259
+ // node_modules/cross-spawn/lib/util/escape.js
50260
+ var require_escape = __commonJS((exports, module) => {
50261
+ var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
50262
+ function escapeCommand(arg) {
50263
+ arg = arg.replace(metaCharsRegExp, "^$1");
50264
+ return arg;
50265
+ }
50266
+ function escapeArgument(arg, doubleEscapeMetaChars) {
50267
+ arg = `${arg}`;
50268
+ arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\"");
50269
+ arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
50270
+ arg = `"${arg}"`;
50271
+ arg = arg.replace(metaCharsRegExp, "^$1");
50272
+ if (doubleEscapeMetaChars) {
50273
+ arg = arg.replace(metaCharsRegExp, "^$1");
50274
+ }
50275
+ return arg;
50276
+ }
50277
+ exports.command = escapeCommand;
50278
+ exports.argument = escapeArgument;
50279
+ });
50280
+
50281
+ // node_modules/shebang-regex/index.js
50282
+ var require_shebang_regex = __commonJS((exports, module) => {
50283
+ module.exports = /^#!(.*)/;
50284
+ });
50285
+
50286
+ // node_modules/shebang-command/index.js
50287
+ var require_shebang_command = __commonJS((exports, module) => {
50288
+ var shebangRegex = require_shebang_regex();
50289
+ module.exports = (string4 = "") => {
50290
+ const match = string4.match(shebangRegex);
50291
+ if (!match) {
50292
+ return null;
50293
+ }
50294
+ const [path4, argument] = match[0].replace(/#! ?/, "").split(" ");
50295
+ const binary2 = path4.split("/").pop();
50296
+ if (binary2 === "env") {
50297
+ return argument;
50298
+ }
50299
+ return argument ? `${binary2} ${argument}` : binary2;
50300
+ };
50301
+ });
50302
+
50303
+ // node_modules/cross-spawn/lib/util/readShebang.js
50304
+ var require_readShebang = __commonJS((exports, module) => {
50305
+ var fs4 = __require("fs");
50306
+ var shebangCommand = require_shebang_command();
50307
+ function readShebang(command) {
50308
+ const size = 150;
50309
+ const buffer2 = Buffer.alloc(size);
50310
+ let fd;
50311
+ try {
50312
+ fd = fs4.openSync(command, "r");
50313
+ fs4.readSync(fd, buffer2, 0, size, 0);
50314
+ fs4.closeSync(fd);
50315
+ } catch (e2) {}
50316
+ return shebangCommand(buffer2.toString());
50317
+ }
50318
+ module.exports = readShebang;
50319
+ });
50320
+
50321
+ // node_modules/cross-spawn/lib/parse.js
50322
+ var require_parse = __commonJS((exports, module) => {
50323
+ var path4 = __require("path");
50324
+ var resolveCommand = require_resolveCommand();
50325
+ var escape = require_escape();
50326
+ var readShebang = require_readShebang();
50327
+ var isWin = process.platform === "win32";
50328
+ var isExecutableRegExp = /\.(?:com|exe)$/i;
50329
+ var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
50330
+ function detectShebang(parsed) {
50331
+ parsed.file = resolveCommand(parsed);
50332
+ const shebang = parsed.file && readShebang(parsed.file);
50333
+ if (shebang) {
50334
+ parsed.args.unshift(parsed.file);
50335
+ parsed.command = shebang;
50336
+ return resolveCommand(parsed);
50337
+ }
50338
+ return parsed.file;
50339
+ }
50340
+ function parseNonShell(parsed) {
50341
+ if (!isWin) {
50342
+ return parsed;
50343
+ }
50344
+ const commandFile = detectShebang(parsed);
50345
+ const needsShell = !isExecutableRegExp.test(commandFile);
50346
+ if (parsed.options.forceShell || needsShell) {
50347
+ const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
50348
+ parsed.command = path4.normalize(parsed.command);
50349
+ parsed.command = escape.command(parsed.command);
50350
+ parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
50351
+ const shellCommand = [parsed.command].concat(parsed.args).join(" ");
50352
+ parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
50353
+ parsed.command = process.env.comspec || "cmd.exe";
50354
+ parsed.options.windowsVerbatimArguments = true;
50355
+ }
50356
+ return parsed;
50357
+ }
50358
+ function parse7(command, args, options) {
50359
+ if (args && !Array.isArray(args)) {
50360
+ options = args;
50361
+ args = null;
50362
+ }
50363
+ args = args ? args.slice(0) : [];
50364
+ options = Object.assign({}, options);
50365
+ const parsed = {
50366
+ command,
50367
+ args,
50368
+ options,
50369
+ file: undefined,
50370
+ original: {
50371
+ command,
50372
+ args
50373
+ }
50374
+ };
50375
+ return options.shell ? parsed : parseNonShell(parsed);
50376
+ }
50377
+ module.exports = parse7;
50378
+ });
50379
+
50380
+ // node_modules/cross-spawn/lib/enoent.js
50381
+ var require_enoent = __commonJS((exports, module) => {
50382
+ var isWin = process.platform === "win32";
50383
+ function notFoundError(original, syscall) {
50384
+ return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
50385
+ code: "ENOENT",
50386
+ errno: "ENOENT",
50387
+ syscall: `${syscall} ${original.command}`,
50388
+ path: original.command,
50389
+ spawnargs: original.args
50390
+ });
50391
+ }
50392
+ function hookChildProcess(cp, parsed) {
50393
+ if (!isWin) {
50394
+ return;
50395
+ }
50396
+ const originalEmit = cp.emit;
50397
+ cp.emit = function(name, arg1) {
50398
+ if (name === "exit") {
50399
+ const err = verifyENOENT(arg1, parsed);
50400
+ if (err) {
50401
+ return originalEmit.call(cp, "error", err);
50402
+ }
50403
+ }
50404
+ return originalEmit.apply(cp, arguments);
50405
+ };
50406
+ }
50407
+ function verifyENOENT(status, parsed) {
50408
+ if (isWin && status === 1 && !parsed.file) {
50409
+ return notFoundError(parsed.original, "spawn");
50410
+ }
50411
+ return null;
50412
+ }
50413
+ function verifyENOENTSync(status, parsed) {
50414
+ if (isWin && status === 1 && !parsed.file) {
50415
+ return notFoundError(parsed.original, "spawnSync");
50416
+ }
50417
+ return null;
50418
+ }
50419
+ module.exports = {
50420
+ hookChildProcess,
50421
+ verifyENOENT,
50422
+ verifyENOENTSync,
50423
+ notFoundError
50424
+ };
50425
+ });
50426
+
50427
+ // node_modules/cross-spawn/index.js
50428
+ var require_cross_spawn = __commonJS((exports, module) => {
50429
+ var cp = __require("child_process");
50430
+ var parse7 = require_parse();
50431
+ var enoent = require_enoent();
50432
+ function spawn(command, args, options) {
50433
+ const parsed = parse7(command, args, options);
50434
+ const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
50435
+ enoent.hookChildProcess(spawned, parsed);
50436
+ return spawned;
50437
+ }
50438
+ function spawnSync(command, args, options) {
50439
+ const parsed = parse7(command, args, options);
50440
+ const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
50441
+ result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
50442
+ return result;
50443
+ }
50444
+ module.exports = spawn;
50445
+ module.exports.spawn = spawn;
50446
+ module.exports.sync = spawnSync;
50447
+ module.exports._parse = parse7;
50448
+ module.exports._enoent = enoent;
50449
+ });
50450
+
49637
50451
  // src/hooks/auto-update-checker/constants.ts
49638
50452
  import * as path4 from "path";
49639
50453
  import * as os3 from "os";
@@ -49651,15 +50465,15 @@ function getUserOpencodeConfig() {
49651
50465
  function getUserOpencodeConfigJsonc() {
49652
50466
  return path4.join(getUserConfigDir(), "opencode.jsonc");
49653
50467
  }
49654
- var PACKAGE_NAME = "oh-my-openagent", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON;
50468
+ var PACKAGE_NAME2 = "oh-my-opencode", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON;
49655
50469
  var init_constants3 = __esm(() => {
49656
50470
  init_data_path();
49657
50471
  init_opencode_config_dir();
49658
- NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
50472
+ NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
49659
50473
  CACHE_ROOT_DIR = getOpenCodeCacheDir();
49660
50474
  CACHE_DIR = path4.join(CACHE_ROOT_DIR, "packages");
49661
50475
  VERSION_FILE = path4.join(CACHE_ROOT_DIR, "version");
49662
- INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
50476
+ INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
49663
50477
  });
49664
50478
 
49665
50479
  // src/hooks/auto-update-checker/checker/config-paths.ts
@@ -49714,7 +50528,7 @@ function getLocalDevPath(directory) {
49714
50528
  const config2 = JSON.parse(stripJsonComments(content));
49715
50529
  const plugins = config2.plugin ?? [];
49716
50530
  for (const entry of plugins) {
49717
- if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
50531
+ if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME2)) {
49718
50532
  try {
49719
50533
  return fileURLToPath(entry);
49720
50534
  } catch {
@@ -49746,7 +50560,7 @@ function findPackageJsonUp(startPath) {
49746
50560
  try {
49747
50561
  const content = fs5.readFileSync(pkgPath, "utf-8");
49748
50562
  const pkg = JSON.parse(content);
49749
- if (pkg.name === PACKAGE_NAME)
50563
+ if (pkg.name === PACKAGE_NAME2)
49750
50564
  return pkgPath;
49751
50565
  } catch {}
49752
50566
  }
@@ -49795,13 +50609,15 @@ function findPluginEntry(directory) {
49795
50609
  const config2 = JSON.parse(stripJsonComments(content));
49796
50610
  const plugins = config2.plugin ?? [];
49797
50611
  for (const entry of plugins) {
49798
- if (entry === PACKAGE_NAME) {
49799
- return { entry, isPinned: false, pinnedVersion: null, configPath };
49800
- }
49801
- if (entry.startsWith(`${PACKAGE_NAME}@`)) {
49802
- const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
49803
- const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
49804
- return { entry, isPinned, pinnedVersion, configPath };
50612
+ for (const pluginName of MATCH_PLUGIN_NAMES) {
50613
+ if (entry === pluginName) {
50614
+ return { entry, isPinned: false, pinnedVersion: null, configPath };
50615
+ }
50616
+ if (entry.startsWith(`${pluginName}@`)) {
50617
+ const pinnedVersion = entry.slice(pluginName.length + 1);
50618
+ const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
50619
+ return { entry, isPinned, pinnedVersion, configPath };
50620
+ }
49805
50621
  }
49806
50622
  }
49807
50623
  } catch {
@@ -49810,11 +50626,12 @@ function findPluginEntry(directory) {
49810
50626
  }
49811
50627
  return null;
49812
50628
  }
49813
- var EXACT_SEMVER_REGEX;
50629
+ var EXACT_SEMVER_REGEX, MATCH_PLUGIN_NAMES;
49814
50630
  var init_plugin_entry = __esm(() => {
49815
50631
  init_constants3();
49816
50632
  init_config_paths();
49817
50633
  EXACT_SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/;
50634
+ MATCH_PLUGIN_NAMES = [PACKAGE_NAME2, PLUGIN_NAME, LEGACY_PLUGIN_NAME];
49818
50635
  });
49819
50636
 
49820
50637
  // src/hooks/auto-update-checker/checker/cached-version.ts
@@ -50022,7 +50839,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50022
50839
  if (!fs9.existsSync(cachePackageJsonPath)) {
50023
50840
  log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
50024
50841
  return {
50025
- ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME]: intentVersion } }),
50842
+ ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME2]: intentVersion } }),
50026
50843
  message: `Created cache package.json with: ${intentVersion}`
50027
50844
  };
50028
50845
  }
@@ -50040,21 +50857,21 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50040
50857
  log("[auto-update-checker] Failed to parse cache package.json:", err);
50041
50858
  return { synced: false, error: "parse_error", message: "Failed to parse cache package.json (malformed JSON)" };
50042
50859
  }
50043
- if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME]) {
50860
+ if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME2]) {
50044
50861
  log("[auto-update-checker] Plugin missing from cache package.json dependencies, adding dependency", { intentVersion });
50045
50862
  const nextPkgJson = {
50046
50863
  ...pkgJson ?? {},
50047
50864
  dependencies: {
50048
50865
  ...pkgJson?.dependencies ?? {},
50049
- [PACKAGE_NAME]: intentVersion
50866
+ [PACKAGE_NAME2]: intentVersion
50050
50867
  }
50051
50868
  };
50052
50869
  return {
50053
50870
  ...writeCachePackageJson(cachePackageJsonPath, nextPkgJson),
50054
- message: `Added ${PACKAGE_NAME}: ${intentVersion}`
50871
+ message: `Added ${PACKAGE_NAME2}: ${intentVersion}`
50055
50872
  };
50056
50873
  }
50057
- const currentVersion = pkgJson.dependencies[PACKAGE_NAME];
50874
+ const currentVersion = pkgJson.dependencies[PACKAGE_NAME2];
50058
50875
  if (currentVersion === intentVersion) {
50059
50876
  log("[auto-update-checker] Cache package.json already matches intent:", intentVersion);
50060
50877
  return { synced: false, error: null, message: `Already matches intent: ${intentVersion}` };
@@ -50066,7 +50883,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50066
50883
  } else {
50067
50884
  log(`[auto-update-checker] Updating cache package.json: "${currentVersion}" \u2192 "${intentVersion}"`);
50068
50885
  }
50069
- pkgJson.dependencies[PACKAGE_NAME] = intentVersion;
50886
+ pkgJson.dependencies[PACKAGE_NAME2] = intentVersion;
50070
50887
  return {
50071
50888
  ...writeCachePackageJson(cachePackageJsonPath, pkgJson),
50072
50889
  message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"`
@@ -50132,7 +50949,7 @@ function removeFromBunLock(packageName) {
50132
50949
  }
50133
50950
  return false;
50134
50951
  }
50135
- function invalidatePackage(packageName = PACKAGE_NAME) {
50952
+ function invalidatePackage(packageName = PACKAGE_NAME2) {
50136
50953
  try {
50137
50954
  const userConfigDir = getUserConfigDir();
50138
50955
  const pkgDirs = [
@@ -50197,8 +51014,8 @@ var init_update_toasts = __esm(() => {
50197
51014
  });
50198
51015
 
50199
51016
  // src/hooks/auto-update-checker/hook/background-update-check.ts
50200
- import { existsSync as existsSync21 } from "fs";
50201
- import { join as join20 } from "path";
51017
+ import { existsSync as existsSync25 } from "fs";
51018
+ import { join as join24 } from "path";
50202
51019
  function getCacheWorkspaceDir(deps) {
50203
51020
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
50204
51021
  }
@@ -50208,8 +51025,8 @@ function getPinnedVersionToastMessage(latestVersion) {
50208
51025
  function resolveActiveInstallWorkspace(deps) {
50209
51026
  const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
50210
51027
  const cacheDir = getCacheWorkspaceDir(deps);
50211
- const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
50212
- const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME, "package.json");
51028
+ const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME2, "package.json");
51029
+ const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME2, "package.json");
50213
51030
  if (deps.existsSync(configInstallPath)) {
50214
51031
  deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50215
51032
  return configPaths.configDir;
@@ -50255,8 +51072,8 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50255
51072
  deps.log("[auto-update-checker] Plugin not found in config");
50256
51073
  return;
50257
51074
  }
50258
- const cachedVersion = deps.getCachedVersion();
50259
- const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
51075
+ const cachedVersion2 = deps.getCachedVersion();
51076
+ const currentVersion = cachedVersion2 ?? pluginInfo.pinnedVersion;
50260
51077
  if (!currentVersion) {
50261
51078
  deps.log("[auto-update-checker] No version found (cached or pinned)");
50262
51079
  return;
@@ -50288,7 +51105,7 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50288
51105
  await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50289
51106
  return;
50290
51107
  }
50291
- deps.invalidatePackage(PACKAGE_NAME);
51108
+ deps.invalidatePackage(PACKAGE_NAME2);
50292
51109
  const activeWorkspace = resolveActiveInstallWorkspace(deps);
50293
51110
  const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
50294
51111
  if (installSuccess) {
@@ -50316,8 +51133,8 @@ var init_background_update_check = __esm(() => {
50316
51133
  init_checker();
50317
51134
  init_update_toasts();
50318
51135
  defaultDeps = {
50319
- existsSync: existsSync21,
50320
- join: join20,
51136
+ existsSync: existsSync25,
51137
+ join: join24,
50321
51138
  runBunInstallWithDetails,
50322
51139
  log,
50323
51140
  getOpenCodeCacheDir,
@@ -50526,9 +51343,9 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
50526
51343
  return;
50527
51344
  hasChecked = true;
50528
51345
  setTimeout(async () => {
50529
- const cachedVersion = getCachedVersion();
51346
+ const cachedVersion2 = getCachedVersion();
50530
51347
  const localDevVersion = getLocalDevVersion(ctx.directory);
50531
- const displayVersion = localDevVersion ?? cachedVersion;
51348
+ const displayVersion = localDevVersion ?? cachedVersion2;
50532
51349
  await showConfigErrorsIfAny(ctx);
50533
51350
  await updateAndShowConnectedProvidersCacheStatus(ctx);
50534
51351
  await refreshModelCapabilitiesOnStartup(modelCapabilities);
@@ -50597,7 +51414,7 @@ var {
50597
51414
  // package.json
50598
51415
  var package_default = {
50599
51416
  name: "oh-my-opencode",
50600
- version: "3.15.2",
51417
+ version: "3.16.0",
50601
51418
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
50602
51419
  main: "./dist/index.js",
50603
51420
  types: "dist/index.d.ts",
@@ -50656,8 +51473,8 @@ var package_default = {
50656
51473
  "@clack/prompts": "^0.11.0",
50657
51474
  "@code-yeongyu/comment-checker": "^0.7.0",
50658
51475
  "@modelcontextprotocol/sdk": "^1.25.2",
50659
- "@opencode-ai/plugin": "^1.2.24",
50660
- "@opencode-ai/sdk": "^1.2.24",
51476
+ "@opencode-ai/plugin": "^1.4.0",
51477
+ "@opencode-ai/sdk": "^1.4.0",
50661
51478
  commander: "^14.0.2",
50662
51479
  "detect-libc": "^2.0.0",
50663
51480
  diff: "^8.0.3",
@@ -50666,7 +51483,7 @@ var package_default = {
50666
51483
  picocolors: "^1.1.1",
50667
51484
  picomatch: "^4.0.2",
50668
51485
  "vscode-jsonrpc": "^8.2.0",
50669
- zod: "^4.1.8"
51486
+ zod: "^4.3.0"
50670
51487
  },
50671
51488
  devDependencies: {
50672
51489
  "@types/js-yaml": "^4.0.9",
@@ -50675,21 +51492,19 @@ var package_default = {
50675
51492
  typescript: "^5.7.3"
50676
51493
  },
50677
51494
  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"
50689
- },
50690
- overrides: {
50691
- "@opencode-ai/sdk": "^1.2.24"
51495
+ "oh-my-opencode-darwin-arm64": "3.16.0",
51496
+ "oh-my-opencode-darwin-x64": "3.16.0",
51497
+ "oh-my-opencode-darwin-x64-baseline": "3.16.0",
51498
+ "oh-my-opencode-linux-arm64": "3.16.0",
51499
+ "oh-my-opencode-linux-arm64-musl": "3.16.0",
51500
+ "oh-my-opencode-linux-x64": "3.16.0",
51501
+ "oh-my-opencode-linux-x64-baseline": "3.16.0",
51502
+ "oh-my-opencode-linux-x64-musl": "3.16.0",
51503
+ "oh-my-opencode-linux-x64-musl-baseline": "3.16.0",
51504
+ "oh-my-opencode-windows-x64": "3.16.0",
51505
+ "oh-my-opencode-windows-x64-baseline": "3.16.0"
50692
51506
  },
51507
+ overrides: {},
50693
51508
  trustedDependencies: [
50694
51509
  "@ast-grep/cli",
50695
51510
  "@ast-grep/napi",
@@ -50700,7 +51515,7 @@ var package_default = {
50700
51515
  // src/cli/cli-installer.ts
50701
51516
  init_shared();
50702
51517
  init_config_manager();
50703
- var import_picocolors2 = __toESM(require_picocolors(), 1);
51518
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
50704
51519
 
50705
51520
  // src/cli/install-validators.ts
50706
51521
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -50847,6 +51662,56 @@ function detectedToInitialValues(detected) {
50847
51662
  };
50848
51663
  }
50849
51664
 
51665
+ // src/cli/doctor/constants.ts
51666
+ init_shared();
51667
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
51668
+ var SYMBOLS2 = {
51669
+ check: import_picocolors2.default.green("\u2713"),
51670
+ cross: import_picocolors2.default.red("\u2717"),
51671
+ warn: import_picocolors2.default.yellow("\u26A0"),
51672
+ info: import_picocolors2.default.blue("\u2139"),
51673
+ arrow: import_picocolors2.default.cyan("\u2192"),
51674
+ bullet: import_picocolors2.default.dim("\u2022"),
51675
+ skip: import_picocolors2.default.dim("\u25CB")
51676
+ };
51677
+ var STATUS_COLORS = {
51678
+ pass: import_picocolors2.default.green,
51679
+ fail: import_picocolors2.default.red,
51680
+ warn: import_picocolors2.default.yellow,
51681
+ skip: import_picocolors2.default.dim
51682
+ };
51683
+ var CHECK_IDS = {
51684
+ SYSTEM: "system",
51685
+ CONFIG: "config",
51686
+ TOOLS: "tools",
51687
+ MODELS: "models"
51688
+ };
51689
+ var CHECK_NAMES = {
51690
+ [CHECK_IDS.SYSTEM]: "System",
51691
+ [CHECK_IDS.CONFIG]: "Configuration",
51692
+ [CHECK_IDS.TOOLS]: "Tools",
51693
+ [CHECK_IDS.MODELS]: "Models"
51694
+ };
51695
+ var EXIT_CODES = {
51696
+ SUCCESS: 0,
51697
+ FAILURE: 1
51698
+ };
51699
+ var MIN_OPENCODE_VERSION = "1.4.0";
51700
+ var PACKAGE_NAME = PLUGIN_NAME;
51701
+ var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
51702
+
51703
+ // src/cli/minimum-opencode-version.ts
51704
+ init_opencode_version();
51705
+ function getUnsupportedOpenCodeVersionMessage(openCodeVersion) {
51706
+ if (!openCodeVersion) {
51707
+ return null;
51708
+ }
51709
+ if (compareVersions(openCodeVersion, MIN_OPENCODE_VERSION) >= 0) {
51710
+ return null;
51711
+ }
51712
+ return `Detected OpenCode ${openCodeVersion}, but ${MIN_OPENCODE_VERSION}+ is required. Update OpenCode, then rerun the installer.`;
51713
+ }
51714
+
50850
51715
  // src/cli/cli-installer.ts
50851
51716
  async function runCliInstaller(args, version) {
50852
51717
  const validation = validateNonTuiArgs(args);
@@ -50868,12 +51733,17 @@ async function runCliInstaller(args, version) {
50868
51733
  let step = 1;
50869
51734
  printStep(step++, totalSteps, "Checking OpenCode installation...");
50870
51735
  const installed = await isOpenCodeInstalled();
50871
- const openCodeVersion = await getOpenCodeVersion();
51736
+ const openCodeVersion = await getOpenCodeVersion2();
50872
51737
  if (!installed) {
50873
51738
  printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
50874
51739
  printInfo("Visit https://opencode.ai/docs for installation instructions");
50875
51740
  } else {
50876
51741
  printSuccess(`OpenCode ${openCodeVersion ?? ""} detected`);
51742
+ const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion);
51743
+ if (unsupportedVersionMessage) {
51744
+ printWarning(unsupportedVersionMessage);
51745
+ return 1;
51746
+ }
50877
51747
  }
50878
51748
  if (isUpdate) {
50879
51749
  const initial = detectedToInitialValues(detected);
@@ -50886,47 +51756,37 @@ async function runCliInstaller(args, version) {
50886
51756
  printError(`Failed: ${pluginResult.error}`);
50887
51757
  return 1;
50888
51758
  }
50889
- printSuccess(`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${import_picocolors2.default.dim(pluginResult.configPath)}`);
51759
+ printSuccess(`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${import_picocolors3.default.dim(pluginResult.configPath)}`);
50890
51760
  printStep(step++, totalSteps, `Writing ${PLUGIN_NAME} configuration...`);
50891
51761
  const omoResult = writeOmoConfig(config);
50892
51762
  if (!omoResult.success) {
50893
51763
  printError(`Failed: ${omoResult.error}`);
50894
51764
  return 1;
50895
51765
  }
50896
- printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors2.default.dim(omoResult.configPath)}`);
51766
+ printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors3.default.dim(omoResult.configPath)}`);
50897
51767
  printBox(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
50898
51768
  if (!config.hasClaude) {
50899
- console.log();
50900
- console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
50901
- console.log();
50902
- console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
50903
- console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
50904
- console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
50905
- console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
50906
- console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
50907
- console.log();
50908
- console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
50909
- console.log();
51769
+ printInfo("Note: Sisyphus agent performs best with Claude Opus 4.5+. " + "Other models work but may have reduced orchestration quality.");
50910
51770
  }
50911
51771
  if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
50912
51772
  printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
50913
51773
  }
50914
- console.log(`${SYMBOLS.star} ${import_picocolors2.default.bold(import_picocolors2.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
50915
- console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
51774
+ console.log(`${SYMBOLS.star} ${import_picocolors3.default.bold(import_picocolors3.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
51775
+ console.log(` Run ${import_picocolors3.default.cyan("opencode")} to start!`);
50916
51776
  console.log();
50917
- printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
51777
+ printBox(`${import_picocolors3.default.bold("Pro Tip:")} Include ${import_picocolors3.default.cyan("ultrawork")} (or ${import_picocolors3.default.cyan("ulw")}) in your prompt.
50918
51778
  ` + `All features work like magic-parallel agents, background tasks,
50919
51779
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
50920
- console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
50921
- console.log(` ${import_picocolors2.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
51780
+ console.log(`${SYMBOLS.star} ${import_picocolors3.default.yellow("If you found this helpful, consider starring the repo!")}`);
51781
+ console.log(` ${import_picocolors3.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
50922
51782
  console.log();
50923
- console.log(import_picocolors2.default.dim("oMoMoMoMo... Enjoy!"));
51783
+ console.log(import_picocolors3.default.dim("oMoMoMoMo... Enjoy!"));
50924
51784
  console.log();
50925
51785
  if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
50926
- printBox(`Run ${import_picocolors2.default.cyan("opencode auth login")} and select your provider:
50927
- ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}
50928
- ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors2.default.gray("\u2192 Gemini")}
50929
- ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}` : ""), "Authenticate Your Providers");
51786
+ printBox(`Run ${import_picocolors3.default.cyan("opencode auth login")} and select your provider:
51787
+ ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors3.default.gray("\u2192 Claude Pro/Max")}
51788
+ ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors3.default.gray("\u2192 Gemini")}
51789
+ ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors3.default.gray("\u2192 Copilot")}` : ""), "Authenticate Your Providers");
50930
51790
  }
50931
51791
  return 0;
50932
51792
  }
@@ -51321,7 +52181,7 @@ class LD extends x {
51321
52181
  }
51322
52182
 
51323
52183
  // node_modules/@clack/prompts/dist/index.mjs
51324
- var import_picocolors3 = __toESM(require_picocolors(), 1);
52184
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
51325
52185
  var import_sisteransi2 = __toESM(require_src(), 1);
51326
52186
  import y2 from "process";
51327
52187
  function ce() {
@@ -51354,13 +52214,13 @@ var b2 = (t) => {
51354
52214
  switch (t) {
51355
52215
  case "initial":
51356
52216
  case "active":
51357
- return import_picocolors3.default.cyan(le);
52217
+ return import_picocolors4.default.cyan(le);
51358
52218
  case "cancel":
51359
- return import_picocolors3.default.red(L2);
52219
+ return import_picocolors4.default.red(L2);
51360
52220
  case "error":
51361
- return import_picocolors3.default.yellow(W2);
52221
+ return import_picocolors4.default.yellow(W2);
51362
52222
  case "submit":
51363
- return import_picocolors3.default.green(C);
52223
+ return import_picocolors4.default.green(C);
51364
52224
  }
51365
52225
  };
51366
52226
  var G2 = (t) => {
@@ -51370,7 +52230,7 @@ var G2 = (t) => {
51370
52230
  const $2 = a < r2.length && l2 > 0, g2 = a < r2.length && l2 + a < r2.length;
51371
52231
  return r2.slice(l2, l2 + a).map((p2, v, f) => {
51372
52232
  const j2 = v === 0 && $2, E = v === f.length - 1 && g2;
51373
- return j2 || E ? import_picocolors3.default.dim("...") : i2(p2, v + l2 === n);
52233
+ return j2 || E ? import_picocolors4.default.dim("...") : i2(p2, v + l2 === n);
51374
52234
  });
51375
52235
  };
51376
52236
  var ve = (t) => {
@@ -51378,29 +52238,29 @@ var ve = (t) => {
51378
52238
  const s = r2.label ?? String(r2.value);
51379
52239
  switch (i2) {
51380
52240
  case "selected":
51381
- return `${import_picocolors3.default.dim(s)}`;
52241
+ return `${import_picocolors4.default.dim(s)}`;
51382
52242
  case "active":
51383
- return `${import_picocolors3.default.green(k2)} ${s} ${r2.hint ? import_picocolors3.default.dim(`(${r2.hint})`) : ""}`;
52243
+ return `${import_picocolors4.default.green(k2)} ${s} ${r2.hint ? import_picocolors4.default.dim(`(${r2.hint})`) : ""}`;
51384
52244
  case "cancelled":
51385
- return `${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(s))}`;
52245
+ return `${import_picocolors4.default.strikethrough(import_picocolors4.default.dim(s))}`;
51386
52246
  default:
51387
- return `${import_picocolors3.default.dim(P2)} ${import_picocolors3.default.dim(s)}`;
52247
+ return `${import_picocolors4.default.dim(P2)} ${import_picocolors4.default.dim(s)}`;
51388
52248
  }
51389
52249
  };
51390
52250
  return new LD({ options: t.options, initialValue: t.initialValue, render() {
51391
- const r2 = `${import_picocolors3.default.gray(o)}
52251
+ const r2 = `${import_picocolors4.default.gray(o)}
51392
52252
  ${b2(this.state)} ${t.message}
51393
52253
  `;
51394
52254
  switch (this.state) {
51395
52255
  case "submit":
51396
- return `${r2}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
52256
+ return `${r2}${import_picocolors4.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
51397
52257
  case "cancel":
51398
- return `${r2}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
51399
- ${import_picocolors3.default.gray(o)}`;
52258
+ return `${r2}${import_picocolors4.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
52259
+ ${import_picocolors4.default.gray(o)}`;
51400
52260
  default:
51401
- return `${r2}${import_picocolors3.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i2, s) => n(i2, s ? "active" : "inactive") }).join(`
51402
- ${import_picocolors3.default.cyan(o)} `)}
51403
- ${import_picocolors3.default.cyan(d2)}
52261
+ return `${r2}${import_picocolors4.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i2, s) => n(i2, s ? "active" : "inactive") }).join(`
52262
+ ${import_picocolors4.default.cyan(o)} `)}
52263
+ ${import_picocolors4.default.cyan(d2)}
51404
52264
  `;
51405
52265
  }
51406
52266
  } }).prompt();
@@ -51412,53 +52272,53 @@ ${t}
51412
52272
  `), i2 = S2(n).length, s = Math.max(r2.reduce((a, l2) => {
51413
52273
  const $2 = S2(l2);
51414
52274
  return $2.length > a ? $2.length : a;
51415
- }, 0), i2) + 2, c = r2.map((a) => `${import_picocolors3.default.gray(o)} ${import_picocolors3.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors3.default.gray(o)}`).join(`
52275
+ }, 0), i2) + 2, c = r2.map((a) => `${import_picocolors4.default.gray(o)} ${import_picocolors4.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors4.default.gray(o)}`).join(`
51416
52276
  `);
51417
- process.stdout.write(`${import_picocolors3.default.gray(o)}
51418
- ${import_picocolors3.default.green(C)} ${import_picocolors3.default.reset(n)} ${import_picocolors3.default.gray(_2.repeat(Math.max(s - i2 - 1, 1)) + me)}
52277
+ process.stdout.write(`${import_picocolors4.default.gray(o)}
52278
+ ${import_picocolors4.default.green(C)} ${import_picocolors4.default.reset(n)} ${import_picocolors4.default.gray(_2.repeat(Math.max(s - i2 - 1, 1)) + me)}
51419
52279
  ${c}
51420
- ${import_picocolors3.default.gray(de + _2.repeat(s + 2) + pe)}
52280
+ ${import_picocolors4.default.gray(de + _2.repeat(s + 2) + pe)}
51421
52281
  `);
51422
52282
  };
51423
52283
  var xe = (t = "") => {
51424
- process.stdout.write(`${import_picocolors3.default.gray(d2)} ${import_picocolors3.default.red(t)}
52284
+ process.stdout.write(`${import_picocolors4.default.gray(d2)} ${import_picocolors4.default.red(t)}
51425
52285
 
51426
52286
  `);
51427
52287
  };
51428
52288
  var Ie = (t = "") => {
51429
- process.stdout.write(`${import_picocolors3.default.gray(ue)} ${t}
52289
+ process.stdout.write(`${import_picocolors4.default.gray(ue)} ${t}
51430
52290
  `);
51431
52291
  };
51432
52292
  var Se = (t = "") => {
51433
- process.stdout.write(`${import_picocolors3.default.gray(o)}
51434
- ${import_picocolors3.default.gray(d2)} ${t}
52293
+ process.stdout.write(`${import_picocolors4.default.gray(o)}
52294
+ ${import_picocolors4.default.gray(d2)} ${t}
51435
52295
 
51436
52296
  `);
51437
52297
  };
51438
- var M2 = { message: (t = "", { symbol: n = import_picocolors3.default.gray(o) } = {}) => {
51439
- const r2 = [`${import_picocolors3.default.gray(o)}`];
52298
+ var M2 = { message: (t = "", { symbol: n = import_picocolors4.default.gray(o) } = {}) => {
52299
+ const r2 = [`${import_picocolors4.default.gray(o)}`];
51440
52300
  if (t) {
51441
52301
  const [i2, ...s] = t.split(`
51442
52302
  `);
51443
- r2.push(`${n} ${i2}`, ...s.map((c) => `${import_picocolors3.default.gray(o)} ${c}`));
52303
+ r2.push(`${n} ${i2}`, ...s.map((c) => `${import_picocolors4.default.gray(o)} ${c}`));
51444
52304
  }
51445
52305
  process.stdout.write(`${r2.join(`
51446
52306
  `)}
51447
52307
  `);
51448
52308
  }, info: (t) => {
51449
- M2.message(t, { symbol: import_picocolors3.default.blue(q) });
52309
+ M2.message(t, { symbol: import_picocolors4.default.blue(q) });
51450
52310
  }, success: (t) => {
51451
- M2.message(t, { symbol: import_picocolors3.default.green(D) });
52311
+ M2.message(t, { symbol: import_picocolors4.default.green(D) });
51452
52312
  }, step: (t) => {
51453
- M2.message(t, { symbol: import_picocolors3.default.green(C) });
52313
+ M2.message(t, { symbol: import_picocolors4.default.green(C) });
51454
52314
  }, warn: (t) => {
51455
- M2.message(t, { symbol: import_picocolors3.default.yellow(U) });
52315
+ M2.message(t, { symbol: import_picocolors4.default.yellow(U) });
51456
52316
  }, warning: (t) => {
51457
52317
  M2.warn(t);
51458
52318
  }, error: (t) => {
51459
- M2.message(t, { symbol: import_picocolors3.default.red(K2) });
52319
+ M2.message(t, { symbol: import_picocolors4.default.red(K2) });
51460
52320
  } };
51461
- var J2 = `${import_picocolors3.default.gray(o)} `;
52321
+ var J2 = `${import_picocolors4.default.gray(o)} `;
51462
52322
  var Y2 = ({ indicator: t = "dots" } = {}) => {
51463
52323
  const n = V2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], r2 = V2 ? 80 : 120, i2 = process.env.CI === "true";
51464
52324
  let s, c, a = false, l2 = "", $2, g2 = performance.now();
@@ -51481,14 +52341,14 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51481
52341
  const h2 = (performance.now() - m2) / 1000, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
51482
52342
  return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
51483
52343
  }, H = (m2 = "") => {
51484
- a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors3.default.gray(o)}
52344
+ a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors4.default.gray(o)}
51485
52345
  `);
51486
52346
  let h2 = 0, w2 = 0;
51487
52347
  j2(), c = setInterval(() => {
51488
52348
  if (i2 && l2 === $2)
51489
52349
  return;
51490
52350
  B2(), $2 = l2;
51491
- const I2 = import_picocolors3.default.magenta(n[h2]);
52351
+ const I2 = import_picocolors4.default.magenta(n[h2]);
51492
52352
  if (i2)
51493
52353
  process.stdout.write(`${I2} ${l2}...`);
51494
52354
  else if (t === "timer")
@@ -51501,7 +52361,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51501
52361
  }, r2);
51502
52362
  }, N2 = (m2 = "", h2 = 0) => {
51503
52363
  a = false, clearInterval(c), B2();
51504
- const w2 = h2 === 0 ? import_picocolors3.default.green(C) : h2 === 1 ? import_picocolors3.default.red(L2) : import_picocolors3.default.red(W2);
52364
+ const w2 = h2 === 0 ? import_picocolors4.default.green(C) : h2 === 1 ? import_picocolors4.default.red(L2) : import_picocolors4.default.red(W2);
51505
52365
  l2 = R2(m2 ?? l2), t === "timer" ? process.stdout.write(`${w2} ${l2} ${O2(g2)}
51506
52366
  `) : process.stdout.write(`${w2} ${l2}
51507
52367
  `), E(), s();
@@ -51514,7 +52374,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51514
52374
  // src/cli/tui-installer.ts
51515
52375
  init_shared();
51516
52376
  init_config_manager();
51517
- var import_picocolors4 = __toESM(require_picocolors(), 1);
52377
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
51518
52378
 
51519
52379
  // src/cli/tui-install-prompts.ts
51520
52380
  async function selectOrCancel(params) {
@@ -51635,7 +52495,7 @@ async function runTuiInstaller(args, version) {
51635
52495
  }
51636
52496
  const detected = detectCurrentConfig();
51637
52497
  const isUpdate = detected.isInstalled;
51638
- Ie(import_picocolors4.default.bgMagenta(import_picocolors4.default.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")));
52498
+ Ie(import_picocolors5.default.bgMagenta(import_picocolors5.default.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")));
51639
52499
  if (isUpdate) {
51640
52500
  const initial = detectedToInitialValues(detected);
51641
52501
  M2.info(`Existing configuration detected: Claude=${initial.claude}, Gemini=${initial.gemini}`);
@@ -51643,13 +52503,19 @@ async function runTuiInstaller(args, version) {
51643
52503
  const spinner = Y2();
51644
52504
  spinner.start("Checking OpenCode installation");
51645
52505
  const installed = await isOpenCodeInstalled();
51646
- const openCodeVersion = await getOpenCodeVersion();
52506
+ const openCodeVersion = await getOpenCodeVersion2();
51647
52507
  if (!installed) {
51648
- spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
52508
+ spinner.stop(`OpenCode binary not found ${import_picocolors5.default.yellow("[!]")}`);
51649
52509
  M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
51650
52510
  Me("Visit https://opencode.ai/docs for installation instructions", "Installation Guide");
51651
52511
  } else {
51652
- spinner.stop(`OpenCode ${openCodeVersion ?? "installed"} ${import_picocolors4.default.green("[OK]")}`);
52512
+ spinner.stop(`OpenCode ${openCodeVersion ?? "installed"} ${import_picocolors5.default.green("[OK]")}`);
52513
+ const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion);
52514
+ if (unsupportedVersionMessage) {
52515
+ M2.warn(unsupportedVersionMessage);
52516
+ Se(import_picocolors5.default.red("Installation blocked."));
52517
+ return 1;
52518
+ }
51653
52519
  }
51654
52520
  const config = await promptInstallConfig(detected);
51655
52521
  if (!config)
@@ -51658,55 +52524,46 @@ async function runTuiInstaller(args, version) {
51658
52524
  const pluginResult = await addPluginToOpenCodeConfig(version);
51659
52525
  if (!pluginResult.success) {
51660
52526
  spinner.stop(`Failed to add plugin: ${pluginResult.error}`);
51661
- Se(import_picocolors4.default.red("Installation failed."));
52527
+ Se(import_picocolors5.default.red("Installation failed."));
51662
52528
  return 1;
51663
52529
  }
51664
- spinner.stop(`Plugin added to ${import_picocolors4.default.cyan(pluginResult.configPath)}`);
52530
+ spinner.stop(`Plugin added to ${import_picocolors5.default.cyan(pluginResult.configPath)}`);
51665
52531
  spinner.start(`Writing ${PLUGIN_NAME} configuration`);
51666
52532
  const omoResult = writeOmoConfig(config);
51667
52533
  if (!omoResult.success) {
51668
52534
  spinner.stop(`Failed to write config: ${omoResult.error}`);
51669
- Se(import_picocolors4.default.red("Installation failed."));
52535
+ Se(import_picocolors5.default.red("Installation failed."));
51670
52536
  return 1;
51671
52537
  }
51672
- spinner.stop(`Config written to ${import_picocolors4.default.cyan(omoResult.configPath)}`);
52538
+ spinner.stop(`Config written to ${import_picocolors5.default.cyan(omoResult.configPath)}`);
51673
52539
  if (!config.hasClaude) {
51674
- console.log();
51675
- console.log(import_picocolors4.default.bgRed(import_picocolors4.default.white(import_picocolors4.default.bold(" CRITICAL WARNING "))));
51676
- console.log();
51677
- console.log(import_picocolors4.default.red(import_picocolors4.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
51678
- console.log(import_picocolors4.default.red(" Without Claude, you may experience significantly degraded performance:"));
51679
- console.log(import_picocolors4.default.dim(" \u2022 Reduced orchestration quality"));
51680
- console.log(import_picocolors4.default.dim(" \u2022 Weaker tool selection and delegation"));
51681
- console.log(import_picocolors4.default.dim(" \u2022 Less reliable task completion"));
51682
- console.log();
51683
- console.log(import_picocolors4.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
51684
- console.log();
52540
+ M2.info(`${import_picocolors5.default.bold("Note:")} Sisyphus agent performs best with Claude Opus 4.5+.
52541
+ ` + `Other models work but may have reduced orchestration quality.`);
51685
52542
  }
51686
52543
  if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
51687
52544
  M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
51688
52545
  }
51689
52546
  Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
51690
- M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51691
- M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
51692
- Me(`Include ${import_picocolors4.default.cyan("ultrawork")} (or ${import_picocolors4.default.cyan("ulw")}) in your prompt.
52547
+ M2.success(import_picocolors5.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
52548
+ M2.message(`Run ${import_picocolors5.default.cyan("opencode")} to start!`);
52549
+ Me(`Include ${import_picocolors5.default.cyan("ultrawork")} (or ${import_picocolors5.default.cyan("ulw")}) in your prompt.
51693
52550
  ` + `All features work like magic-parallel agents, background tasks,
51694
52551
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51695
- M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51696
- M2.message(` ${import_picocolors4.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
51697
- Se(import_picocolors4.default.green("oMoMoMoMo... Enjoy!"));
52552
+ M2.message(`${import_picocolors5.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
52553
+ M2.message(` ${import_picocolors5.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
52554
+ Se(import_picocolors5.default.green("oMoMoMoMo... Enjoy!"));
51698
52555
  if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
51699
52556
  const providers = [];
51700
52557
  if (config.hasClaude)
51701
- providers.push(`Anthropic ${import_picocolors4.default.gray("\u2192 Claude Pro/Max")}`);
52558
+ providers.push(`Anthropic ${import_picocolors5.default.gray("\u2192 Claude Pro/Max")}`);
51702
52559
  if (config.hasGemini)
51703
- providers.push(`Google ${import_picocolors4.default.gray("\u2192 Gemini")}`);
52560
+ providers.push(`Google ${import_picocolors5.default.gray("\u2192 Gemini")}`);
51704
52561
  if (config.hasCopilot)
51705
- providers.push(`GitHub ${import_picocolors4.default.gray("\u2192 Copilot")}`);
52562
+ providers.push(`GitHub ${import_picocolors5.default.gray("\u2192 Copilot")}`);
51706
52563
  console.log();
51707
- console.log(import_picocolors4.default.bold("Authenticate Your Providers"));
52564
+ console.log(import_picocolors5.default.bold("Authenticate Your Providers"));
51708
52565
  console.log();
51709
- console.log(` Run ${import_picocolors4.default.cyan("opencode auth login")} and select:`);
52566
+ console.log(` Run ${import_picocolors5.default.cyan("opencode auth login")} and select:`);
51710
52567
  for (const provider of providers) {
51711
52568
  console.log(` ${SYMBOLS.bullet} ${provider}`);
51712
52569
  }
@@ -51722,7 +52579,7 @@ async function install(args) {
51722
52579
  }
51723
52580
 
51724
52581
  // src/cli/run/runner.ts
51725
- var import_picocolors14 = __toESM(require_picocolors(), 1);
52582
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
51726
52583
 
51727
52584
  // src/cli/run/event-state.ts
51728
52585
  function createEventState() {
@@ -51756,7 +52613,7 @@ function createEventState() {
51756
52613
  };
51757
52614
  }
51758
52615
  // src/cli/run/event-formatting.ts
51759
- var import_picocolors5 = __toESM(require_picocolors(), 1);
52616
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
51760
52617
  function serializeError(error) {
51761
52618
  if (!error)
51762
52619
  return "Unknown error";
@@ -51800,10 +52657,10 @@ function getSessionTag(ctx, payload) {
51800
52657
  const sessionID = props?.sessionID ?? props?.sessionId ?? info?.sessionID ?? info?.sessionId ?? part?.sessionID ?? part?.sessionId;
51801
52658
  const isMainSession = sessionID === ctx.sessionID;
51802
52659
  if (isMainSession)
51803
- return import_picocolors5.default.green("[MAIN]");
52660
+ return import_picocolors6.default.green("[MAIN]");
51804
52661
  if (sessionID)
51805
- return import_picocolors5.default.yellow(`[${String(sessionID).slice(0, 8)}]`);
51806
- return import_picocolors5.default.dim("[system]");
52662
+ return import_picocolors6.default.yellow(`[${String(sessionID).slice(0, 8)}]`);
52663
+ return import_picocolors6.default.dim("[system]");
51807
52664
  }
51808
52665
  function logEventVerbose(ctx, payload) {
51809
52666
  const sessionTag = getSessionTag(ctx, payload);
@@ -51812,7 +52669,7 @@ function logEventVerbose(ctx, payload) {
51812
52669
  case "session.idle":
51813
52670
  case "session.status": {
51814
52671
  const status = props?.status?.type ?? "idle";
51815
- console.error(import_picocolors5.default.dim(`${sessionTag} ${payload.type}: ${status}`));
52672
+ console.error(import_picocolors6.default.dim(`${sessionTag} ${payload.type}: ${status}`));
51816
52673
  break;
51817
52674
  }
51818
52675
  case "message.part.updated": {
@@ -51820,10 +52677,10 @@ function logEventVerbose(ctx, payload) {
51820
52677
  const part = partProps?.part;
51821
52678
  if (part?.type === "tool") {
51822
52679
  const status = part.state?.status ?? "unknown";
51823
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part (tool): ${part.tool ?? part.name ?? "?"} [${status}]`));
52680
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.part (tool): ${part.tool ?? part.name ?? "?"} [${status}]`));
51824
52681
  } else if (part?.type === "text" && part.text) {
51825
52682
  const preview = part.text.slice(0, 80).replace(/\n/g, "\\n");
51826
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`));
52683
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`));
51827
52684
  }
51828
52685
  break;
51829
52686
  }
@@ -51832,7 +52689,7 @@ function logEventVerbose(ctx, payload) {
51832
52689
  const field = deltaProps?.field ?? "unknown";
51833
52690
  const delta = deltaProps?.delta ?? "";
51834
52691
  const preview = delta.slice(0, 80).replace(/\n/g, "\\n");
51835
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part.delta (${field}): "${preview}${delta.length > 80 ? "..." : ""}"`));
52692
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.part.delta (${field}): "${preview}${delta.length > 80 ? "..." : ""}"`));
51836
52693
  break;
51837
52694
  }
51838
52695
  case "message.updated": {
@@ -51841,7 +52698,7 @@ function logEventVerbose(ctx, payload) {
51841
52698
  const model = msgProps?.info?.modelID;
51842
52699
  const agent = msgProps?.info?.agent;
51843
52700
  const details = [role, agent, model].filter(Boolean).join(", ");
51844
- console.error(import_picocolors5.default.dim(`${sessionTag} message.updated (${details})`));
52701
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.updated (${details})`));
51845
52702
  break;
51846
52703
  }
51847
52704
  case "tool.execute": {
@@ -51859,32 +52716,32 @@ function logEventVerbose(ctx, payload) {
51859
52716
  }
51860
52717
  }
51861
52718
  const inputPreview = inputStr.slice(0, 150);
51862
- console.error(import_picocolors5.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors5.default.bold(toolName)}`));
51863
- console.error(import_picocolors5.default.dim(` input: ${inputPreview}${inputStr.length >= 150 ? "..." : ""}`));
52719
+ console.error(import_picocolors6.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors6.default.bold(toolName)}`));
52720
+ console.error(import_picocolors6.default.dim(` input: ${inputPreview}${inputStr.length >= 150 ? "..." : ""}`));
51864
52721
  break;
51865
52722
  }
51866
52723
  case "tool.result": {
51867
52724
  const resultProps = props;
51868
52725
  const output = resultProps?.output ?? "";
51869
52726
  const preview = output.slice(0, 200).replace(/\n/g, "\\n");
51870
- console.error(import_picocolors5.default.green(`${sessionTag} TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
52727
+ console.error(import_picocolors6.default.green(`${sessionTag} TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
51871
52728
  break;
51872
52729
  }
51873
52730
  case "session.error": {
51874
52731
  const errorProps = props;
51875
52732
  const errorMsg = serializeError(errorProps?.error);
51876
- console.error(import_picocolors5.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
52733
+ console.error(import_picocolors6.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
51877
52734
  break;
51878
52735
  }
51879
52736
  default:
51880
- console.error(import_picocolors5.default.dim(`${sessionTag} ${payload.type}`));
52737
+ console.error(import_picocolors6.default.dim(`${sessionTag} ${payload.type}`));
51881
52738
  }
51882
52739
  }
51883
52740
  // src/cli/run/event-stream-processor.ts
51884
- var import_picocolors8 = __toESM(require_picocolors(), 1);
52741
+ var import_picocolors9 = __toESM(require_picocolors(), 1);
51885
52742
 
51886
52743
  // src/cli/run/event-handlers.ts
51887
- var import_picocolors7 = __toESM(require_picocolors(), 1);
52744
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
51888
52745
 
51889
52746
  // src/cli/run/tool-input-preview.ts
51890
52747
  function formatToolHeader(toolName, input) {
@@ -52020,14 +52877,14 @@ var displayChars = {
52020
52877
  };
52021
52878
 
52022
52879
  // src/cli/run/output-renderer.ts
52023
- var import_picocolors6 = __toESM(require_picocolors(), 1);
52880
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
52024
52881
  function renderAgentHeader(agent, model, variant, agentColorsByName) {
52025
52882
  if (!agent && !model)
52026
52883
  return;
52027
- const agentLabel = agent ? import_picocolors6.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
52884
+ const agentLabel = agent ? import_picocolors7.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
52028
52885
  const modelBase = model ?? "";
52029
52886
  const variantSuffix = variant ? ` (${variant})` : "";
52030
- const modelLabel = model ? import_picocolors6.default.dim(`${modelBase}${variantSuffix}`) : "";
52887
+ const modelLabel = model ? import_picocolors7.default.dim(`${modelBase}${variantSuffix}`) : "";
52031
52888
  process.stdout.write(`
52032
52889
  `);
52033
52890
  if (modelLabel) {
@@ -52035,7 +52892,7 @@ function renderAgentHeader(agent, model, variant, agentColorsByName) {
52035
52892
  `);
52036
52893
  }
52037
52894
  if (agentLabel) {
52038
- process.stdout.write(` ${import_picocolors6.default.dim("\u2514\u2500")} ${agentLabel}
52895
+ process.stdout.write(` ${import_picocolors7.default.dim("\u2514\u2500")} ${agentLabel}
52039
52896
  `);
52040
52897
  }
52041
52898
  process.stdout.write(`
@@ -52043,7 +52900,7 @@ function renderAgentHeader(agent, model, variant, agentColorsByName) {
52043
52900
  }
52044
52901
  function openThinkBlock() {
52045
52902
  process.stdout.write(`
52046
- ${import_picocolors6.default.dim("\u2503 Thinking:")} `);
52903
+ ${import_picocolors7.default.dim("\u2503 Thinking:")} `);
52047
52904
  }
52048
52905
  function closeThinkBlock() {
52049
52906
  process.stdout.write(`
@@ -52077,10 +52934,10 @@ function writePaddedText(text, atLineStart) {
52077
52934
  }
52078
52935
  function colorizeWithProfileColor(text, hexColor) {
52079
52936
  if (!hexColor)
52080
- return import_picocolors6.default.magenta(text);
52937
+ return import_picocolors7.default.magenta(text);
52081
52938
  const rgb = parseHexColor(hexColor);
52082
52939
  if (!rgb)
52083
- return import_picocolors6.default.magenta(text);
52940
+ return import_picocolors7.default.magenta(text);
52084
52941
  const [r2, g2, b3] = rgb;
52085
52942
  return `\x1B[38;2;${r2};${g2};${b3}m${text}\x1B[39m`;
52086
52943
  }
@@ -52120,7 +52977,7 @@ function renderCompletionMetaLine(state, messageID) {
52120
52977
  const agent = state.currentAgent ?? "assistant";
52121
52978
  const model = state.currentModel ?? "unknown-model";
52122
52979
  const variant = state.currentVariant ? ` (${state.currentVariant})` : "";
52123
- process.stdout.write(import_picocolors7.default.dim(`
52980
+ process.stdout.write(import_picocolors8.default.dim(`
52124
52981
  ${displayChars.treeEnd} ${agent} \xB7 ${model}${variant} \xB7 ${elapsedSec}s
52125
52982
  `));
52126
52983
  state.completionMetaPrintedByMessageId[messageID] = true;
@@ -52154,7 +53011,7 @@ function handleSessionError(ctx, payload, state) {
52154
53011
  if (getSessionId(props) === ctx.sessionID) {
52155
53012
  state.mainSessionError = true;
52156
53013
  state.lastError = serializeError(props?.error);
52157
- console.error(import_picocolors7.default.red(`
53014
+ console.error(import_picocolors8.default.red(`
52158
53015
  [session.error] ${state.lastError}`));
52159
53016
  }
52160
53017
  }
@@ -52182,7 +53039,7 @@ function handleMessagePartUpdated(ctx, payload, state) {
52182
53039
  const newText = reasoningText.slice(state.lastReasoningText.length);
52183
53040
  if (newText) {
52184
53041
  const padded = writePaddedText(newText, state.thinkingAtLineStart);
52185
- process.stdout.write(import_picocolors7.default.dim(padded.output));
53042
+ process.stdout.write(import_picocolors8.default.dim(padded.output));
52186
53043
  state.thinkingAtLineStart = padded.atLineStart;
52187
53044
  state.hasReceivedMeaningfulWork = true;
52188
53045
  }
@@ -52229,7 +53086,7 @@ function handleMessagePartDelta(ctx, payload, state) {
52229
53086
  if (partType === "reasoning") {
52230
53087
  ensureThinkBlockOpen(state);
52231
53088
  const padded2 = writePaddedText(delta, state.thinkingAtLineStart);
52232
- process.stdout.write(import_picocolors7.default.dim(padded2.output));
53089
+ process.stdout.write(import_picocolors8.default.dim(padded2.output));
52233
53090
  state.thinkingAtLineStart = padded2.atLineStart;
52234
53091
  state.lastReasoningText += delta;
52235
53092
  state.hasReceivedMeaningfulWork = true;
@@ -52250,10 +53107,10 @@ function handleToolPart(_ctx, part, state) {
52250
53107
  return;
52251
53108
  state.currentTool = toolName;
52252
53109
  const header = formatToolHeader(toolName, part.state?.input ?? {});
52253
- const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
53110
+ const suffix = header.description ? ` ${import_picocolors8.default.dim(header.description)}` : "";
52254
53111
  state.hasReceivedMeaningfulWork = true;
52255
53112
  process.stdout.write(`
52256
- ${import_picocolors7.default.cyan(header.icon)} ${import_picocolors7.default.bold(header.title)}${suffix}
53113
+ ${import_picocolors8.default.cyan(header.icon)} ${import_picocolors8.default.bold(header.title)}${suffix}
52257
53114
  `);
52258
53115
  }
52259
53116
  if (status === "completed" || status === "error") {
@@ -52261,10 +53118,10 @@ function handleToolPart(_ctx, part, state) {
52261
53118
  return;
52262
53119
  const output = part.state?.output || "";
52263
53120
  if (output.trim()) {
52264
- process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
53121
+ process.stdout.write(import_picocolors8.default.dim(` ${displayChars.treeEnd} output
52265
53122
  `));
52266
53123
  const padded = writePaddedText(output, true);
52267
- process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
53124
+ process.stdout.write(import_picocolors8.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52268
53125
  process.stdout.write(`
52269
53126
  `);
52270
53127
  }
@@ -52326,10 +53183,10 @@ function handleToolExecute(ctx, payload, state) {
52326
53183
  const toolName = props?.name || "unknown";
52327
53184
  state.currentTool = toolName;
52328
53185
  const header = formatToolHeader(toolName, props?.input ?? {});
52329
- const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
53186
+ const suffix = header.description ? ` ${import_picocolors8.default.dim(header.description)}` : "";
52330
53187
  state.hasReceivedMeaningfulWork = true;
52331
53188
  process.stdout.write(`
52332
- ${import_picocolors7.default.cyan(header.icon)} ${import_picocolors7.default.bold(header.title)}${suffix}
53189
+ ${import_picocolors8.default.cyan(header.icon)} ${import_picocolors8.default.bold(header.title)}${suffix}
52333
53190
  `);
52334
53191
  }
52335
53192
  function handleToolResult(ctx, payload, state) {
@@ -52343,10 +53200,10 @@ function handleToolResult(ctx, payload, state) {
52343
53200
  return;
52344
53201
  const output = props?.output || "";
52345
53202
  if (output.trim()) {
52346
- process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
53203
+ process.stdout.write(import_picocolors8.default.dim(` ${displayChars.treeEnd} output
52347
53204
  `));
52348
53205
  const padded = writePaddedText(output, true);
52349
- process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
53206
+ process.stdout.write(import_picocolors8.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52350
53207
  process.stdout.write(`
52351
53208
  `);
52352
53209
  }
@@ -52395,7 +53252,7 @@ async function processEvents(ctx, stream, state) {
52395
53252
  const payload = event;
52396
53253
  if (!payload?.type) {
52397
53254
  if (ctx.verbose) {
52398
- console.error(import_picocolors8.default.dim(`[event] no type: ${JSON.stringify(event)}`));
53255
+ console.error(import_picocolors9.default.dim(`[event] no type: ${JSON.stringify(event)}`));
52399
53256
  }
52400
53257
  continue;
52401
53258
  }
@@ -52413,7 +53270,7 @@ async function processEvents(ctx, stream, state) {
52413
53270
  handleToolResult(ctx, payload, state);
52414
53271
  handleTuiToast(ctx, payload, state);
52415
53272
  } catch (err) {
52416
- console.error(import_picocolors8.default.red(`[event error] ${err}`));
53273
+ console.error(import_picocolors9.default.red(`[event error] ${err}`));
52417
53274
  }
52418
53275
  }
52419
53276
  }
@@ -66488,12 +67345,12 @@ init_shared();
66488
67345
  // src/shared/migrate-legacy-config-file.ts
66489
67346
  init_logger();
66490
67347
  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";
67348
+ import { existsSync as existsSync14, readFileSync as readFileSync9, renameSync as renameSync2, rmSync } from "fs";
67349
+ import { join as join12, dirname as dirname2, basename } from "path";
66493
67350
  function buildCanonicalPath(legacyPath) {
66494
- const dir = dirname(legacyPath);
67351
+ const dir = dirname2(legacyPath);
66495
67352
  const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
66496
- return join9(dir, `${CONFIG_BASENAME}${ext}`);
67353
+ return join12(dir, `${CONFIG_BASENAME}${ext}`);
66497
67354
  }
66498
67355
  function archiveLegacyConfigFile(legacyPath) {
66499
67356
  const backupPath = `${legacyPath}.bak`;
@@ -66525,15 +67382,15 @@ function archiveLegacyConfigFile(legacyPath) {
66525
67382
  }
66526
67383
  }
66527
67384
  function migrateLegacyConfigFile(legacyPath) {
66528
- if (!existsSync10(legacyPath))
67385
+ if (!existsSync14(legacyPath))
66529
67386
  return false;
66530
67387
  if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
66531
67388
  return false;
66532
67389
  const canonicalPath = buildCanonicalPath(legacyPath);
66533
- if (existsSync10(canonicalPath))
67390
+ if (existsSync14(canonicalPath))
66534
67391
  return false;
66535
67392
  try {
66536
- const content = readFileSync8(legacyPath, "utf-8");
67393
+ const content = readFileSync9(legacyPath, "utf-8");
66537
67394
  writeFileAtomically(canonicalPath, content);
66538
67395
  const archivedLegacyConfig = archiveLegacyConfigFile(legacyPath);
66539
67396
  log("[migrateLegacyConfigFile] Migrated legacy config to canonical path", {
@@ -68064,6 +68921,31 @@ class OpencodeClient extends _HeyApiClient {
68064
68921
  }
68065
68922
 
68066
68923
  // node_modules/@opencode-ai/sdk/dist/client.js
68924
+ function pick2(value, fallback) {
68925
+ if (!value)
68926
+ return;
68927
+ if (!fallback)
68928
+ return value;
68929
+ if (value === fallback)
68930
+ return fallback;
68931
+ if (value === encodeURIComponent(fallback))
68932
+ return fallback;
68933
+ return value;
68934
+ }
68935
+ function rewrite(request, directory) {
68936
+ if (request.method !== "GET" && request.method !== "HEAD")
68937
+ return request;
68938
+ const value = pick2(request.headers.get("x-opencode-directory"), directory);
68939
+ if (!value)
68940
+ return request;
68941
+ const url2 = new URL(request.url);
68942
+ if (!url2.searchParams.has("directory")) {
68943
+ url2.searchParams.set("directory", value);
68944
+ }
68945
+ const next = new Request(url2, request);
68946
+ next.headers.delete("x-opencode-directory");
68947
+ return next;
68948
+ }
68067
68949
  function createOpencodeClient(config2) {
68068
68950
  if (!config2?.fetch) {
68069
68951
  const customFetch = (req) => {
@@ -68082,10 +68964,46 @@ function createOpencodeClient(config2) {
68082
68964
  };
68083
68965
  }
68084
68966
  const client2 = createClient(config2);
68967
+ client2.interceptors.request.use((request) => rewrite(request, config2?.directory));
68085
68968
  return new OpencodeClient({ client: client2 });
68086
68969
  }
68087
68970
  // node_modules/@opencode-ai/sdk/dist/server.js
68088
- import { spawn } from "child_process";
68971
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
68972
+
68973
+ // node_modules/@opencode-ai/sdk/dist/process.js
68974
+ import { spawnSync } from "child_process";
68975
+ function stop(proc) {
68976
+ if (proc.exitCode !== null || proc.signalCode !== null)
68977
+ return;
68978
+ if (process.platform === "win32" && proc.pid) {
68979
+ const out = spawnSync("taskkill", ["/pid", String(proc.pid), "/T", "/F"], { windowsHide: true });
68980
+ if (!out.error && out.status === 0)
68981
+ return;
68982
+ }
68983
+ proc.kill();
68984
+ }
68985
+ function bindAbort(proc, signal, onAbort) {
68986
+ if (!signal)
68987
+ return () => {};
68988
+ const abort = () => {
68989
+ clear();
68990
+ stop(proc);
68991
+ onAbort?.();
68992
+ };
68993
+ const clear = () => {
68994
+ signal.removeEventListener("abort", abort);
68995
+ proc.off("exit", clear);
68996
+ proc.off("error", clear);
68997
+ };
68998
+ signal.addEventListener("abort", abort, { once: true });
68999
+ proc.on("exit", clear);
69000
+ proc.on("error", clear);
69001
+ if (signal.aborted)
69002
+ abort();
69003
+ return clear;
69004
+ }
69005
+
69006
+ // node_modules/@opencode-ai/sdk/dist/server.js
68089
69007
  async function createOpencodeServer(options) {
68090
69008
  options = Object.assign({
68091
69009
  hostname: "127.0.0.1",
@@ -68095,19 +69013,24 @@ async function createOpencodeServer(options) {
68095
69013
  const args = [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`];
68096
69014
  if (options.config?.logLevel)
68097
69015
  args.push(`--log-level=${options.config.logLevel}`);
68098
- const proc = spawn(`opencode`, args, {
68099
- signal: options.signal,
69016
+ const proc = import_cross_spawn.default(`opencode`, args, {
68100
69017
  env: {
68101
69018
  ...process.env,
68102
69019
  OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {})
68103
69020
  }
68104
69021
  });
69022
+ let clear = () => {};
68105
69023
  const url2 = await new Promise((resolve2, reject) => {
68106
69024
  const id = setTimeout(() => {
69025
+ clear();
69026
+ stop(proc);
68107
69027
  reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`));
68108
69028
  }, options.timeout);
68109
69029
  let output = "";
69030
+ let resolved = false;
68110
69031
  proc.stdout?.on("data", (chunk) => {
69032
+ if (resolved)
69033
+ return;
68111
69034
  output += chunk.toString();
68112
69035
  const lines = output.split(`
68113
69036
  `);
@@ -68115,9 +69038,14 @@ async function createOpencodeServer(options) {
68115
69038
  if (line.startsWith("opencode server listening")) {
68116
69039
  const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
68117
69040
  if (!match) {
68118
- throw new Error(`Failed to parse server url from output: ${line}`);
69041
+ clear();
69042
+ stop(proc);
69043
+ clearTimeout(id);
69044
+ reject(new Error(`Failed to parse server url from output: ${line}`));
69045
+ return;
68119
69046
  }
68120
69047
  clearTimeout(id);
69048
+ resolved = true;
68121
69049
  resolve2(match[1]);
68122
69050
  return;
68123
69051
  }
@@ -68139,17 +69067,16 @@ Server output: ${output}`;
68139
69067
  clearTimeout(id);
68140
69068
  reject(error48);
68141
69069
  });
68142
- if (options.signal) {
68143
- options.signal.addEventListener("abort", () => {
68144
- clearTimeout(id);
68145
- reject(new Error("Aborted"));
68146
- });
68147
- }
69070
+ clear = bindAbort(proc, options.signal, () => {
69071
+ clearTimeout(id);
69072
+ reject(options.signal?.reason);
69073
+ });
68148
69074
  });
68149
69075
  return {
68150
69076
  url: url2,
68151
69077
  close() {
68152
- proc.kill();
69078
+ clear();
69079
+ stop(proc);
68153
69080
  }
68154
69081
  };
68155
69082
  }
@@ -68169,11 +69096,11 @@ async function createOpencode(options) {
68169
69096
 
68170
69097
  // src/cli/run/server-connection.ts
68171
69098
  init_port_utils();
68172
- var import_picocolors9 = __toESM(require_picocolors(), 1);
69099
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
68173
69100
 
68174
69101
  // src/cli/run/opencode-binary-resolver.ts
68175
69102
  init_spawn_with_windows_hide();
68176
- import { delimiter, dirname as dirname3, join as join11 } from "path";
69103
+ import { delimiter, dirname as dirname4, join as join14 } from "path";
68177
69104
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
68178
69105
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
68179
69106
  function getCommandCandidates(platform) {
@@ -68196,7 +69123,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
68196
69123
  }
68197
69124
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
68198
69125
  for (const command of commandCandidates) {
68199
- addCandidate(join11(entry, command));
69126
+ addCandidate(join14(entry, command));
68200
69127
  }
68201
69128
  }
68202
69129
  return candidates;
@@ -68223,7 +69150,7 @@ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = can
68223
69150
  return null;
68224
69151
  }
68225
69152
  function buildPathWithBinaryFirst(pathEnv, binaryPath) {
68226
- const preferredDir = dirname3(binaryPath);
69153
+ const preferredDir = dirname4(binaryPath);
68227
69154
  const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
68228
69155
  return [preferredDir, ...existing].join(delimiter);
68229
69156
  }
@@ -68257,13 +69184,13 @@ function isPortRangeExhausted(error48) {
68257
69184
  async function startServer(options) {
68258
69185
  const { signal, port } = options;
68259
69186
  const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
68260
- console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server2.url));
69187
+ console.log(import_picocolors10.default.dim("Server listening at"), import_picocolors10.default.cyan(server2.url));
68261
69188
  return { client: client3, cleanup: () => server2.close() };
68262
69189
  }
68263
69190
  async function createServerConnection(options) {
68264
69191
  const { port, attach, signal } = options;
68265
69192
  if (attach !== undefined) {
68266
- console.log(import_picocolors9.default.dim("Attaching to existing server at"), import_picocolors9.default.cyan(attach));
69193
+ console.log(import_picocolors10.default.dim("Attaching to existing server at"), import_picocolors10.default.cyan(attach));
68267
69194
  const client3 = createOpencodeClient({ baseUrl: attach });
68268
69195
  return { client: client3, cleanup: () => {} };
68269
69196
  }
@@ -68273,7 +69200,7 @@ async function createServerConnection(options) {
68273
69200
  }
68274
69201
  const available = await isPortAvailable(port, "127.0.0.1");
68275
69202
  if (available) {
68276
- console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(port.toString()));
69203
+ console.log(import_picocolors10.default.dim("Starting server on port"), import_picocolors10.default.cyan(port.toString()));
68277
69204
  try {
68278
69205
  return await startServer({ signal, port });
68279
69206
  } catch (error48) {
@@ -68284,12 +69211,12 @@ async function createServerConnection(options) {
68284
69211
  if (stillAvailable) {
68285
69212
  throw error48;
68286
69213
  }
68287
- console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("became occupied, attaching to existing server"));
69214
+ console.log(import_picocolors10.default.dim("Port"), import_picocolors10.default.cyan(port.toString()), import_picocolors10.default.dim("became occupied, attaching to existing server"));
68288
69215
  const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
68289
69216
  return { client: client4, cleanup: () => {} };
68290
69217
  }
68291
69218
  }
68292
- console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("is occupied, attaching to existing server"));
69219
+ console.log(import_picocolors10.default.dim("Port"), import_picocolors10.default.cyan(port.toString()), import_picocolors10.default.dim("is occupied, attaching to existing server"));
68293
69220
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
68294
69221
  return { client: client3, cleanup: () => {} };
68295
69222
  }
@@ -68307,14 +69234,14 @@ async function createServerConnection(options) {
68307
69234
  if (defaultPortIsAvailable) {
68308
69235
  throw error48;
68309
69236
  }
68310
- console.log(import_picocolors9.default.dim("Port range exhausted, attaching to existing server on"), import_picocolors9.default.cyan(DEFAULT_SERVER_PORT.toString()));
69237
+ console.log(import_picocolors10.default.dim("Port range exhausted, attaching to existing server on"), import_picocolors10.default.cyan(DEFAULT_SERVER_PORT.toString()));
68311
69238
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${DEFAULT_SERVER_PORT}` });
68312
69239
  return { client: client3, cleanup: () => {} };
68313
69240
  }
68314
69241
  if (wasAutoSelected) {
68315
- console.log(import_picocolors9.default.dim("Auto-selected port"), import_picocolors9.default.cyan(selectedPort.toString()));
69242
+ console.log(import_picocolors10.default.dim("Auto-selected port"), import_picocolors10.default.cyan(selectedPort.toString()));
68316
69243
  } else {
68317
- console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(selectedPort.toString()));
69244
+ console.log(import_picocolors10.default.dim("Starting server on port"), import_picocolors10.default.cyan(selectedPort.toString()));
68318
69245
  }
68319
69246
  try {
68320
69247
  return await startServer({ signal, port: selectedPort });
@@ -68323,13 +69250,13 @@ async function createServerConnection(options) {
68323
69250
  throw error48;
68324
69251
  }
68325
69252
  const { port: retryPort } = await getAvailableServerPort(selectedPort + 1, "127.0.0.1");
68326
- console.log(import_picocolors9.default.dim("Retrying server start on port"), import_picocolors9.default.cyan(retryPort.toString()));
69253
+ console.log(import_picocolors10.default.dim("Retrying server start on port"), import_picocolors10.default.cyan(retryPort.toString()));
68327
69254
  return await startServer({ signal, port: retryPort });
68328
69255
  }
68329
69256
  }
68330
69257
 
68331
69258
  // src/cli/run/session-resolver.ts
68332
- var import_picocolors10 = __toESM(require_picocolors(), 1);
69259
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
68333
69260
  var SESSION_CREATE_MAX_RETRIES = 3;
68334
69261
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
68335
69262
  async function resolveSession(options) {
@@ -68355,11 +69282,11 @@ async function resolveSession(options) {
68355
69282
  query: { directory }
68356
69283
  });
68357
69284
  if (res.error) {
68358
- console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
68359
- console.error(import_picocolors10.default.dim(` Error: ${serializeError(res.error)}`));
69285
+ console.error(import_picocolors11.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
69286
+ console.error(import_picocolors11.default.dim(` Error: ${serializeError(res.error)}`));
68360
69287
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
68361
69288
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
68362
- console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
69289
+ console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
68363
69290
  await new Promise((resolve2) => setTimeout(resolve2, delay));
68364
69291
  }
68365
69292
  continue;
@@ -68367,10 +69294,10 @@ async function resolveSession(options) {
68367
69294
  if (res.data?.id) {
68368
69295
  return res.data.id;
68369
69296
  }
68370
- console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
69297
+ console.error(import_picocolors11.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
68371
69298
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
68372
69299
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
68373
- console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
69300
+ console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
68374
69301
  await new Promise((resolve2) => setTimeout(resolve2, delay));
68375
69302
  }
68376
69303
  }
@@ -68488,7 +69415,7 @@ async function executeOnCompleteHook(options) {
68488
69415
 
68489
69416
  // src/cli/run/agent-resolver.ts
68490
69417
  init_agent_display_names();
68491
- var import_picocolors11 = __toESM(require_picocolors(), 1);
69418
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
68492
69419
  var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
68493
69420
  var DEFAULT_AGENT = "sisyphus";
68494
69421
  var normalizeAgentName = (agent) => {
@@ -68533,10 +69460,10 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
68533
69460
  const fallbackName = getAgentDisplayName(fallback);
68534
69461
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
68535
69462
  if (fallbackDisabled) {
68536
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
69463
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
68537
69464
  return fallbackName;
68538
69465
  }
68539
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
69466
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
68540
69467
  return fallbackName;
68541
69468
  }
68542
69469
  return resolved.resolvedName;
@@ -68567,11 +69494,11 @@ function resolveRunModel(modelString) {
68567
69494
  }
68568
69495
 
68569
69496
  // src/cli/run/poll-for-completion.ts
68570
- var import_picocolors13 = __toESM(require_picocolors(), 1);
69497
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
68571
69498
 
68572
69499
  // src/cli/run/completion.ts
68573
69500
  init_shared();
68574
- var import_picocolors12 = __toESM(require_picocolors(), 1);
69501
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
68575
69502
  // src/features/boulder-state/constants.ts
68576
69503
  var BOULDER_DIR = ".sisyphus";
68577
69504
  var BOULDER_FILE = "boulder.json";
@@ -68579,19 +69506,19 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68579
69506
  var NOTEPAD_DIR = "notepads";
68580
69507
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68581
69508
  // 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";
69509
+ import { existsSync as existsSync16, readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
69510
+ import { dirname as dirname5, join as join15, basename as basename3 } from "path";
68584
69511
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68585
69512
  function getBoulderFilePath(directory) {
68586
- return join12(directory, BOULDER_DIR, BOULDER_FILE);
69513
+ return join15(directory, BOULDER_DIR, BOULDER_FILE);
68587
69514
  }
68588
69515
  function readBoulderState(directory) {
68589
69516
  const filePath = getBoulderFilePath(directory);
68590
- if (!existsSync12(filePath)) {
69517
+ if (!existsSync16(filePath)) {
68591
69518
  return null;
68592
69519
  }
68593
69520
  try {
68594
- const content = readFileSync10(filePath, "utf-8");
69521
+ const content = readFileSync11(filePath, "utf-8");
68595
69522
  const parsed = JSON.parse(content);
68596
69523
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
68597
69524
  return null;
@@ -68599,6 +69526,15 @@ function readBoulderState(directory) {
68599
69526
  if (!Array.isArray(parsed.session_ids)) {
68600
69527
  parsed.session_ids = [];
68601
69528
  }
69529
+ if (!parsed.session_origins || typeof parsed.session_origins !== "object" || Array.isArray(parsed.session_origins)) {
69530
+ parsed.session_origins = {};
69531
+ }
69532
+ if (parsed.session_ids.length === 1) {
69533
+ const soleSessionId = parsed.session_ids[0];
69534
+ if (typeof soleSessionId === "string" && parsed.session_origins[soleSessionId] !== "appended" && parsed.session_origins[soleSessionId] !== "direct") {
69535
+ parsed.session_origins[soleSessionId] = "direct";
69536
+ }
69537
+ }
68602
69538
  if (!parsed.task_sessions || typeof parsed.task_sessions !== "object" || Array.isArray(parsed.task_sessions)) {
68603
69539
  parsed.task_sessions = {};
68604
69540
  }
@@ -68607,39 +69543,101 @@ function readBoulderState(directory) {
68607
69543
  return null;
68608
69544
  }
68609
69545
  }
69546
+ var TODO_HEADING_PATTERN = /^##\s+TODOs\b/i;
69547
+ var FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wave\b/i;
69548
+ var SECOND_LEVEL_HEADING_PATTERN = /^##\s+/;
69549
+ var UNCHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
69550
+ var CHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[[xX]\]\s*(.+)$/;
69551
+ var TODO_TASK_PATTERN = /^\d+\.\s+/;
69552
+ var FINAL_WAVE_TASK_PATTERN = /^F\d+\.\s+/i;
68610
69553
  function getPlanProgress(planPath) {
68611
- if (!existsSync12(planPath)) {
69554
+ if (!existsSync16(planPath)) {
68612
69555
  return { total: 0, completed: 0, isComplete: true };
68613
69556
  }
68614
69557
  try {
68615
- const content = readFileSync10(planPath, "utf-8");
68616
- const uncheckedMatches = content.match(/^\s*[-*]\s*\[\s*\]/gm) || [];
68617
- const checkedMatches = content.match(/^\s*[-*]\s*\[[xX]\]/gm) || [];
68618
- const total = uncheckedMatches.length + checkedMatches.length;
68619
- const completed = checkedMatches.length;
68620
- return {
68621
- total,
68622
- completed,
68623
- isComplete: total > 0 && completed === total
68624
- };
69558
+ const content = readFileSync11(planPath, "utf-8");
69559
+ const lines = content.split(/\r?\n/);
69560
+ const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN.test(line) || FINAL_VERIFICATION_HEADING_PATTERN.test(line));
69561
+ if (hasStructuredSections) {
69562
+ return getStructuredPlanProgress(lines);
69563
+ }
69564
+ return getSimplePlanProgress(content);
68625
69565
  } catch {
68626
69566
  return { total: 0, completed: 0, isComplete: true };
68627
69567
  }
68628
69568
  }
69569
+ function getStructuredPlanProgress(lines) {
69570
+ let section = "other";
69571
+ let total = 0;
69572
+ let completed = 0;
69573
+ for (const line of lines) {
69574
+ if (SECOND_LEVEL_HEADING_PATTERN.test(line)) {
69575
+ section = TODO_HEADING_PATTERN.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN.test(line) ? "final-wave" : "other";
69576
+ continue;
69577
+ }
69578
+ if (section !== "todo" && section !== "final-wave") {
69579
+ continue;
69580
+ }
69581
+ const checkedMatch = line.match(CHECKED_CHECKBOX_PATTERN);
69582
+ const uncheckedMatch = checkedMatch ? null : line.match(UNCHECKED_CHECKBOX_PATTERN);
69583
+ const match = checkedMatch ?? uncheckedMatch;
69584
+ if (!match) {
69585
+ continue;
69586
+ }
69587
+ if (match[1].length > 0) {
69588
+ continue;
69589
+ }
69590
+ const taskBody = match[2].trim();
69591
+ const labelPattern = section === "todo" ? TODO_TASK_PATTERN : FINAL_WAVE_TASK_PATTERN;
69592
+ if (!labelPattern.test(taskBody)) {
69593
+ continue;
69594
+ }
69595
+ total++;
69596
+ if (checkedMatch) {
69597
+ completed++;
69598
+ }
69599
+ }
69600
+ return {
69601
+ total,
69602
+ completed,
69603
+ isComplete: total > 0 && completed === total
69604
+ };
69605
+ }
69606
+ function getSimplePlanProgress(content) {
69607
+ const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || [];
69608
+ const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || [];
69609
+ const total = uncheckedMatches.length + checkedMatches.length;
69610
+ const completed = checkedMatches.length;
69611
+ return {
69612
+ total,
69613
+ completed,
69614
+ isComplete: total > 0 && completed === total
69615
+ };
69616
+ }
69617
+ // src/features/claude-code-session-state/state.ts
69618
+ init_agent_display_names();
69619
+ var subagentSessions = new Set;
69620
+ var syncSubagentSessions = new Set;
69621
+ var registeredAgentNames = new Set;
69622
+ var registeredAgentAliases = new Map;
69623
+ var sessionAgentMap = new Map;
69624
+ function getSessionAgent(sessionID) {
69625
+ return sessionAgentMap.get(sessionID);
69626
+ }
68629
69627
  // src/features/run-continuation-state/constants.ts
68630
69628
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68631
69629
  // 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";
69630
+ import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync12, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
69631
+ import { join as join16 } from "path";
68634
69632
  function getMarkerPath(directory, sessionID) {
68635
- return join13(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
69633
+ return join16(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68636
69634
  }
68637
69635
  function readContinuationMarker(directory, sessionID) {
68638
69636
  const markerPath = getMarkerPath(directory, sessionID);
68639
- if (!existsSync13(markerPath))
69637
+ if (!existsSync17(markerPath))
68640
69638
  return null;
68641
69639
  try {
68642
- const raw = readFileSync11(markerPath, "utf-8");
69640
+ const raw = readFileSync12(markerPath, "utf-8");
68643
69641
  const parsed = JSON.parse(raw);
68644
69642
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
68645
69643
  return null;
@@ -68662,10 +69660,120 @@ function getActiveContinuationMarkerReason(marker) {
68662
69660
  const [source, entry] = active;
68663
69661
  return entry.reason ?? `${source} continuation is active`;
68664
69662
  }
69663
+ // src/hooks/atlas/boulder-session-lineage.ts
69664
+ init_logger();
69665
+
69666
+ // src/hooks/atlas/hook-name.ts
69667
+ var HOOK_NAME = "atlas";
69668
+
69669
+ // src/hooks/atlas/boulder-session-lineage.ts
69670
+ async function isSessionInBoulderLineage(input) {
69671
+ const visitedSessionIDs = new Set;
69672
+ let currentSessionID = input.sessionID;
69673
+ while (!visitedSessionIDs.has(currentSessionID)) {
69674
+ visitedSessionIDs.add(currentSessionID);
69675
+ const sessionResult = await input.client.session.get({ path: { id: currentSessionID } }).catch((error48) => {
69676
+ log(`[${HOOK_NAME}] Failed to resolve session lineage`, {
69677
+ sessionID: input.sessionID,
69678
+ currentSessionID,
69679
+ error: error48
69680
+ });
69681
+ return null;
69682
+ });
69683
+ if (!sessionResult || sessionResult.error) {
69684
+ return false;
69685
+ }
69686
+ const parentSessionID = sessionResult.data?.parentID;
69687
+ if (!parentSessionID) {
69688
+ return false;
69689
+ }
69690
+ if (input.boulderSessionIDs.includes(parentSessionID)) {
69691
+ return true;
69692
+ }
69693
+ currentSessionID = parentSessionID;
69694
+ }
69695
+ return false;
69696
+ }
69697
+
69698
+ // src/hooks/atlas/session-last-agent.ts
69699
+ init_shared();
69700
+ init_compaction_marker();
69701
+ import { readFileSync as readFileSync13, readdirSync as readdirSync4 } from "fs";
69702
+ import { join as join17 } from "path";
69703
+ function getLastAgentFromMessageDir(messageDir) {
69704
+ try {
69705
+ const messages = readdirSync4(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
69706
+ try {
69707
+ const content = readFileSync13(join17(messageDir, fileName), "utf-8");
69708
+ const parsed = JSON.parse(content);
69709
+ return {
69710
+ fileName,
69711
+ id: parsed.id,
69712
+ agent: parsed.agent,
69713
+ createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
69714
+ };
69715
+ } catch {
69716
+ return null;
69717
+ }
69718
+ }).filter((message) => message !== null).sort((left, right) => (right?.createdAt ?? 0) - (left?.createdAt ?? 0) || (right?.fileName ?? "").localeCompare(left?.fileName ?? ""));
69719
+ for (const message of messages) {
69720
+ if (!message)
69721
+ continue;
69722
+ if (isCompactionMessage({ agent: message.agent }) || hasCompactionPartInStorage(message?.id)) {
69723
+ continue;
69724
+ }
69725
+ if (typeof message.agent === "string") {
69726
+ return message.agent.toLowerCase();
69727
+ }
69728
+ }
69729
+ } catch {
69730
+ return null;
69731
+ }
69732
+ return null;
69733
+ }
69734
+ async function getLastAgentFromSession(sessionID, client3) {
69735
+ if (isSqliteBackend() && client3) {
69736
+ try {
69737
+ const response = await client3.session.messages({ path: { id: sessionID } });
69738
+ const messages = normalizeSDKResponse(response, [], {
69739
+ preferResponseOnMissingData: true
69740
+ }).sort((left, right) => {
69741
+ const leftTime = left.info?.time?.created ?? Number.NEGATIVE_INFINITY;
69742
+ const rightTime = right.info?.time?.created ?? Number.NEGATIVE_INFINITY;
69743
+ if (leftTime !== rightTime) {
69744
+ return rightTime - leftTime;
69745
+ }
69746
+ const leftId = typeof left.id === "string" ? left.id : "";
69747
+ const rightId = typeof right.id === "string" ? right.id : "";
69748
+ return rightId.localeCompare(leftId);
69749
+ });
69750
+ for (const message of messages) {
69751
+ if (isCompactionMessage(message)) {
69752
+ continue;
69753
+ }
69754
+ const agent = message.info?.agent;
69755
+ if (typeof agent === "string") {
69756
+ return agent.toLowerCase();
69757
+ }
69758
+ }
69759
+ } catch {
69760
+ return null;
69761
+ }
69762
+ return null;
69763
+ }
69764
+ const messageDir = getMessageDir(sessionID);
69765
+ if (!messageDir)
69766
+ return null;
69767
+ return getLastAgentFromMessageDir(messageDir);
69768
+ }
69769
+
69770
+ // src/cli/run/continuation-state.ts
69771
+ init_agent_display_names();
69772
+
68665
69773
  // src/hooks/ralph-loop/storage.ts
68666
69774
  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";
69775
+ import { existsSync as existsSync18, readFileSync as readFileSync14, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync7 } from "fs";
69776
+ import { dirname as dirname6, join as join18 } from "path";
68669
69777
 
68670
69778
  // src/hooks/ralph-loop/constants.ts
68671
69779
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -68674,15 +69782,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
68674
69782
 
68675
69783
  // src/hooks/ralph-loop/storage.ts
68676
69784
  function getStateFilePath(directory, customPath) {
68677
- return customPath ? join14(directory, customPath) : join14(directory, DEFAULT_STATE_FILE);
69785
+ return customPath ? join18(directory, customPath) : join18(directory, DEFAULT_STATE_FILE);
68678
69786
  }
68679
69787
  function readState(directory, customPath) {
68680
69788
  const filePath = getStateFilePath(directory, customPath);
68681
- if (!existsSync14(filePath)) {
69789
+ if (!existsSync18(filePath)) {
68682
69790
  return null;
68683
69791
  }
68684
69792
  try {
68685
- const content = readFileSync12(filePath, "utf-8");
69793
+ const content = readFileSync14(filePath, "utf-8");
68686
69794
  const { data, body } = parseFrontmatter(content);
68687
69795
  const active = data.active;
68688
69796
  const iteration = data.iteration;
@@ -68722,10 +69830,10 @@ function readState(directory, customPath) {
68722
69830
  }
68723
69831
 
68724
69832
  // src/cli/run/continuation-state.ts
68725
- function getContinuationState(directory, sessionID) {
69833
+ async function getContinuationState(directory, sessionID, client3) {
68726
69834
  const marker = readContinuationMarker(directory, sessionID);
68727
69835
  return {
68728
- hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
69836
+ hasActiveBoulder: await hasActiveBoulderContinuation(directory, sessionID, client3),
68729
69837
  hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
68730
69838
  hasHookMarker: marker !== null,
68731
69839
  hasTodoHookMarker: marker?.sources.todo !== undefined,
@@ -68733,20 +69841,54 @@ function getContinuationState(directory, sessionID) {
68733
69841
  activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
68734
69842
  };
68735
69843
  }
68736
- function hasActiveBoulderContinuation(directory, sessionID) {
69844
+ async function hasActiveBoulderContinuation(directory, sessionID, client3) {
68737
69845
  const boulder = readBoulderState(directory);
68738
69846
  if (!boulder)
68739
69847
  return false;
68740
- if (!boulder.session_ids.includes(sessionID))
68741
- return false;
68742
69848
  const progress = getPlanProgress(boulder.active_plan);
68743
- return !progress.isComplete;
69849
+ if (progress.isComplete)
69850
+ return false;
69851
+ if (!client3)
69852
+ return false;
69853
+ const isTrackedSession = boulder.session_ids.includes(sessionID);
69854
+ const sessionOrigin = boulder.session_origins?.[sessionID];
69855
+ if (!isTrackedSession) {
69856
+ return false;
69857
+ }
69858
+ const isTrackedDescendant = await isTrackedDescendantSession(client3, sessionID, boulder.session_ids);
69859
+ if (isTrackedSession && sessionOrigin === "direct") {
69860
+ return true;
69861
+ }
69862
+ if (isTrackedSession && sessionOrigin !== "direct" && !isTrackedDescendant) {
69863
+ return false;
69864
+ }
69865
+ const sessionAgent = await getLastAgentFromSession(sessionID, client3) ?? getSessionAgent(sessionID);
69866
+ if (!sessionAgent) {
69867
+ return false;
69868
+ }
69869
+ const requiredAgentKey = getAgentConfigKey(boulder.agent ?? "atlas");
69870
+ const sessionAgentKey = getAgentConfigKey(sessionAgent);
69871
+ if (sessionAgentKey !== requiredAgentKey && !(requiredAgentKey === getAgentConfigKey("atlas") && sessionAgentKey === getAgentConfigKey("sisyphus"))) {
69872
+ return false;
69873
+ }
69874
+ return isTrackedSession || isTrackedDescendant;
69875
+ }
69876
+ async function isTrackedDescendantSession(client3, sessionID, trackedSessionIDs) {
69877
+ const ancestorSessionIDs = trackedSessionIDs.filter((trackedSessionID) => trackedSessionID !== sessionID);
69878
+ if (ancestorSessionIDs.length === 0) {
69879
+ return false;
69880
+ }
69881
+ return isSessionInBoulderLineage({
69882
+ client: client3,
69883
+ sessionID,
69884
+ boulderSessionIDs: ancestorSessionIDs
69885
+ });
68744
69886
  }
68745
69887
  function hasActiveRalphLoopContinuation(directory, sessionID) {
68746
- const state = readState(directory);
68747
- if (!state || !state.active)
69888
+ const state2 = readState(directory);
69889
+ if (!state2 || !state2.active)
68748
69890
  return false;
68749
- if (state.session_id && state.session_id !== sessionID) {
69891
+ if (state2.session_id && state2.session_id !== sessionID) {
68750
69892
  return false;
68751
69893
  }
68752
69894
  return true;
@@ -68755,7 +69897,7 @@ function hasActiveRalphLoopContinuation(directory, sessionID) {
68755
69897
  // src/cli/run/completion.ts
68756
69898
  async function checkCompletionConditions(ctx) {
68757
69899
  try {
68758
- const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
69900
+ const continuationState = await getContinuationState(ctx.directory, ctx.sessionID, ctx.client);
68759
69901
  if (continuationState.hasActiveHookMarker) {
68760
69902
  const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
68761
69903
  logWaiting(ctx, reason);
@@ -68772,7 +69914,7 @@ async function checkCompletionConditions(ctx) {
68772
69914
  }
68773
69915
  return true;
68774
69916
  } catch (err) {
68775
- console.error(import_picocolors12.default.red(`[completion] API error: ${err}`));
69917
+ console.error(import_picocolors13.default.red(`[completion] API error: ${err}`));
68776
69918
  return false;
68777
69919
  }
68778
69920
  }
@@ -68833,7 +69975,7 @@ function logWaiting(ctx, message) {
68833
69975
  if (!ctx.verbose) {
68834
69976
  return;
68835
69977
  }
68836
- console.log(import_picocolors12.default.dim(` Waiting: ${message}`));
69978
+ console.log(import_picocolors13.default.dim(` Waiting: ${message}`));
68837
69979
  }
68838
69980
 
68839
69981
  // src/cli/run/poll-for-completion.ts
@@ -68864,10 +70006,10 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
68864
70006
  if (eventState.mainSessionError) {
68865
70007
  errorCycleCount++;
68866
70008
  if (errorCycleCount >= ERROR_GRACE_CYCLES) {
68867
- console.error(import_picocolors13.default.red(`
70009
+ console.error(import_picocolors14.default.red(`
68868
70010
 
68869
70011
  Session ended with error: ${eventState.lastError}`));
68870
- console.error(import_picocolors13.default.yellow("Check if todos were completed before the error."));
70012
+ console.error(import_picocolors14.default.yellow("Check if todos were completed before the error."));
68871
70013
  return 1;
68872
70014
  }
68873
70015
  continue;
@@ -68878,7 +70020,7 @@ Session ended with error: ${eventState.lastError}`));
68878
70020
  if (eventState.lastEventTimestamp !== null) {
68879
70021
  const timeSinceLastEvent = Date.now() - eventState.lastEventTimestamp;
68880
70022
  if (timeSinceLastEvent > eventWatchdogMs) {
68881
- console.log(import_picocolors13.default.yellow(`
70023
+ console.log(import_picocolors14.default.yellow(`
68882
70024
  No events for ${Math.round(timeSinceLastEvent / 1000)}s, verifying session status...`));
68883
70025
  mainSessionStatus = await getMainSessionStatus(ctx);
68884
70026
  if (mainSessionStatus === "idle") {
@@ -68927,7 +70069,7 @@ Session ended with error: ${eventState.lastError}`));
68927
70069
  const hasActiveWork = hasActiveChildren || hasActiveTodos;
68928
70070
  if (hasActiveWork) {
68929
70071
  eventState.hasReceivedMeaningfulWork = true;
68930
- console.log(import_picocolors13.default.yellow(`
70072
+ console.log(import_picocolors14.default.yellow(`
68931
70073
  No meaningful work events for ${Math.round(secondaryMeaningfulWorkTimeoutMs / 1000)}s but session has active work - assuming in progress`));
68932
70074
  }
68933
70075
  }
@@ -68947,7 +70089,7 @@ Session ended with error: ${eventState.lastError}`));
68947
70089
  }
68948
70090
  consecutiveCompleteChecks++;
68949
70091
  if (consecutiveCompleteChecks >= requiredConsecutive) {
68950
- console.log(import_picocolors13.default.green(`
70092
+ console.log(import_picocolors14.default.green(`
68951
70093
 
68952
70094
  All tasks completed.`));
68953
70095
  return 0;
@@ -69116,7 +70258,7 @@ async function run(options) {
69116
70258
  };
69117
70259
  const restoreInput = suppressRunInput();
69118
70260
  const handleSigint = () => {
69119
- console.log(import_picocolors14.default.yellow(`
70261
+ console.log(import_picocolors15.default.yellow(`
69120
70262
  Interrupted. Shutting down...`));
69121
70263
  restoreInput();
69122
70264
  cleanup();
@@ -69129,9 +70271,9 @@ Interrupted. Shutting down...`));
69129
70271
  sessionId: options.sessionId,
69130
70272
  directory
69131
70273
  });
69132
- console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
70274
+ console.log(import_picocolors15.default.dim(`Session: ${sessionID}`));
69133
70275
  if (resolvedModel) {
69134
- console.log(import_picocolors14.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
70276
+ console.log(import_picocolors15.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
69135
70277
  }
69136
70278
  const ctx = {
69137
70279
  client: client3,
@@ -69194,7 +70336,7 @@ Interrupted. Shutting down...`));
69194
70336
  if (err instanceof Error && err.name === "AbortError") {
69195
70337
  return 130;
69196
70338
  }
69197
- console.error(import_picocolors14.default.red(`Error: ${serializeError(err)}`));
70339
+ console.error(import_picocolors15.default.red(`Error: ${serializeError(err)}`));
69198
70340
  return 1;
69199
70341
  } finally {
69200
70342
  timestampOutput?.restore();
@@ -69204,53 +70346,53 @@ Interrupted. Shutting down...`));
69204
70346
  init_checker();
69205
70347
 
69206
70348
  // src/cli/get-local-version/formatter.ts
69207
- var import_picocolors15 = __toESM(require_picocolors(), 1);
69208
- var SYMBOLS2 = {
69209
- check: import_picocolors15.default.green("[OK]"),
69210
- cross: import_picocolors15.default.red("[X]"),
69211
- arrow: import_picocolors15.default.cyan("->"),
69212
- info: import_picocolors15.default.blue("[i]"),
69213
- warn: import_picocolors15.default.yellow("[!]"),
69214
- pin: import_picocolors15.default.magenta("[PINNED]"),
69215
- dev: import_picocolors15.default.cyan("[DEV]")
70349
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
70350
+ var SYMBOLS3 = {
70351
+ check: import_picocolors16.default.green("[OK]"),
70352
+ cross: import_picocolors16.default.red("[X]"),
70353
+ arrow: import_picocolors16.default.cyan("->"),
70354
+ info: import_picocolors16.default.blue("[i]"),
70355
+ warn: import_picocolors16.default.yellow("[!]"),
70356
+ pin: import_picocolors16.default.magenta("[PINNED]"),
70357
+ dev: import_picocolors16.default.cyan("[DEV]")
69216
70358
  };
69217
70359
  function formatVersionOutput(info) {
69218
70360
  const lines = [];
69219
70361
  lines.push("");
69220
- lines.push(import_picocolors15.default.bold(import_picocolors15.default.white("oh-my-opencode Version Information")));
69221
- lines.push(import_picocolors15.default.dim("\u2500".repeat(50)));
70362
+ lines.push(import_picocolors16.default.bold(import_picocolors16.default.white("oh-my-opencode Version Information")));
70363
+ lines.push(import_picocolors16.default.dim("\u2500".repeat(50)));
69222
70364
  lines.push("");
69223
70365
  if (info.currentVersion) {
69224
- lines.push(` Current Version: ${import_picocolors15.default.cyan(info.currentVersion)}`);
70366
+ lines.push(` Current Version: ${import_picocolors16.default.cyan(info.currentVersion)}`);
69225
70367
  } else {
69226
- lines.push(` Current Version: ${import_picocolors15.default.dim("unknown")}`);
70368
+ lines.push(` Current Version: ${import_picocolors16.default.dim("unknown")}`);
69227
70369
  }
69228
70370
  if (!info.isLocalDev && info.latestVersion) {
69229
- lines.push(` Latest Version: ${import_picocolors15.default.cyan(info.latestVersion)}`);
70371
+ lines.push(` Latest Version: ${import_picocolors16.default.cyan(info.latestVersion)}`);
69230
70372
  }
69231
70373
  lines.push("");
69232
70374
  switch (info.status) {
69233
70375
  case "up-to-date":
69234
- lines.push(` ${SYMBOLS2.check} ${import_picocolors15.default.green("You're up to date!")}`);
70376
+ lines.push(` ${SYMBOLS3.check} ${import_picocolors16.default.green("You're up to date!")}`);
69235
70377
  break;
69236
70378
  case "outdated":
69237
- lines.push(` ${SYMBOLS2.warn} ${import_picocolors15.default.yellow("Update available")}`);
69238
- lines.push(` ${import_picocolors15.default.dim("Run:")} ${import_picocolors15.default.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`);
70379
+ lines.push(` ${SYMBOLS3.warn} ${import_picocolors16.default.yellow("Update available")}`);
70380
+ lines.push(` ${import_picocolors16.default.dim("Run:")} ${import_picocolors16.default.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`);
69239
70381
  break;
69240
70382
  case "local-dev":
69241
- lines.push(` ${SYMBOLS2.dev} ${import_picocolors15.default.cyan("Running in local development mode")}`);
69242
- lines.push(` ${import_picocolors15.default.dim("Using file:// protocol from config")}`);
70383
+ lines.push(` ${SYMBOLS3.dev} ${import_picocolors16.default.cyan("Running in local development mode")}`);
70384
+ lines.push(` ${import_picocolors16.default.dim("Using file:// protocol from config")}`);
69243
70385
  break;
69244
70386
  case "pinned":
69245
- lines.push(` ${SYMBOLS2.pin} ${import_picocolors15.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
69246
- lines.push(` ${import_picocolors15.default.dim("Update check skipped for pinned versions")}`);
70387
+ lines.push(` ${SYMBOLS3.pin} ${import_picocolors16.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
70388
+ lines.push(` ${import_picocolors16.default.dim("Update check skipped for pinned versions")}`);
69247
70389
  break;
69248
70390
  case "error":
69249
- lines.push(` ${SYMBOLS2.cross} ${import_picocolors15.default.red("Unable to check for updates")}`);
69250
- lines.push(` ${import_picocolors15.default.dim("Network error or npm registry unavailable")}`);
70391
+ lines.push(` ${SYMBOLS3.cross} ${import_picocolors16.default.red("Unable to check for updates")}`);
70392
+ lines.push(` ${import_picocolors16.default.dim("Network error or npm registry unavailable")}`);
69251
70393
  break;
69252
70394
  case "unknown":
69253
- lines.push(` ${SYMBOLS2.info} ${import_picocolors15.default.yellow("Version information unavailable")}`);
70395
+ lines.push(` ${SYMBOLS3.info} ${import_picocolors16.default.yellow("Version information unavailable")}`);
69254
70396
  break;
69255
70397
  }
69256
70398
  lines.push("");
@@ -69349,69 +70491,31 @@ async function getLocalVersion(options = {}) {
69349
70491
  return 1;
69350
70492
  }
69351
70493
  }
69352
- // src/cli/doctor/constants.ts
69353
- init_shared();
69354
- var import_picocolors16 = __toESM(require_picocolors(), 1);
69355
- var SYMBOLS3 = {
69356
- check: import_picocolors16.default.green("\u2713"),
69357
- cross: import_picocolors16.default.red("\u2717"),
69358
- warn: import_picocolors16.default.yellow("\u26A0"),
69359
- info: import_picocolors16.default.blue("\u2139"),
69360
- arrow: import_picocolors16.default.cyan("\u2192"),
69361
- bullet: import_picocolors16.default.dim("\u2022"),
69362
- skip: import_picocolors16.default.dim("\u25CB")
69363
- };
69364
- var STATUS_COLORS = {
69365
- pass: import_picocolors16.default.green,
69366
- fail: import_picocolors16.default.red,
69367
- warn: import_picocolors16.default.yellow,
69368
- skip: import_picocolors16.default.dim
69369
- };
69370
- var CHECK_IDS = {
69371
- SYSTEM: "system",
69372
- CONFIG: "config",
69373
- TOOLS: "tools",
69374
- MODELS: "models"
69375
- };
69376
- var CHECK_NAMES = {
69377
- [CHECK_IDS.SYSTEM]: "System",
69378
- [CHECK_IDS.CONFIG]: "Configuration",
69379
- [CHECK_IDS.TOOLS]: "Tools",
69380
- [CHECK_IDS.MODELS]: "Models"
69381
- };
69382
- var EXIT_CODES = {
69383
- SUCCESS: 0,
69384
- FAILURE: 1
69385
- };
69386
- var MIN_OPENCODE_VERSION = "1.0.150";
69387
- var PACKAGE_NAME2 = PLUGIN_NAME;
69388
- var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
69389
-
69390
70494
  // src/cli/doctor/checks/system.ts
69391
- import { existsSync as existsSync25, readFileSync as readFileSync22 } from "fs";
70495
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
69392
70496
 
69393
70497
  // src/cli/doctor/checks/system-binary.ts
69394
70498
  init_spawn_with_windows_hide();
69395
- import { existsSync as existsSync22 } from "fs";
70499
+ import { existsSync as existsSync26 } from "fs";
69396
70500
  import { homedir as homedir5 } from "os";
69397
- import { join as join21 } from "path";
70501
+ import { join as join25 } from "path";
69398
70502
  function getDesktopAppPaths(platform) {
69399
70503
  const home = homedir5();
69400
70504
  switch (platform) {
69401
70505
  case "darwin":
69402
70506
  return [
69403
70507
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
69404
- join21(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
70508
+ join25(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69405
70509
  ];
69406
70510
  case "win32": {
69407
70511
  const programFiles = process.env.ProgramFiles;
69408
70512
  const localAppData = process.env.LOCALAPPDATA;
69409
70513
  const paths = [];
69410
70514
  if (programFiles) {
69411
- paths.push(join21(programFiles, "OpenCode", "OpenCode.exe"));
70515
+ paths.push(join25(programFiles, "OpenCode", "OpenCode.exe"));
69412
70516
  }
69413
70517
  if (localAppData) {
69414
- paths.push(join21(localAppData, "OpenCode", "OpenCode.exe"));
70518
+ paths.push(join25(localAppData, "OpenCode", "OpenCode.exe"));
69415
70519
  }
69416
70520
  return paths;
69417
70521
  }
@@ -69419,8 +70523,8 @@ function getDesktopAppPaths(platform) {
69419
70523
  return [
69420
70524
  "/usr/bin/opencode",
69421
70525
  "/usr/lib/opencode/opencode",
69422
- join21(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69423
- join21(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
70526
+ join25(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
70527
+ join25(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69424
70528
  ];
69425
70529
  default:
69426
70530
  return [];
@@ -69432,7 +70536,7 @@ function buildVersionCommand(binaryPath, platform) {
69432
70536
  }
69433
70537
  return [binaryPath, "--version"];
69434
70538
  }
69435
- function findDesktopBinary(platform = process.platform, checkExists = existsSync22) {
70539
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync26) {
69436
70540
  for (const desktopPath of getDesktopAppPaths(platform)) {
69437
70541
  if (checkExists(desktopPath)) {
69438
70542
  return { binary: "opencode", path: desktopPath };
@@ -69449,7 +70553,7 @@ async function findOpenCodeBinary() {
69449
70553
  }
69450
70554
  return findDesktopBinary();
69451
70555
  }
69452
- async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
70556
+ async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
69453
70557
  try {
69454
70558
  const command = buildVersionCommand(binaryPath, platform);
69455
70559
  const processResult = spawnWithWindowsHide(command, { stdout: "pipe", stderr: "pipe" });
@@ -69462,10 +70566,10 @@ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
69462
70566
  return null;
69463
70567
  }
69464
70568
  }
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);
70569
+ function compareVersions3(current, minimum) {
70570
+ const parseVersion3 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
70571
+ const currentParts = parseVersion3(current);
70572
+ const minimumParts = parseVersion3(minimum);
69469
70573
  const length = Math.max(currentParts.length, minimumParts.length);
69470
70574
  for (let index = 0;index < length; index++) {
69471
70575
  const currentPart = currentParts[index] ?? 0;
@@ -69480,12 +70584,12 @@ function compareVersions(current, minimum) {
69480
70584
 
69481
70585
  // src/cli/doctor/checks/system-plugin.ts
69482
70586
  init_shared();
69483
- import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
70587
+ import { existsSync as existsSync27, readFileSync as readFileSync22 } from "fs";
69484
70588
  function detectConfigPath() {
69485
70589
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
69486
- if (existsSync23(paths.configJsonc))
70590
+ if (existsSync27(paths.configJsonc))
69487
70591
  return paths.configJsonc;
69488
- if (existsSync23(paths.configJson))
70592
+ if (existsSync27(paths.configJson))
69489
70593
  return paths.configJson;
69490
70594
  return null;
69491
70595
  }
@@ -69531,7 +70635,7 @@ function getPluginInfo() {
69531
70635
  };
69532
70636
  }
69533
70637
  try {
69534
- const content = readFileSync20(configPath, "utf-8");
70638
+ const content = readFileSync22(configPath, "utf-8");
69535
70639
  const parsedConfig = parseJsonc(content);
69536
70640
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
69537
70641
  if (!pluginEntry) {
@@ -69569,37 +70673,37 @@ function getPluginInfo() {
69569
70673
  init_file_utils();
69570
70674
  init_checker();
69571
70675
  init_auto_update_checker();
69572
- import { existsSync as existsSync24, readFileSync as readFileSync21 } from "fs";
70676
+ import { existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
69573
70677
  import { homedir as homedir6 } from "os";
69574
- import { join as join22 } from "path";
70678
+ import { join as join26 } from "path";
69575
70679
  init_shared();
69576
70680
  function getPlatformDefaultCacheDir(platform = process.platform) {
69577
70681
  if (platform === "darwin")
69578
- return join22(homedir6(), "Library", "Caches");
70682
+ return join26(homedir6(), "Library", "Caches");
69579
70683
  if (platform === "win32")
69580
- return process.env.LOCALAPPDATA ?? join22(homedir6(), "AppData", "Local");
69581
- return join22(homedir6(), ".cache");
70684
+ return process.env.LOCALAPPDATA ?? join26(homedir6(), "AppData", "Local");
70685
+ return join26(homedir6(), ".cache");
69582
70686
  }
69583
70687
  function resolveOpenCodeCacheDir() {
69584
70688
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
69585
70689
  if (xdgCacheHome)
69586
- return join22(xdgCacheHome, "opencode");
70690
+ return join26(xdgCacheHome, "opencode");
69587
70691
  const fromShared = getOpenCodeCacheDir();
69588
- const platformDefault = join22(getPlatformDefaultCacheDir(), "opencode");
69589
- if (existsSync24(fromShared) || !existsSync24(platformDefault))
70692
+ const platformDefault = join26(getPlatformDefaultCacheDir(), "opencode");
70693
+ if (existsSync28(fromShared) || !existsSync28(platformDefault))
69590
70694
  return fromShared;
69591
70695
  return platformDefault;
69592
70696
  }
69593
70697
  function resolveExistingDir(dirPath) {
69594
- if (!existsSync24(dirPath))
70698
+ if (!existsSync28(dirPath))
69595
70699
  return dirPath;
69596
70700
  return resolveSymlink(dirPath);
69597
70701
  }
69598
70702
  function readPackageJson(filePath) {
69599
- if (!existsSync24(filePath))
70703
+ if (!existsSync28(filePath))
69600
70704
  return null;
69601
70705
  try {
69602
- const content = readFileSync21(filePath, "utf-8");
70706
+ const content = readFileSync23(filePath, "utf-8");
69603
70707
  return parseJsonc(content);
69604
70708
  } catch {
69605
70709
  return null;
@@ -69618,20 +70722,20 @@ function getLoadedPluginVersion() {
69618
70722
  const candidates = [
69619
70723
  {
69620
70724
  cacheDir: configDir,
69621
- cachePackagePath: join22(configDir, "package.json"),
69622
- installedPackagePath: join22(configDir, "node_modules", PACKAGE_NAME2, "package.json")
70725
+ cachePackagePath: join26(configDir, "package.json"),
70726
+ installedPackagePath: join26(configDir, "node_modules", PACKAGE_NAME, "package.json")
69623
70727
  },
69624
70728
  {
69625
70729
  cacheDir,
69626
- cachePackagePath: join22(cacheDir, "package.json"),
69627
- installedPackagePath: join22(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
70730
+ cachePackagePath: join26(cacheDir, "package.json"),
70731
+ installedPackagePath: join26(cacheDir, "node_modules", PACKAGE_NAME, "package.json")
69628
70732
  }
69629
70733
  ];
69630
- const selectedCandidate = candidates.find((candidate) => existsSync24(candidate.installedPackagePath)) ?? candidates[0];
70734
+ const selectedCandidate = candidates.find((candidate) => existsSync28(candidate.installedPackagePath)) ?? candidates[0];
69631
70735
  const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
69632
70736
  const cachePackage = readPackageJson(cachePackagePath);
69633
70737
  const installedPackage = readPackageJson(installedPackagePath);
69634
- const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME2]);
70738
+ const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME]);
69635
70739
  const loadedVersion = normalizeVersion(installedPackage?.version);
69636
70740
  return {
69637
70741
  cacheDir: selectedDir,
@@ -69654,10 +70758,10 @@ init_shared();
69654
70758
  function isConfigValid(configPath) {
69655
70759
  if (!configPath)
69656
70760
  return true;
69657
- if (!existsSync25(configPath))
70761
+ if (!existsSync29(configPath))
69658
70762
  return false;
69659
70763
  try {
69660
- parseJsonc(readFileSync22(configPath, "utf-8"));
70764
+ parseJsonc(readFileSync24(configPath, "utf-8"));
69661
70765
  return true;
69662
70766
  } catch {
69663
70767
  return false;
@@ -69680,7 +70784,7 @@ function buildMessage(status, issues) {
69680
70784
  async function gatherSystemInfo() {
69681
70785
  const [binaryInfo, pluginInfo] = await Promise.all([findOpenCodeBinary(), Promise.resolve(getPluginInfo())]);
69682
70786
  const loadedInfo = getLoadedPluginVersion();
69683
- const opencodeVersion = binaryInfo ? await getOpenCodeVersion2(binaryInfo.path) : null;
70787
+ const opencodeVersion = binaryInfo ? await getOpenCodeVersion3(binaryInfo.path) : null;
69684
70788
  const pluginVersion = pluginInfo.pinnedVersion ?? loadedInfo.expectedVersion ?? loadedInfo.loadedVersion;
69685
70789
  return {
69686
70790
  opencodeVersion,
@@ -69708,7 +70812,7 @@ async function checkSystem() {
69708
70812
  affects: ["doctor", "run"]
69709
70813
  });
69710
70814
  }
69711
- if (systemInfo.opencodeVersion && !compareVersions(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
70815
+ if (systemInfo.opencodeVersion && !compareVersions3(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69712
70816
  issues.push({
69713
70817
  title: "OpenCode version below minimum",
69714
70818
  description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
@@ -69748,7 +70852,7 @@ async function checkSystem() {
69748
70852
  affects: ["plugin loading"]
69749
70853
  });
69750
70854
  }
69751
- if (systemInfo.loadedVersion && latestVersion && !compareVersions(systemInfo.loadedVersion, latestVersion)) {
70855
+ if (systemInfo.loadedVersion && latestVersion && !compareVersions3(systemInfo.loadedVersion, latestVersion)) {
69752
70856
  issues.push({
69753
70857
  title: "Loaded plugin is outdated",
69754
70858
  description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
@@ -69773,28 +70877,28 @@ async function checkSystem() {
69773
70877
  }
69774
70878
 
69775
70879
  // src/cli/doctor/checks/config.ts
69776
- import { readFileSync as readFileSync25 } from "fs";
69777
- import { join as join26 } from "path";
70880
+ import { readFileSync as readFileSync27 } from "fs";
70881
+ import { join as join30 } from "path";
69778
70882
  init_shared();
69779
70883
 
69780
70884
  // src/cli/doctor/checks/model-resolution-cache.ts
69781
70885
  init_shared();
69782
- import { existsSync as existsSync26, readFileSync as readFileSync23 } from "fs";
70886
+ import { existsSync as existsSync30, readFileSync as readFileSync25 } from "fs";
69783
70887
  import { homedir as homedir7 } from "os";
69784
- import { join as join23 } from "path";
70888
+ import { join as join27 } from "path";
69785
70889
  function getOpenCodeCacheDir2() {
69786
70890
  const xdgCache = process.env.XDG_CACHE_HOME;
69787
70891
  if (xdgCache)
69788
- return join23(xdgCache, "opencode");
69789
- return join23(homedir7(), ".cache", "opencode");
70892
+ return join27(xdgCache, "opencode");
70893
+ return join27(homedir7(), ".cache", "opencode");
69790
70894
  }
69791
70895
  function loadAvailableModelsFromCache() {
69792
- const cacheFile = join23(getOpenCodeCacheDir2(), "models.json");
69793
- if (!existsSync26(cacheFile)) {
70896
+ const cacheFile = join27(getOpenCodeCacheDir2(), "models.json");
70897
+ if (!existsSync30(cacheFile)) {
69794
70898
  return { providers: [], modelCount: 0, cacheExists: false };
69795
70899
  }
69796
70900
  try {
69797
- const content = readFileSync23(cacheFile, "utf-8");
70901
+ const content = readFileSync25(cacheFile, "utf-8");
69798
70902
  const data = parseJsonc(content);
69799
70903
  const providers = Object.keys(data);
69800
70904
  let modelCount = 0;
@@ -69816,14 +70920,14 @@ init_model_capabilities();
69816
70920
 
69817
70921
  // src/cli/doctor/checks/model-resolution-config.ts
69818
70922
  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");
70923
+ import { readFileSync as readFileSync26 } from "fs";
70924
+ import { join as join28 } from "path";
70925
+ var PROJECT_CONFIG_DIR = join28(process.cwd(), ".opencode");
69822
70926
  function loadOmoConfig() {
69823
70927
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
69824
70928
  if (projectDetected.format !== "none") {
69825
70929
  try {
69826
- const content = readFileSync24(projectDetected.path, "utf-8");
70930
+ const content = readFileSync26(projectDetected.path, "utf-8");
69827
70931
  return parseJsonc(content);
69828
70932
  } catch {
69829
70933
  return null;
@@ -69833,7 +70937,7 @@ function loadOmoConfig() {
69833
70937
  const userDetected = detectPluginConfigFile(userConfigDir);
69834
70938
  if (userDetected.format !== "none") {
69835
70939
  try {
69836
- const content = readFileSync24(userDetected.path, "utf-8");
70940
+ const content = readFileSync26(userDetected.path, "utf-8");
69837
70941
  return parseJsonc(content);
69838
70942
  } catch {
69839
70943
  return null;
@@ -69844,7 +70948,7 @@ function loadOmoConfig() {
69844
70948
 
69845
70949
  // src/cli/doctor/checks/model-resolution-details.ts
69846
70950
  init_shared();
69847
- import { join as join25 } from "path";
70951
+ import { join as join29 } from "path";
69848
70952
 
69849
70953
  // src/cli/doctor/checks/model-resolution-variant.ts
69850
70954
  function formatModelWithVariant(model, variant) {
@@ -69886,7 +70990,7 @@ function formatCapabilityResolutionLabel(mode) {
69886
70990
  }
69887
70991
  function buildModelResolutionDetails(options) {
69888
70992
  const details = [];
69889
- const cacheFile = join25(getOpenCodeCacheDir(), "models.json");
70993
+ const cacheFile = join29(getOpenCodeCacheDir(), "models.json");
69890
70994
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
69891
70995
  details.push("");
69892
70996
  if (options.available.cacheExists) {
@@ -70041,7 +71145,7 @@ async function checkModels() {
70041
71145
  }
70042
71146
 
70043
71147
  // src/cli/doctor/checks/config.ts
70044
- var PROJECT_CONFIG_DIR2 = join26(process.cwd(), ".opencode");
71148
+ var PROJECT_CONFIG_DIR2 = join30(process.cwd(), ".opencode");
70045
71149
  function findConfigPath() {
70046
71150
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
70047
71151
  if (projectConfig.format !== "none")
@@ -70058,7 +71162,7 @@ function validateConfig() {
70058
71162
  return { exists: false, path: null, valid: true, config: null, errors: [] };
70059
71163
  }
70060
71164
  try {
70061
- const content = readFileSync25(configPath, "utf-8");
71165
+ const content = readFileSync27(configPath, "utf-8");
70062
71166
  const rawConfig = parseJsonc(content);
70063
71167
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
70064
71168
  if (!schemaResult.success) {
@@ -70162,9 +71266,9 @@ async function checkConfig() {
70162
71266
 
70163
71267
  // src/cli/doctor/checks/dependencies.ts
70164
71268
  init_spawn_with_windows_hide();
70165
- import { existsSync as existsSync27 } from "fs";
71269
+ import { existsSync as existsSync31 } from "fs";
70166
71270
  import { createRequire } from "module";
70167
- import { dirname as dirname9, join as join27 } from "path";
71271
+ import { dirname as dirname10, join as join31 } from "path";
70168
71272
  async function checkBinaryExists(binary2) {
70169
71273
  try {
70170
71274
  const path10 = Bun.which(binary2);
@@ -70220,15 +71324,15 @@ async function checkAstGrepNapi() {
70220
71324
  path: null
70221
71325
  };
70222
71326
  } catch {
70223
- const { existsSync: existsSync28 } = await import("fs");
70224
- const { join: join28 } = await import("path");
71327
+ const { existsSync: existsSync32 } = await import("fs");
71328
+ const { join: join32 } = await import("path");
70225
71329
  const { homedir: homedir8 } = await import("os");
70226
71330
  const pathsToCheck = [
70227
- join28(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70228
- join28(process.cwd(), "node_modules", "@ast-grep", "napi")
71331
+ join32(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
71332
+ join32(process.cwd(), "node_modules", "@ast-grep", "napi")
70229
71333
  ];
70230
71334
  for (const napiPath of pathsToCheck) {
70231
- if (existsSync28(napiPath)) {
71335
+ if (existsSync32(napiPath)) {
70232
71336
  return {
70233
71337
  name: "AST-Grep NAPI",
70234
71338
  required: false,
@@ -70253,8 +71357,8 @@ function findCommentCheckerPackageBinary() {
70253
71357
  try {
70254
71358
  const require2 = createRequire(import.meta.url);
70255
71359
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
70256
- const binaryPath = join27(dirname9(pkgPath), "bin", binaryName);
70257
- if (existsSync27(binaryPath))
71360
+ const binaryPath = join31(dirname10(pkgPath), "bin", binaryName);
71361
+ if (existsSync31(binaryPath))
70258
71362
  return binaryPath;
70259
71363
  } catch {}
70260
71364
  return null;
@@ -70411,15 +71515,15 @@ var BUILTIN_SERVERS = {
70411
71515
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
70412
71516
  };
70413
71517
  // src/tools/lsp/server-config-loader.ts
70414
- import { existsSync as existsSync28, readFileSync as readFileSync26 } from "fs";
70415
- import { join as join28 } from "path";
71518
+ import { existsSync as existsSync32, readFileSync as readFileSync28 } from "fs";
71519
+ import { join as join32 } from "path";
70416
71520
  init_shared();
70417
71521
  init_jsonc_parser();
70418
71522
  function loadJsonFile(path10) {
70419
- if (!existsSync28(path10))
71523
+ if (!existsSync32(path10))
70420
71524
  return null;
70421
71525
  try {
70422
- return parseJsonc(readFileSync26(path10, "utf-8"));
71526
+ return parseJsonc(readFileSync28(path10, "utf-8"));
70423
71527
  } catch {
70424
71528
  return null;
70425
71529
  }
@@ -70428,9 +71532,9 @@ function getConfigPaths2() {
70428
71532
  const cwd = process.cwd();
70429
71533
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70430
71534
  return {
70431
- project: detectPluginConfigFile(join28(cwd, ".opencode")).path,
71535
+ project: detectPluginConfigFile(join32(cwd, ".opencode")).path,
70432
71536
  user: detectPluginConfigFile(configDir).path,
70433
- opencode: detectConfigFile(join28(configDir, "opencode")).path
71537
+ opencode: detectConfigFile(join32(configDir, "opencode")).path
70434
71538
  };
70435
71539
  }
70436
71540
  function loadAllConfigs() {
@@ -70499,21 +71603,21 @@ function getMergedServers() {
70499
71603
  }
70500
71604
 
70501
71605
  // src/tools/lsp/server-installation.ts
70502
- import { existsSync as existsSync29 } from "fs";
70503
- import { delimiter as delimiter2, join as join30 } from "path";
71606
+ import { existsSync as existsSync33 } from "fs";
71607
+ import { delimiter as delimiter2, join as join34 } from "path";
70504
71608
 
70505
71609
  // src/tools/lsp/server-path-bases.ts
70506
71610
  init_shared();
70507
- import { join as join29 } from "path";
71611
+ import { join as join33 } from "path";
70508
71612
  function getLspServerAdditionalPathBases(workingDirectory) {
70509
71613
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70510
- const dataDir = join29(getDataDir(), "opencode");
71614
+ const dataDir = join33(getDataDir(), "opencode");
70511
71615
  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")
71616
+ join33(workingDirectory, "node_modules", ".bin"),
71617
+ join33(configDir, "bin"),
71618
+ join33(configDir, "node_modules", ".bin"),
71619
+ join33(dataDir, "bin"),
71620
+ join33(dataDir, "bin", "node_modules", ".bin")
70517
71621
  ];
70518
71622
  }
70519
71623
 
@@ -70523,7 +71627,7 @@ function isServerInstalled(command) {
70523
71627
  return false;
70524
71628
  const cmd = command[0];
70525
71629
  if (cmd.includes("/") || cmd.includes("\\")) {
70526
- if (existsSync29(cmd))
71630
+ if (existsSync33(cmd))
70527
71631
  return true;
70528
71632
  }
70529
71633
  const isWindows = process.platform === "win32";
@@ -70544,14 +71648,14 @@ function isServerInstalled(command) {
70544
71648
  const paths = pathEnv.split(delimiter2);
70545
71649
  for (const p2 of paths) {
70546
71650
  for (const suffix of exts) {
70547
- if (existsSync29(join30(p2, cmd + suffix))) {
71651
+ if (existsSync33(join34(p2, cmd + suffix))) {
70548
71652
  return true;
70549
71653
  }
70550
71654
  }
70551
71655
  }
70552
71656
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
70553
71657
  for (const suffix of exts) {
70554
- if (existsSync29(join30(base, cmd + suffix))) {
71658
+ if (existsSync33(join34(base, cmd + suffix))) {
70555
71659
  return true;
70556
71660
  }
70557
71661
  }
@@ -70613,24 +71717,24 @@ function getInstalledLspServers() {
70613
71717
 
70614
71718
  // src/cli/doctor/checks/tools-mcp.ts
70615
71719
  init_shared();
70616
- import { existsSync as existsSync30, readFileSync as readFileSync27 } from "fs";
71720
+ import { existsSync as existsSync34, readFileSync as readFileSync29 } from "fs";
70617
71721
  import { homedir as homedir8 } from "os";
70618
- import { join as join31 } from "path";
71722
+ import { join as join35 } from "path";
70619
71723
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
70620
71724
  function getMcpConfigPaths() {
70621
71725
  return [
70622
- join31(homedir8(), ".claude", ".mcp.json"),
70623
- join31(process.cwd(), ".mcp.json"),
70624
- join31(process.cwd(), ".claude", ".mcp.json")
71726
+ join35(homedir8(), ".claude", ".mcp.json"),
71727
+ join35(process.cwd(), ".mcp.json"),
71728
+ join35(process.cwd(), ".claude", ".mcp.json")
70625
71729
  ];
70626
71730
  }
70627
71731
  function loadUserMcpConfig() {
70628
71732
  const servers = {};
70629
71733
  for (const configPath of getMcpConfigPaths()) {
70630
- if (!existsSync30(configPath))
71734
+ if (!existsSync34(configPath))
70631
71735
  continue;
70632
71736
  try {
70633
- const content = readFileSync27(configPath, "utf-8");
71737
+ const content = readFileSync29(configPath, "utf-8");
70634
71738
  const config2 = parseJsonc(content);
70635
71739
  if (config2.mcpServers) {
70636
71740
  Object.assign(servers, config2.mcpServers);
@@ -70797,17 +71901,17 @@ function formatStatusSymbol(status) {
70797
71901
  const colorFn = STATUS_COLORS[status];
70798
71902
  switch (status) {
70799
71903
  case "pass":
70800
- return colorFn(SYMBOLS3.check);
71904
+ return colorFn(SYMBOLS2.check);
70801
71905
  case "fail":
70802
- return colorFn(SYMBOLS3.cross);
71906
+ return colorFn(SYMBOLS2.cross);
70803
71907
  case "warn":
70804
- return colorFn(SYMBOLS3.warn);
71908
+ return colorFn(SYMBOLS2.warn);
70805
71909
  case "skip":
70806
- return colorFn(SYMBOLS3.skip);
71910
+ return colorFn(SYMBOLS2.skip);
70807
71911
  }
70808
71912
  }
70809
71913
  function formatStatusMark(available) {
70810
- return available ? import_picocolors17.default.green(SYMBOLS3.check) : import_picocolors17.default.red(SYMBOLS3.cross);
71914
+ return available ? import_picocolors17.default.green(SYMBOLS2.check) : import_picocolors17.default.red(SYMBOLS2.cross);
70811
71915
  }
70812
71916
  function formatHeader() {
70813
71917
  return `
@@ -70837,12 +71941,12 @@ function formatDefault(result) {
70837
71941
  if (allIssues.length === 0) {
70838
71942
  const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
70839
71943
  const pluginVer = result.systemInfo.pluginVersion ?? "unknown";
70840
- lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 oh-my-opencode ${pluginVer})`)}`);
71944
+ lines.push(` ${import_picocolors18.default.green(SYMBOLS2.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 oh-my-opencode ${pluginVer})`)}`);
70841
71945
  } else {
70842
71946
  const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
70843
71947
  const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
70844
71948
  const totalStr = `${issueCount + warnCount} ${issueCount + warnCount === 1 ? "issue" : "issues"}`;
70845
- lines.push(` ${import_picocolors18.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
71949
+ lines.push(` ${import_picocolors18.default.yellow(SYMBOLS2.warn)} ${totalStr} found:
70846
71950
  `);
70847
71951
  allIssues.forEach((issue2, index) => {
70848
71952
  lines.push(formatIssue(issue2, index + 1));
@@ -71083,11 +72187,11 @@ async function refreshModelCapabilities(options, deps = {}) {
71083
72187
 
71084
72188
  // src/features/mcp-oauth/storage.ts
71085
72189
  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";
72190
+ import { chmodSync, existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync30, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
72191
+ import { dirname as dirname11, join as join36 } from "path";
71088
72192
  var STORAGE_FILE_NAME = "mcp-oauth.json";
71089
72193
  function getMcpOauthStoragePath() {
71090
- return join32(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
72194
+ return join36(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71091
72195
  }
71092
72196
  function normalizeHost(serverHost) {
71093
72197
  let host = serverHost.trim();
@@ -71124,11 +72228,11 @@ function buildKey(serverHost, resource) {
71124
72228
  }
71125
72229
  function readStore() {
71126
72230
  const filePath = getMcpOauthStoragePath();
71127
- if (!existsSync31(filePath)) {
72231
+ if (!existsSync35(filePath)) {
71128
72232
  return null;
71129
72233
  }
71130
72234
  try {
71131
- const content = readFileSync28(filePath, "utf-8");
72235
+ const content = readFileSync30(filePath, "utf-8");
71132
72236
  return JSON.parse(content);
71133
72237
  } catch {
71134
72238
  return null;
@@ -71137,12 +72241,14 @@ function readStore() {
71137
72241
  function writeStore(store2) {
71138
72242
  const filePath = getMcpOauthStoragePath();
71139
72243
  try {
71140
- const dir = dirname10(filePath);
71141
- if (!existsSync31(dir)) {
71142
- mkdirSync8(dir, { recursive: true });
71143
- }
71144
- writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
71145
- chmodSync(filePath, 384);
72244
+ const dir = dirname11(filePath);
72245
+ if (!existsSync35(dir)) {
72246
+ mkdirSync9(dir, { recursive: true });
72247
+ }
72248
+ const tempPath = `${filePath}.tmp.${Date.now()}`;
72249
+ writeFileSync10(tempPath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
72250
+ chmodSync(tempPath, 384);
72251
+ renameSync4(tempPath, filePath);
71146
72252
  return true;
71147
72253
  } catch {
71148
72254
  return false;
@@ -71173,7 +72279,7 @@ function deleteToken(serverHost, resource) {
71173
72279
  if (Object.keys(store2).length === 0) {
71174
72280
  try {
71175
72281
  const filePath = getMcpOauthStoragePath();
71176
- if (existsSync31(filePath)) {
72282
+ if (existsSync35(filePath)) {
71177
72283
  unlinkSync4(filePath);
71178
72284
  }
71179
72285
  return true;
@@ -71363,7 +72469,7 @@ async function findAvailablePort2(startPort = DEFAULT_PORT) {
71363
72469
  }
71364
72470
 
71365
72471
  // src/features/mcp-oauth/oauth-authorization-flow.ts
71366
- import { spawn as spawn2 } from "child_process";
72472
+ import { spawn } from "child_process";
71367
72473
  import { createHash, randomBytes as randomBytes2 } from "crypto";
71368
72474
  import { createServer } from "http";
71369
72475
  function generateCodeVerifier() {
@@ -71396,7 +72502,7 @@ function startCallbackServer(port) {
71396
72502
  clearTimeout(timeoutId);
71397
72503
  const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
71398
72504
  const code = requestUrl.searchParams.get("code");
71399
- const state = requestUrl.searchParams.get("state");
72505
+ const state2 = requestUrl.searchParams.get("state");
71400
72506
  const error48 = requestUrl.searchParams.get("error");
71401
72507
  if (error48) {
71402
72508
  const errorDescription = requestUrl.searchParams.get("error_description") ?? error48;
@@ -71406,7 +72512,7 @@ function startCallbackServer(port) {
71406
72512
  reject(new Error(`OAuth authorization error: ${errorDescription}`));
71407
72513
  return;
71408
72514
  }
71409
- if (!code || !state) {
72515
+ if (!code || !state2) {
71410
72516
  response.writeHead(400, { "content-type": "text/html" });
71411
72517
  response.end("<html><body><h1>Missing code or state</h1></body></html>");
71412
72518
  server2.close();
@@ -71416,7 +72522,7 @@ function startCallbackServer(port) {
71416
72522
  response.writeHead(200, { "content-type": "text/html" });
71417
72523
  response.end("<html><body><h1>Authorization successful. You can close this tab.</h1></body></html>");
71418
72524
  server2.close();
71419
- resolve2({ code, state });
72525
+ resolve2({ code, state: state2 });
71420
72526
  });
71421
72527
  timeoutId = setTimeout(() => {
71422
72528
  server2.close();
@@ -71444,7 +72550,7 @@ function openBrowser(url2) {
71444
72550
  args = [url2];
71445
72551
  }
71446
72552
  try {
71447
- const child = spawn2(command, args, { stdio: "ignore", detached: true });
72553
+ const child = spawn(command, args, { stdio: "ignore", detached: true });
71448
72554
  child.on("error", () => {});
71449
72555
  child.unref();
71450
72556
  } catch {}
@@ -71452,25 +72558,57 @@ function openBrowser(url2) {
71452
72558
  async function runAuthorizationCodeRedirect(options) {
71453
72559
  const verifier = generateCodeVerifier();
71454
72560
  const challenge = generateCodeChallenge(verifier);
71455
- const state = randomBytes2(16).toString("hex");
72561
+ const state2 = randomBytes2(16).toString("hex");
71456
72562
  const authorizationUrl = buildAuthorizationUrl(options.authorizationEndpoint, {
71457
72563
  clientId: options.clientId,
71458
72564
  redirectUri: options.redirectUri,
71459
72565
  codeChallenge: challenge,
71460
- state,
72566
+ state: state2,
71461
72567
  scopes: options.scopes,
71462
72568
  resource: options.resource
71463
72569
  });
71464
72570
  const callbackPromise = startCallbackServer(options.callbackPort);
71465
72571
  openBrowser(authorizationUrl);
71466
72572
  const result = await callbackPromise;
71467
- if (result.state !== state) {
72573
+ if (result.state !== state2) {
71468
72574
  throw new Error("OAuth state mismatch");
71469
72575
  }
71470
72576
  return { code: result.code, verifier };
71471
72577
  }
71472
72578
 
71473
72579
  // src/features/mcp-oauth/provider.ts
72580
+ async function parseTokenResponse(tokenResponse) {
72581
+ if (!tokenResponse.ok) {
72582
+ let errorDetail = `${tokenResponse.status}`;
72583
+ try {
72584
+ const body = await tokenResponse.json();
72585
+ if (body.error) {
72586
+ errorDetail = `${tokenResponse.status} ${body.error}`;
72587
+ if (body.error_description) {
72588
+ errorDetail += `: ${body.error_description}`;
72589
+ }
72590
+ }
72591
+ } catch {}
72592
+ throw new Error(`Token exchange failed: ${errorDetail}`);
72593
+ }
72594
+ return await tokenResponse.json();
72595
+ }
72596
+ function buildOAuthTokenData(tokenData, clientInfo, fallbackRefreshToken) {
72597
+ const accessToken = tokenData.access_token;
72598
+ if (typeof accessToken !== "string") {
72599
+ throw new Error("Token response missing access_token");
72600
+ }
72601
+ return {
72602
+ accessToken,
72603
+ refreshToken: typeof tokenData.refresh_token === "string" ? tokenData.refresh_token : fallbackRefreshToken,
72604
+ expiresAt: typeof tokenData.expires_in === "number" ? Math.floor(Date.now() / 1000) + tokenData.expires_in : undefined,
72605
+ clientInfo: {
72606
+ clientId: clientInfo.clientId,
72607
+ ...clientInfo.clientSecret ? { clientSecret: clientInfo.clientSecret } : {}
72608
+ }
72609
+ };
72610
+ }
72611
+
71474
72612
  class McpOAuthProvider {
71475
72613
  serverUrl;
71476
72614
  configClientId;
@@ -71565,33 +72703,34 @@ class McpOAuthProvider {
71565
72703
  ...metadata.resource ? { resource: metadata.resource } : {}
71566
72704
  }).toString()
71567
72705
  });
71568
- if (!tokenResponse.ok) {
71569
- let errorDetail = `${tokenResponse.status}`;
71570
- try {
71571
- const body = await tokenResponse.json();
71572
- if (body.error) {
71573
- errorDetail = `${tokenResponse.status} ${body.error}`;
71574
- if (body.error_description) {
71575
- errorDetail += `: ${body.error_description}`;
71576
- }
71577
- }
71578
- } catch {}
71579
- throw new Error(`Token exchange failed: ${errorDetail}`);
71580
- }
71581
- const tokenData = await tokenResponse.json();
71582
- const accessToken = tokenData.access_token;
71583
- if (typeof accessToken !== "string") {
71584
- throw new Error("Token response missing access_token");
72706
+ const tokenData = await parseTokenResponse(tokenResponse);
72707
+ const oauthTokenData = buildOAuthTokenData(tokenData, clientInfo);
72708
+ this.saveTokens(oauthTokenData);
72709
+ return oauthTokenData;
72710
+ }
72711
+ async refresh(refreshToken) {
72712
+ const metadata = await discoverOAuthServerMetadata(this.serverUrl);
72713
+ const clientInfo = this.clientInformation();
72714
+ const clientId = clientInfo?.clientId ?? this.configClientId;
72715
+ if (!clientId) {
72716
+ throw new Error("No client information available. Run login() or register a client first.");
71585
72717
  }
71586
- const oauthTokenData = {
71587
- accessToken,
71588
- refreshToken: typeof tokenData.refresh_token === "string" ? tokenData.refresh_token : undefined,
71589
- expiresAt: typeof tokenData.expires_in === "number" ? Math.floor(Date.now() / 1000) + tokenData.expires_in : undefined,
71590
- clientInfo: {
71591
- clientId: clientInfo.clientId,
71592
- clientSecret: clientInfo.clientSecret
71593
- }
71594
- };
72718
+ const tokenResponse = await fetch(metadata.tokenEndpoint, {
72719
+ method: "POST",
72720
+ headers: { "content-type": "application/x-www-form-urlencoded" },
72721
+ body: new URLSearchParams({
72722
+ grant_type: "refresh_token",
72723
+ refresh_token: refreshToken,
72724
+ client_id: clientId,
72725
+ ...clientInfo?.clientSecret ? { client_secret: clientInfo.clientSecret } : {},
72726
+ ...metadata.resource ? { resource: metadata.resource } : {}
72727
+ }).toString()
72728
+ });
72729
+ const tokenData = await parseTokenResponse(tokenResponse);
72730
+ const oauthTokenData = buildOAuthTokenData(tokenData, {
72731
+ clientId,
72732
+ ...clientInfo?.clientSecret ? { clientSecret: clientInfo.clientSecret } : {}
72733
+ }, refreshToken);
71595
72734
  this.saveTokens(oauthTokenData);
71596
72735
  return oauthTokenData;
71597
72736
  }