oh-my-opencode 3.15.3 → 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 (49) 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 +1421 -533
  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/types.d.ts +1 -0
  11. package/dist/create-managers.d.ts +14 -0
  12. package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +5 -2
  13. package/dist/features/boulder-state/storage.d.ts +7 -0
  14. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +1 -1
  15. package/dist/features/claude-code-mcp-loader/env-expander.d.ts +5 -2
  16. package/dist/features/claude-code-plugin-loader/loader.d.ts +15 -0
  17. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +2 -0
  18. package/dist/features/claude-code-plugin-loader/types.d.ts +11 -0
  19. package/dist/features/claude-code-session-state/state.d.ts +1 -0
  20. package/dist/features/mcp-oauth/provider.d.ts +1 -0
  21. package/dist/features/mcp-oauth/refresh-mutex.d.ts +26 -0
  22. package/dist/features/skill-mcp-manager/error-redaction.d.ts +10 -0
  23. package/dist/features/skill-mcp-manager/oauth-handler.d.ts +7 -0
  24. package/dist/features/skill-mcp-manager/types.d.ts +3 -1
  25. package/dist/hooks/atlas/types.d.ts +1 -0
  26. package/dist/hooks/auto-update-checker/constants.d.ts +2 -2
  27. package/dist/hooks/keyword-detector/hook.d.ts +2 -1
  28. package/dist/hooks/ralph-loop/constants.d.ts +1 -0
  29. package/dist/hooks/ralph-loop/oracle-verification-detector.d.ts +8 -0
  30. package/dist/hooks/read-image-resizer/png-fallback-resizer.d.ts +2 -0
  31. package/dist/hooks/runtime-fallback/auto-retry-signal.d.ts +4 -0
  32. package/dist/hooks/runtime-fallback/error-classifier.d.ts +1 -5
  33. package/dist/hooks/session-recovery/types.d.ts +2 -0
  34. package/dist/hooks/todo-continuation-enforcer/pending-question-detection.d.ts +1 -1
  35. package/dist/hooks/todo-continuation-enforcer/token-limit-detection.d.ts +4 -0
  36. package/dist/hooks/todo-continuation-enforcer/types.d.ts +7 -0
  37. package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
  38. package/dist/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.d.ts +2 -0
  39. package/dist/index.js +1957 -1020
  40. package/dist/plugin/chat-params.d.ts +1 -0
  41. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  42. package/dist/shared/agent-display-names.d.ts +9 -2
  43. package/dist/shared/compaction-marker.d.ts +12 -0
  44. package/dist/shared/index.d.ts +1 -0
  45. package/dist/shared/internal-initiator-marker.d.ts +1 -0
  46. package/dist/shared/session-prompt-params-state.d.ts +1 -0
  47. package/dist/tools/background-task/constants.d.ts +1 -1
  48. package/package.json +16 -18
  49. 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",
@@ -48375,6 +48379,57 @@ var init_constants = __esm(() => {
48375
48379
  init_shared();
48376
48380
  });
48377
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
+
48378
48433
  // src/features/hook-message-injector/injector.ts
48379
48434
  import { randomBytes } from "crypto";
48380
48435
  var processPrefix;
@@ -48383,6 +48438,7 @@ var init_injector = __esm(() => {
48383
48438
  init_logger();
48384
48439
  init_opencode_storage_detection();
48385
48440
  init_shared();
48441
+ init_compaction_marker();
48386
48442
  processPrefix = randomBytes(4).toString("hex");
48387
48443
  });
48388
48444
 
@@ -48392,35 +48448,24 @@ var init_hook_message_injector = __esm(() => {
48392
48448
  init_constants();
48393
48449
  });
48394
48450
 
48395
- // src/shared/opencode-storage-paths.ts
48396
- import { join as join8 } from "path";
48397
- var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48398
- var init_opencode_storage_paths = __esm(() => {
48399
- init_data_path();
48400
- OPENCODE_STORAGE = getOpenCodeStorageDir();
48401
- MESSAGE_STORAGE = join8(OPENCODE_STORAGE, "message");
48402
- PART_STORAGE = join8(OPENCODE_STORAGE, "part");
48403
- SESSION_STORAGE = join8(OPENCODE_STORAGE, "session");
48404
- });
48405
-
48406
48451
  // src/shared/opencode-message-dir.ts
48407
- import { existsSync as existsSync6, readdirSync } from "fs";
48408
- import { join as join9 } from "path";
48452
+ import { existsSync as existsSync7, readdirSync as readdirSync2 } from "fs";
48453
+ import { join as join10 } from "path";
48409
48454
  function getMessageDir(sessionID) {
48410
48455
  if (!sessionID.startsWith("ses_"))
48411
48456
  return null;
48412
48457
  if (/[/\\]|\.\./.test(sessionID))
48413
48458
  return null;
48414
- if (!existsSync6(MESSAGE_STORAGE))
48459
+ if (!existsSync7(MESSAGE_STORAGE))
48415
48460
  return null;
48416
- const directPath = join9(MESSAGE_STORAGE, sessionID);
48417
- if (existsSync6(directPath)) {
48461
+ const directPath = join10(MESSAGE_STORAGE, sessionID);
48462
+ if (existsSync7(directPath)) {
48418
48463
  return directPath;
48419
48464
  }
48420
48465
  try {
48421
- for (const dir of readdirSync(MESSAGE_STORAGE)) {
48422
- const sessionPath = join9(MESSAGE_STORAGE, dir, sessionID);
48423
- if (existsSync6(sessionPath)) {
48466
+ for (const dir of readdirSync2(MESSAGE_STORAGE)) {
48467
+ const sessionPath = join10(MESSAGE_STORAGE, dir, sessionID);
48468
+ if (existsSync7(sessionPath)) {
48424
48469
  return sessionPath;
48425
48470
  }
48426
48471
  }
@@ -48455,22 +48500,25 @@ function getAgentConfigKey(agentName) {
48455
48500
  const reversed = REVERSE_DISPLAY_NAMES[lower];
48456
48501
  if (reversed !== undefined)
48457
48502
  return reversed;
48503
+ const legacy = LEGACY_DISPLAY_NAMES[lower];
48504
+ if (legacy !== undefined)
48505
+ return legacy;
48458
48506
  if (AGENT_DISPLAY_NAMES[lower] !== undefined)
48459
48507
  return lower;
48460
48508
  return lower;
48461
48509
  }
48462
- var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES;
48510
+ var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
48463
48511
  var init_agent_display_names = __esm(() => {
48464
48512
  AGENT_DISPLAY_NAMES = {
48465
- sisyphus: "Sisyphus (Ultraworker)",
48466
- hephaestus: "Hephaestus (Deep Agent)",
48467
- prometheus: "Prometheus (Plan Builder)",
48468
- atlas: "Atlas (Plan Executor)",
48513
+ sisyphus: "Sisyphus - Ultraworker",
48514
+ hephaestus: "Hephaestus - Deep Agent",
48515
+ prometheus: "Prometheus - Plan Builder",
48516
+ atlas: "Atlas - Plan Executor",
48469
48517
  "sisyphus-junior": "Sisyphus-Junior",
48470
- metis: "Metis (Plan Consultant)",
48471
- momus: "Momus (Plan Critic)",
48472
- athena: "Athena (Council)",
48473
- "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",
48474
48522
  oracle: "oracle",
48475
48523
  librarian: "librarian",
48476
48524
  explore: "explore",
@@ -48478,6 +48526,16 @@ var init_agent_display_names = __esm(() => {
48478
48526
  "council-member": "council-member"
48479
48527
  };
48480
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
+ };
48481
48539
  });
48482
48540
 
48483
48541
  // src/shared/session-utils.ts
@@ -48641,9 +48699,18 @@ var init_session_tools_store = __esm(() => {
48641
48699
  var init_prompt_tools = __esm(() => {
48642
48700
  init_session_tools_store();
48643
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
+
48644
48710
  // src/features/claude-code-plugin-loader/discovery.ts
48645
48711
  var init_discovery = __esm(() => {
48646
48712
  init_logger();
48713
+ init_scope_filter();
48647
48714
  });
48648
48715
 
48649
48716
  // src/features/claude-code-plugin-loader/command-loader.ts
@@ -48694,7 +48761,7 @@ var init_env_expander = __esm(() => {
48694
48761
  });
48695
48762
 
48696
48763
  // src/features/claude-code-mcp-loader/scope-filter.ts
48697
- var init_scope_filter = __esm(() => {
48764
+ var init_scope_filter2 = __esm(() => {
48698
48765
  init_contains_path();
48699
48766
  });
48700
48767
 
@@ -48705,7 +48772,7 @@ var init_transformer = __esm(() => {
48705
48772
  // src/features/claude-code-plugin-loader/mcp-server-loader.ts
48706
48773
  var init_mcp_server_loader = __esm(() => {
48707
48774
  init_env_expander();
48708
- init_scope_filter();
48775
+ init_scope_filter2();
48709
48776
  init_transformer();
48710
48777
  init_logger();
48711
48778
  });
@@ -48836,6 +48903,8 @@ var init_shared = __esm(() => {
48836
48903
  init_project_discovery_dirs();
48837
48904
  init_session_directory_resolver();
48838
48905
  init_prompt_tools();
48906
+ init_compaction_marker();
48907
+ init_internal_initiator_marker();
48839
48908
  init_plugin_command_discovery();
48840
48909
  init_log_legacy_plugin_startup_warning();
48841
48910
  });
@@ -48916,12 +48985,37 @@ var init_plugin_name_with_version = __esm(() => {
48916
48985
  PRIORITIZED_TAGS = ["latest", "beta", "next"];
48917
48986
  });
48918
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
+
48919
49013
  // src/cli/config-manager/ensure-config-directory-exists.ts
48920
- import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
49014
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
48921
49015
  function ensureConfigDirectoryExists() {
48922
49016
  const configDir = getConfigDir();
48923
- if (!existsSync7(configDir)) {
48924
- mkdirSync3(configDir, { recursive: true });
49017
+ if (!existsSync9(configDir)) {
49018
+ mkdirSync4(configDir, { recursive: true });
48925
49019
  }
48926
49020
  }
48927
49021
  var init_ensure_config_directory_exists = __esm(() => {
@@ -48958,14 +49052,14 @@ function formatErrorWithSuggestion(err, context) {
48958
49052
  }
48959
49053
 
48960
49054
  // src/cli/config-manager/opencode-config-format.ts
48961
- import { existsSync as existsSync8 } from "fs";
49055
+ import { existsSync as existsSync10 } from "fs";
48962
49056
  function detectConfigFormat() {
48963
49057
  const configJsonc = getConfigJsonc();
48964
49058
  const configJson = getConfigJson();
48965
- if (existsSync8(configJsonc)) {
49059
+ if (existsSync10(configJsonc)) {
48966
49060
  return { format: "jsonc", path: configJsonc };
48967
49061
  }
48968
- if (existsSync8(configJson)) {
49062
+ if (existsSync10(configJson)) {
48969
49063
  return { format: "json", path: configJson };
48970
49064
  }
48971
49065
  return { format: "none", path: configJson };
@@ -48975,7 +49069,7 @@ var init_opencode_config_format = __esm(() => {
48975
49069
  });
48976
49070
 
48977
49071
  // src/cli/config-manager/parse-opencode-config-file.ts
48978
- import { readFileSync as readFileSync4, statSync } from "fs";
49072
+ import { readFileSync as readFileSync5, statSync } from "fs";
48979
49073
  function isEmptyOrWhitespace(content) {
48980
49074
  return content.trim().length === 0;
48981
49075
  }
@@ -48985,7 +49079,7 @@ function parseOpenCodeConfigFileWithError(path3) {
48985
49079
  if (stat.size === 0) {
48986
49080
  return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
48987
49081
  }
48988
- const content = readFileSync4(path3, "utf-8");
49082
+ const content = readFileSync5(path3, "utf-8");
48989
49083
  if (isEmptyOrWhitespace(content)) {
48990
49084
  return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
48991
49085
  }
@@ -49008,8 +49102,90 @@ var init_parse_opencode_config_file = __esm(() => {
49008
49102
  init_shared();
49009
49103
  });
49010
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
+
49011
49187
  // src/cli/config-manager/add-plugin-to-opencode-config.ts
49012
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
49188
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
49013
49189
  async function addPluginToOpenCodeConfig(currentVersion) {
49014
49190
  try {
49015
49191
  ensureConfigDirectoryExists();
@@ -49042,19 +49218,35 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49042
49218
  const canonicalEntries = plugins.filter((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`));
49043
49219
  const legacyEntries = plugins.filter((plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`));
49044
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
+ }
49045
49241
  const normalizedPlugins = [...otherPlugins];
49046
- if (canonicalEntries.length > 0) {
49047
- normalizedPlugins.push(canonicalEntries[0]);
49048
- } else if (legacyEntries.length > 0) {
49049
- const versionMatch = legacyEntries[0].match(/@(.+)$/);
49050
- const preservedVersion = versionMatch ? versionMatch[1] : null;
49051
- normalizedPlugins.push(preservedVersion ? `${PLUGIN_NAME}@${preservedVersion}` : pluginEntry);
49242
+ if (canonicalEntries.length > 0 || legacyEntries.length > 0) {
49243
+ normalizedPlugins.push(pluginEntry);
49052
49244
  } else {
49053
49245
  normalizedPlugins.push(pluginEntry);
49054
49246
  }
49055
49247
  config.plugin = normalizedPlugins;
49056
49248
  if (format2 === "jsonc") {
49057
- const content = readFileSync5(path3, "utf-8");
49249
+ const content = readFileSync6(path3, "utf-8");
49058
49250
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
49059
49251
  const match = content.match(pluginArrayRegex);
49060
49252
  if (match) {
@@ -49084,6 +49276,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49084
49276
  }
49085
49277
  var init_add_plugin_to_opencode_config = __esm(() => {
49086
49278
  init_shared();
49279
+ init_backup_config();
49087
49280
  init_config_context();
49088
49281
  init_ensure_config_directory_exists();
49089
49282
  init_opencode_config_format();
@@ -49199,6 +49392,47 @@ var init_fallback_chain_resolution = __esm(() => {
49199
49392
  });
49200
49393
 
49201
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
+ }
49202
49436
  function generateModelConfig(config) {
49203
49437
  const avail = toProviderAvailability(config);
49204
49438
  const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai || avail.kimiForCoding || avail.opencodeGo;
@@ -49213,25 +49447,31 @@ function generateModelConfig(config) {
49213
49447
  const categories = {};
49214
49448
  for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
49215
49449
  if (role === "librarian") {
49450
+ let agentConfig;
49216
49451
  if (avail.opencodeGo) {
49217
- agents[role] = { model: "opencode-go/minimax-m2.7" };
49452
+ agentConfig = { model: "opencode-go/minimax-m2.7" };
49218
49453
  } else if (avail.zai) {
49219
- agents[role] = { model: ZAI_MODEL };
49454
+ agentConfig = { model: ZAI_MODEL };
49455
+ }
49456
+ if (agentConfig) {
49457
+ agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
49220
49458
  }
49221
49459
  continue;
49222
49460
  }
49223
49461
  if (role === "explore") {
49462
+ let agentConfig;
49224
49463
  if (avail.native.claude) {
49225
- agents[role] = { model: "anthropic/claude-haiku-4-5" };
49464
+ agentConfig = { model: "anthropic/claude-haiku-4-5" };
49226
49465
  } else if (avail.opencodeZen) {
49227
- agents[role] = { model: "opencode/claude-haiku-4-5" };
49466
+ agentConfig = { model: "opencode/claude-haiku-4-5" };
49228
49467
  } else if (avail.opencodeGo) {
49229
- agents[role] = { model: "opencode-go/minimax-m2.7" };
49468
+ agentConfig = { model: "opencode-go/minimax-m2.7" };
49230
49469
  } else if (avail.copilot) {
49231
- agents[role] = { model: "github-copilot/gpt-5-mini" };
49470
+ agentConfig = { model: "github-copilot/gpt-5-mini" };
49232
49471
  } else {
49233
- agents[role] = { model: "opencode/gpt-5-nano" };
49472
+ agentConfig = { model: "opencode/gpt-5-nano" };
49234
49473
  }
49474
+ agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
49235
49475
  continue;
49236
49476
  }
49237
49477
  if (role === "sisyphus") {
@@ -49242,7 +49482,8 @@ function generateModelConfig(config) {
49242
49482
  const resolved2 = resolveModelFromChain(fallbackChain, avail);
49243
49483
  if (resolved2) {
49244
49484
  const variant = resolved2.variant ?? req.variant;
49245
- 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);
49246
49487
  }
49247
49488
  continue;
49248
49489
  }
@@ -49255,7 +49496,8 @@ function generateModelConfig(config) {
49255
49496
  const resolved = resolveModelFromChain(req.fallbackChain, avail);
49256
49497
  if (resolved) {
49257
49498
  const variant = resolved.variant ?? req.variant;
49258
- 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);
49259
49501
  } else {
49260
49502
  agents[role] = { model: ULTIMATE_FALLBACK };
49261
49503
  }
@@ -49271,7 +49513,8 @@ function generateModelConfig(config) {
49271
49513
  const resolved = resolveModelFromChain(fallbackChain, avail);
49272
49514
  if (resolved) {
49273
49515
  const variant = resolved.variant ?? req.variant;
49274
- 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);
49275
49518
  } else {
49276
49519
  categories[cat] = { model: ULTIMATE_FALLBACK };
49277
49520
  }
@@ -49288,6 +49531,7 @@ var init_model_fallback = __esm(() => {
49288
49531
  init_model_fallback_requirements();
49289
49532
  init_openai_only_model_catalog();
49290
49533
  init_fallback_chain_resolution();
49534
+ init_provider_model_id_transform();
49291
49535
  });
49292
49536
 
49293
49537
  // src/cli/config-manager/generate-omo-config.ts
@@ -49316,7 +49560,7 @@ function deepMergeRecord(target, source) {
49316
49560
  }
49317
49561
 
49318
49562
  // src/cli/config-manager/write-omo-config.ts
49319
- import { existsSync as existsSync9, 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";
49320
49564
  function isEmptyOrWhitespace2(content) {
49321
49565
  return content.trim().length === 0;
49322
49566
  }
@@ -49333,10 +49577,18 @@ function writeOmoConfig(installConfig) {
49333
49577
  const omoConfigPath = getOmoConfigPath();
49334
49578
  try {
49335
49579
  const newConfig = generateOmoConfig(installConfig);
49336
- if (existsSync9(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
+ }
49337
49589
  try {
49338
49590
  const stat = statSync2(omoConfigPath);
49339
- const content = readFileSync6(omoConfigPath, "utf-8");
49591
+ const content = readFileSync7(omoConfigPath, "utf-8");
49340
49592
  if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
49341
49593
  writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49342
49594
  `);
@@ -49374,6 +49626,7 @@ function writeOmoConfig(installConfig) {
49374
49626
  }
49375
49627
  var init_write_omo_config = __esm(() => {
49376
49628
  init_shared();
49629
+ init_backup_config();
49377
49630
  init_config_context();
49378
49631
  init_ensure_config_directory_exists();
49379
49632
  init_generate_omo_config();
@@ -49476,10 +49729,10 @@ var init_opencode_binary = __esm(() => {
49476
49729
  });
49477
49730
 
49478
49731
  // src/cli/config-manager/detect-current-config.ts
49479
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
49732
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
49480
49733
  function detectProvidersFromOmoConfig() {
49481
49734
  const omoConfigPath = getOmoConfigPath();
49482
- if (!existsSync10(omoConfigPath)) {
49735
+ if (!existsSync12(omoConfigPath)) {
49483
49736
  return {
49484
49737
  hasOpenAI: true,
49485
49738
  hasOpencodeZen: true,
@@ -49489,7 +49742,7 @@ function detectProvidersFromOmoConfig() {
49489
49742
  };
49490
49743
  }
49491
49744
  try {
49492
- const content = readFileSync7(omoConfigPath, "utf-8");
49745
+ const content = readFileSync8(omoConfigPath, "utf-8");
49493
49746
  const omoConfig = parseJsonc(content);
49494
49747
  if (!omoConfig || typeof omoConfig !== "object") {
49495
49748
  return {
@@ -49520,9 +49773,13 @@ function detectProvidersFromOmoConfig() {
49520
49773
  function isOurPlugin(plugin) {
49521
49774
  return plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) || plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`);
49522
49775
  }
49776
+ function findOurPluginEntry(plugins) {
49777
+ return plugins.find(isOurPlugin) ?? null;
49778
+ }
49523
49779
  function detectCurrentConfig() {
49524
49780
  const result = {
49525
49781
  isInstalled: false,
49782
+ installedVersion: null,
49526
49783
  hasClaude: true,
49527
49784
  isMax20: true,
49528
49785
  hasOpenAI: true,
@@ -49543,7 +49800,11 @@ function detectCurrentConfig() {
49543
49800
  }
49544
49801
  const openCodeConfig = parseResult.config;
49545
49802
  const plugins = openCodeConfig.plugin ?? [];
49546
- result.isInstalled = plugins.some(isOurPlugin);
49803
+ const ourPluginEntry = findOurPluginEntry(plugins);
49804
+ result.isInstalled = !!ourPluginEntry;
49805
+ if (ourPluginEntry) {
49806
+ result.installedVersion = extractVersionFromPluginEntry(ourPluginEntry);
49807
+ }
49547
49808
  if (!result.isInstalled) {
49548
49809
  return result;
49549
49810
  }
@@ -49565,10 +49826,10 @@ var init_detect_current_config = __esm(() => {
49565
49826
  });
49566
49827
 
49567
49828
  // src/cli/config-manager/bun-install.ts
49568
- import { existsSync as existsSync11 } from "fs";
49569
- import { join as join10 } from "path";
49829
+ import { existsSync as existsSync13 } from "fs";
49830
+ import { join as join11 } from "path";
49570
49831
  function getDefaultWorkspaceDir() {
49571
- return join10(getOpenCodeCacheDir(), "packages");
49832
+ return join11(getOpenCodeCacheDir(), "packages");
49572
49833
  }
49573
49834
  function readProcessOutput(stream) {
49574
49835
  if (!stream) {
@@ -49594,7 +49855,7 @@ async function runBunInstallWithDetails(options) {
49594
49855
  const outputMode = options?.outputMode ?? "pipe";
49595
49856
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
49596
49857
  const packageJsonPath = `${cacheDir}/package.json`;
49597
- if (!existsSync11(packageJsonPath)) {
49858
+ if (!existsSync13(packageJsonPath)) {
49598
49859
  return {
49599
49860
  success: false,
49600
49861
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -49670,6 +49931,7 @@ var init_config_manager = __esm(() => {
49670
49931
  init_opencode_binary();
49671
49932
  init_detect_current_config();
49672
49933
  init_bun_install();
49934
+ init_backup_config();
49673
49935
  });
49674
49936
 
49675
49937
  // node_modules/sisteransi/src/index.js
@@ -49730,6 +49992,462 @@ var require_src = __commonJS((exports, module) => {
49730
49992
  module.exports = { cursor, scroll, erase, beep };
49731
49993
  });
49732
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
+
49733
50451
  // src/hooks/auto-update-checker/constants.ts
49734
50452
  import * as path4 from "path";
49735
50453
  import * as os3 from "os";
@@ -49747,15 +50465,15 @@ function getUserOpencodeConfig() {
49747
50465
  function getUserOpencodeConfigJsonc() {
49748
50466
  return path4.join(getUserConfigDir(), "opencode.jsonc");
49749
50467
  }
49750
- 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;
49751
50469
  var init_constants3 = __esm(() => {
49752
50470
  init_data_path();
49753
50471
  init_opencode_config_dir();
49754
- 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`;
49755
50473
  CACHE_ROOT_DIR = getOpenCodeCacheDir();
49756
50474
  CACHE_DIR = path4.join(CACHE_ROOT_DIR, "packages");
49757
50475
  VERSION_FILE = path4.join(CACHE_ROOT_DIR, "version");
49758
- 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");
49759
50477
  });
49760
50478
 
49761
50479
  // src/hooks/auto-update-checker/checker/config-paths.ts
@@ -49810,7 +50528,7 @@ function getLocalDevPath(directory) {
49810
50528
  const config2 = JSON.parse(stripJsonComments(content));
49811
50529
  const plugins = config2.plugin ?? [];
49812
50530
  for (const entry of plugins) {
49813
- if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
50531
+ if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME2)) {
49814
50532
  try {
49815
50533
  return fileURLToPath(entry);
49816
50534
  } catch {
@@ -49842,7 +50560,7 @@ function findPackageJsonUp(startPath) {
49842
50560
  try {
49843
50561
  const content = fs5.readFileSync(pkgPath, "utf-8");
49844
50562
  const pkg = JSON.parse(content);
49845
- if (pkg.name === PACKAGE_NAME)
50563
+ if (pkg.name === PACKAGE_NAME2)
49846
50564
  return pkgPath;
49847
50565
  } catch {}
49848
50566
  }
@@ -49891,13 +50609,15 @@ function findPluginEntry(directory) {
49891
50609
  const config2 = JSON.parse(stripJsonComments(content));
49892
50610
  const plugins = config2.plugin ?? [];
49893
50611
  for (const entry of plugins) {
49894
- if (entry === PACKAGE_NAME) {
49895
- return { entry, isPinned: false, pinnedVersion: null, configPath };
49896
- }
49897
- if (entry.startsWith(`${PACKAGE_NAME}@`)) {
49898
- const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
49899
- const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
49900
- 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
+ }
49901
50621
  }
49902
50622
  }
49903
50623
  } catch {
@@ -49906,11 +50626,12 @@ function findPluginEntry(directory) {
49906
50626
  }
49907
50627
  return null;
49908
50628
  }
49909
- var EXACT_SEMVER_REGEX;
50629
+ var EXACT_SEMVER_REGEX, MATCH_PLUGIN_NAMES;
49910
50630
  var init_plugin_entry = __esm(() => {
49911
50631
  init_constants3();
49912
50632
  init_config_paths();
49913
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];
49914
50635
  });
49915
50636
 
49916
50637
  // src/hooks/auto-update-checker/checker/cached-version.ts
@@ -50118,7 +50839,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50118
50839
  if (!fs9.existsSync(cachePackageJsonPath)) {
50119
50840
  log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
50120
50841
  return {
50121
- ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME]: intentVersion } }),
50842
+ ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME2]: intentVersion } }),
50122
50843
  message: `Created cache package.json with: ${intentVersion}`
50123
50844
  };
50124
50845
  }
@@ -50136,21 +50857,21 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50136
50857
  log("[auto-update-checker] Failed to parse cache package.json:", err);
50137
50858
  return { synced: false, error: "parse_error", message: "Failed to parse cache package.json (malformed JSON)" };
50138
50859
  }
50139
- if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME]) {
50860
+ if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME2]) {
50140
50861
  log("[auto-update-checker] Plugin missing from cache package.json dependencies, adding dependency", { intentVersion });
50141
50862
  const nextPkgJson = {
50142
50863
  ...pkgJson ?? {},
50143
50864
  dependencies: {
50144
50865
  ...pkgJson?.dependencies ?? {},
50145
- [PACKAGE_NAME]: intentVersion
50866
+ [PACKAGE_NAME2]: intentVersion
50146
50867
  }
50147
50868
  };
50148
50869
  return {
50149
50870
  ...writeCachePackageJson(cachePackageJsonPath, nextPkgJson),
50150
- message: `Added ${PACKAGE_NAME}: ${intentVersion}`
50871
+ message: `Added ${PACKAGE_NAME2}: ${intentVersion}`
50151
50872
  };
50152
50873
  }
50153
- const currentVersion = pkgJson.dependencies[PACKAGE_NAME];
50874
+ const currentVersion = pkgJson.dependencies[PACKAGE_NAME2];
50154
50875
  if (currentVersion === intentVersion) {
50155
50876
  log("[auto-update-checker] Cache package.json already matches intent:", intentVersion);
50156
50877
  return { synced: false, error: null, message: `Already matches intent: ${intentVersion}` };
@@ -50162,7 +50883,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50162
50883
  } else {
50163
50884
  log(`[auto-update-checker] Updating cache package.json: "${currentVersion}" \u2192 "${intentVersion}"`);
50164
50885
  }
50165
- pkgJson.dependencies[PACKAGE_NAME] = intentVersion;
50886
+ pkgJson.dependencies[PACKAGE_NAME2] = intentVersion;
50166
50887
  return {
50167
50888
  ...writeCachePackageJson(cachePackageJsonPath, pkgJson),
50168
50889
  message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"`
@@ -50228,7 +50949,7 @@ function removeFromBunLock(packageName) {
50228
50949
  }
50229
50950
  return false;
50230
50951
  }
50231
- function invalidatePackage(packageName = PACKAGE_NAME) {
50952
+ function invalidatePackage(packageName = PACKAGE_NAME2) {
50232
50953
  try {
50233
50954
  const userConfigDir = getUserConfigDir();
50234
50955
  const pkgDirs = [
@@ -50293,8 +51014,8 @@ var init_update_toasts = __esm(() => {
50293
51014
  });
50294
51015
 
50295
51016
  // src/hooks/auto-update-checker/hook/background-update-check.ts
50296
- import { existsSync as existsSync23 } from "fs";
50297
- import { join as join23 } from "path";
51017
+ import { existsSync as existsSync25 } from "fs";
51018
+ import { join as join24 } from "path";
50298
51019
  function getCacheWorkspaceDir(deps) {
50299
51020
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
50300
51021
  }
@@ -50304,8 +51025,8 @@ function getPinnedVersionToastMessage(latestVersion) {
50304
51025
  function resolveActiveInstallWorkspace(deps) {
50305
51026
  const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
50306
51027
  const cacheDir = getCacheWorkspaceDir(deps);
50307
- const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
50308
- 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");
50309
51030
  if (deps.existsSync(configInstallPath)) {
50310
51031
  deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50311
51032
  return configPaths.configDir;
@@ -50384,7 +51105,7 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50384
51105
  await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50385
51106
  return;
50386
51107
  }
50387
- deps.invalidatePackage(PACKAGE_NAME);
51108
+ deps.invalidatePackage(PACKAGE_NAME2);
50388
51109
  const activeWorkspace = resolveActiveInstallWorkspace(deps);
50389
51110
  const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
50390
51111
  if (installSuccess) {
@@ -50412,8 +51133,8 @@ var init_background_update_check = __esm(() => {
50412
51133
  init_checker();
50413
51134
  init_update_toasts();
50414
51135
  defaultDeps = {
50415
- existsSync: existsSync23,
50416
- join: join23,
51136
+ existsSync: existsSync25,
51137
+ join: join24,
50417
51138
  runBunInstallWithDetails,
50418
51139
  log,
50419
51140
  getOpenCodeCacheDir,
@@ -50693,7 +51414,7 @@ var {
50693
51414
  // package.json
50694
51415
  var package_default = {
50695
51416
  name: "oh-my-opencode",
50696
- version: "3.15.3",
51417
+ version: "3.16.0",
50697
51418
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
50698
51419
  main: "./dist/index.js",
50699
51420
  types: "dist/index.d.ts",
@@ -50752,8 +51473,8 @@ var package_default = {
50752
51473
  "@clack/prompts": "^0.11.0",
50753
51474
  "@code-yeongyu/comment-checker": "^0.7.0",
50754
51475
  "@modelcontextprotocol/sdk": "^1.25.2",
50755
- "@opencode-ai/plugin": "^1.2.24",
50756
- "@opencode-ai/sdk": "^1.2.24",
51476
+ "@opencode-ai/plugin": "^1.4.0",
51477
+ "@opencode-ai/sdk": "^1.4.0",
50757
51478
  commander: "^14.0.2",
50758
51479
  "detect-libc": "^2.0.0",
50759
51480
  diff: "^8.0.3",
@@ -50762,7 +51483,7 @@ var package_default = {
50762
51483
  picocolors: "^1.1.1",
50763
51484
  picomatch: "^4.0.2",
50764
51485
  "vscode-jsonrpc": "^8.2.0",
50765
- zod: "^4.1.8"
51486
+ zod: "^4.3.0"
50766
51487
  },
50767
51488
  devDependencies: {
50768
51489
  "@types/js-yaml": "^4.0.9",
@@ -50771,21 +51492,19 @@ var package_default = {
50771
51492
  typescript: "^5.7.3"
50772
51493
  },
50773
51494
  optionalDependencies: {
50774
- "oh-my-opencode-darwin-arm64": "3.15.3",
50775
- "oh-my-opencode-darwin-x64": "3.15.3",
50776
- "oh-my-opencode-darwin-x64-baseline": "3.15.3",
50777
- "oh-my-opencode-linux-arm64": "3.15.3",
50778
- "oh-my-opencode-linux-arm64-musl": "3.15.3",
50779
- "oh-my-opencode-linux-x64": "3.15.3",
50780
- "oh-my-opencode-linux-x64-baseline": "3.15.3",
50781
- "oh-my-opencode-linux-x64-musl": "3.15.3",
50782
- "oh-my-opencode-linux-x64-musl-baseline": "3.15.3",
50783
- "oh-my-opencode-windows-x64": "3.15.3",
50784
- "oh-my-opencode-windows-x64-baseline": "3.15.3"
50785
- },
50786
- overrides: {
50787
- "@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"
50788
51506
  },
51507
+ overrides: {},
50789
51508
  trustedDependencies: [
50790
51509
  "@ast-grep/cli",
50791
51510
  "@ast-grep/napi",
@@ -50796,7 +51515,7 @@ var package_default = {
50796
51515
  // src/cli/cli-installer.ts
50797
51516
  init_shared();
50798
51517
  init_config_manager();
50799
- var import_picocolors2 = __toESM(require_picocolors(), 1);
51518
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
50800
51519
 
50801
51520
  // src/cli/install-validators.ts
50802
51521
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -50943,6 +51662,56 @@ function detectedToInitialValues(detected) {
50943
51662
  };
50944
51663
  }
50945
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
+
50946
51715
  // src/cli/cli-installer.ts
50947
51716
  async function runCliInstaller(args, version) {
50948
51717
  const validation = validateNonTuiArgs(args);
@@ -50970,6 +51739,11 @@ async function runCliInstaller(args, version) {
50970
51739
  printInfo("Visit https://opencode.ai/docs for installation instructions");
50971
51740
  } else {
50972
51741
  printSuccess(`OpenCode ${openCodeVersion ?? ""} detected`);
51742
+ const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion);
51743
+ if (unsupportedVersionMessage) {
51744
+ printWarning(unsupportedVersionMessage);
51745
+ return 1;
51746
+ }
50973
51747
  }
50974
51748
  if (isUpdate) {
50975
51749
  const initial = detectedToInitialValues(detected);
@@ -50982,47 +51756,37 @@ async function runCliInstaller(args, version) {
50982
51756
  printError(`Failed: ${pluginResult.error}`);
50983
51757
  return 1;
50984
51758
  }
50985
- 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)}`);
50986
51760
  printStep(step++, totalSteps, `Writing ${PLUGIN_NAME} configuration...`);
50987
51761
  const omoResult = writeOmoConfig(config);
50988
51762
  if (!omoResult.success) {
50989
51763
  printError(`Failed: ${omoResult.error}`);
50990
51764
  return 1;
50991
51765
  }
50992
- printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors2.default.dim(omoResult.configPath)}`);
51766
+ printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors3.default.dim(omoResult.configPath)}`);
50993
51767
  printBox(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
50994
51768
  if (!config.hasClaude) {
50995
- console.log();
50996
- console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
50997
- console.log();
50998
- console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
50999
- console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
51000
- console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
51001
- console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
51002
- console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
51003
- console.log();
51004
- console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
51005
- console.log();
51769
+ printInfo("Note: Sisyphus agent performs best with Claude Opus 4.5+. " + "Other models work but may have reduced orchestration quality.");
51006
51770
  }
51007
51771
  if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
51008
51772
  printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
51009
51773
  }
51010
- console.log(`${SYMBOLS.star} ${import_picocolors2.default.bold(import_picocolors2.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
51011
- 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!`);
51012
51776
  console.log();
51013
- 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.
51014
51778
  ` + `All features work like magic-parallel agents, background tasks,
51015
51779
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51016
- console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
51017
- 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")}`);
51018
51782
  console.log();
51019
- console.log(import_picocolors2.default.dim("oMoMoMoMo... Enjoy!"));
51783
+ console.log(import_picocolors3.default.dim("oMoMoMoMo... Enjoy!"));
51020
51784
  console.log();
51021
51785
  if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
51022
- printBox(`Run ${import_picocolors2.default.cyan("opencode auth login")} and select your provider:
51023
- ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}
51024
- ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors2.default.gray("\u2192 Gemini")}
51025
- ` : "") + (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");
51026
51790
  }
51027
51791
  return 0;
51028
51792
  }
@@ -51417,7 +52181,7 @@ class LD extends x {
51417
52181
  }
51418
52182
 
51419
52183
  // node_modules/@clack/prompts/dist/index.mjs
51420
- var import_picocolors3 = __toESM(require_picocolors(), 1);
52184
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
51421
52185
  var import_sisteransi2 = __toESM(require_src(), 1);
51422
52186
  import y2 from "process";
51423
52187
  function ce() {
@@ -51450,13 +52214,13 @@ var b2 = (t) => {
51450
52214
  switch (t) {
51451
52215
  case "initial":
51452
52216
  case "active":
51453
- return import_picocolors3.default.cyan(le);
52217
+ return import_picocolors4.default.cyan(le);
51454
52218
  case "cancel":
51455
- return import_picocolors3.default.red(L2);
52219
+ return import_picocolors4.default.red(L2);
51456
52220
  case "error":
51457
- return import_picocolors3.default.yellow(W2);
52221
+ return import_picocolors4.default.yellow(W2);
51458
52222
  case "submit":
51459
- return import_picocolors3.default.green(C);
52223
+ return import_picocolors4.default.green(C);
51460
52224
  }
51461
52225
  };
51462
52226
  var G2 = (t) => {
@@ -51466,7 +52230,7 @@ var G2 = (t) => {
51466
52230
  const $2 = a < r2.length && l2 > 0, g2 = a < r2.length && l2 + a < r2.length;
51467
52231
  return r2.slice(l2, l2 + a).map((p2, v, f) => {
51468
52232
  const j2 = v === 0 && $2, E = v === f.length - 1 && g2;
51469
- 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);
51470
52234
  });
51471
52235
  };
51472
52236
  var ve = (t) => {
@@ -51474,29 +52238,29 @@ var ve = (t) => {
51474
52238
  const s = r2.label ?? String(r2.value);
51475
52239
  switch (i2) {
51476
52240
  case "selected":
51477
- return `${import_picocolors3.default.dim(s)}`;
52241
+ return `${import_picocolors4.default.dim(s)}`;
51478
52242
  case "active":
51479
- 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})`) : ""}`;
51480
52244
  case "cancelled":
51481
- return `${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(s))}`;
52245
+ return `${import_picocolors4.default.strikethrough(import_picocolors4.default.dim(s))}`;
51482
52246
  default:
51483
- return `${import_picocolors3.default.dim(P2)} ${import_picocolors3.default.dim(s)}`;
52247
+ return `${import_picocolors4.default.dim(P2)} ${import_picocolors4.default.dim(s)}`;
51484
52248
  }
51485
52249
  };
51486
52250
  return new LD({ options: t.options, initialValue: t.initialValue, render() {
51487
- const r2 = `${import_picocolors3.default.gray(o)}
52251
+ const r2 = `${import_picocolors4.default.gray(o)}
51488
52252
  ${b2(this.state)} ${t.message}
51489
52253
  `;
51490
52254
  switch (this.state) {
51491
52255
  case "submit":
51492
- 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")}`;
51493
52257
  case "cancel":
51494
- return `${r2}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
51495
- ${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)}`;
51496
52260
  default:
51497
- 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(`
51498
- ${import_picocolors3.default.cyan(o)} `)}
51499
- ${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)}
51500
52264
  `;
51501
52265
  }
51502
52266
  } }).prompt();
@@ -51508,53 +52272,53 @@ ${t}
51508
52272
  `), i2 = S2(n).length, s = Math.max(r2.reduce((a, l2) => {
51509
52273
  const $2 = S2(l2);
51510
52274
  return $2.length > a ? $2.length : a;
51511
- }, 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(`
51512
52276
  `);
51513
- process.stdout.write(`${import_picocolors3.default.gray(o)}
51514
- ${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)}
51515
52279
  ${c}
51516
- ${import_picocolors3.default.gray(de + _2.repeat(s + 2) + pe)}
52280
+ ${import_picocolors4.default.gray(de + _2.repeat(s + 2) + pe)}
51517
52281
  `);
51518
52282
  };
51519
52283
  var xe = (t = "") => {
51520
- 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)}
51521
52285
 
51522
52286
  `);
51523
52287
  };
51524
52288
  var Ie = (t = "") => {
51525
- process.stdout.write(`${import_picocolors3.default.gray(ue)} ${t}
52289
+ process.stdout.write(`${import_picocolors4.default.gray(ue)} ${t}
51526
52290
  `);
51527
52291
  };
51528
52292
  var Se = (t = "") => {
51529
- process.stdout.write(`${import_picocolors3.default.gray(o)}
51530
- ${import_picocolors3.default.gray(d2)} ${t}
52293
+ process.stdout.write(`${import_picocolors4.default.gray(o)}
52294
+ ${import_picocolors4.default.gray(d2)} ${t}
51531
52295
 
51532
52296
  `);
51533
52297
  };
51534
- var M2 = { message: (t = "", { symbol: n = import_picocolors3.default.gray(o) } = {}) => {
51535
- 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)}`];
51536
52300
  if (t) {
51537
52301
  const [i2, ...s] = t.split(`
51538
52302
  `);
51539
- 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}`));
51540
52304
  }
51541
52305
  process.stdout.write(`${r2.join(`
51542
52306
  `)}
51543
52307
  `);
51544
52308
  }, info: (t) => {
51545
- M2.message(t, { symbol: import_picocolors3.default.blue(q) });
52309
+ M2.message(t, { symbol: import_picocolors4.default.blue(q) });
51546
52310
  }, success: (t) => {
51547
- M2.message(t, { symbol: import_picocolors3.default.green(D) });
52311
+ M2.message(t, { symbol: import_picocolors4.default.green(D) });
51548
52312
  }, step: (t) => {
51549
- M2.message(t, { symbol: import_picocolors3.default.green(C) });
52313
+ M2.message(t, { symbol: import_picocolors4.default.green(C) });
51550
52314
  }, warn: (t) => {
51551
- M2.message(t, { symbol: import_picocolors3.default.yellow(U) });
52315
+ M2.message(t, { symbol: import_picocolors4.default.yellow(U) });
51552
52316
  }, warning: (t) => {
51553
52317
  M2.warn(t);
51554
52318
  }, error: (t) => {
51555
- M2.message(t, { symbol: import_picocolors3.default.red(K2) });
52319
+ M2.message(t, { symbol: import_picocolors4.default.red(K2) });
51556
52320
  } };
51557
- var J2 = `${import_picocolors3.default.gray(o)} `;
52321
+ var J2 = `${import_picocolors4.default.gray(o)} `;
51558
52322
  var Y2 = ({ indicator: t = "dots" } = {}) => {
51559
52323
  const n = V2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], r2 = V2 ? 80 : 120, i2 = process.env.CI === "true";
51560
52324
  let s, c, a = false, l2 = "", $2, g2 = performance.now();
@@ -51577,14 +52341,14 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51577
52341
  const h2 = (performance.now() - m2) / 1000, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
51578
52342
  return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
51579
52343
  }, H = (m2 = "") => {
51580
- 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)}
51581
52345
  `);
51582
52346
  let h2 = 0, w2 = 0;
51583
52347
  j2(), c = setInterval(() => {
51584
52348
  if (i2 && l2 === $2)
51585
52349
  return;
51586
52350
  B2(), $2 = l2;
51587
- const I2 = import_picocolors3.default.magenta(n[h2]);
52351
+ const I2 = import_picocolors4.default.magenta(n[h2]);
51588
52352
  if (i2)
51589
52353
  process.stdout.write(`${I2} ${l2}...`);
51590
52354
  else if (t === "timer")
@@ -51597,7 +52361,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51597
52361
  }, r2);
51598
52362
  }, N2 = (m2 = "", h2 = 0) => {
51599
52363
  a = false, clearInterval(c), B2();
51600
- 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);
51601
52365
  l2 = R2(m2 ?? l2), t === "timer" ? process.stdout.write(`${w2} ${l2} ${O2(g2)}
51602
52366
  `) : process.stdout.write(`${w2} ${l2}
51603
52367
  `), E(), s();
@@ -51610,7 +52374,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51610
52374
  // src/cli/tui-installer.ts
51611
52375
  init_shared();
51612
52376
  init_config_manager();
51613
- var import_picocolors4 = __toESM(require_picocolors(), 1);
52377
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
51614
52378
 
51615
52379
  // src/cli/tui-install-prompts.ts
51616
52380
  async function selectOrCancel(params) {
@@ -51731,7 +52495,7 @@ async function runTuiInstaller(args, version) {
51731
52495
  }
51732
52496
  const detected = detectCurrentConfig();
51733
52497
  const isUpdate = detected.isInstalled;
51734
- 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... ")));
51735
52499
  if (isUpdate) {
51736
52500
  const initial = detectedToInitialValues(detected);
51737
52501
  M2.info(`Existing configuration detected: Claude=${initial.claude}, Gemini=${initial.gemini}`);
@@ -51741,11 +52505,17 @@ async function runTuiInstaller(args, version) {
51741
52505
  const installed = await isOpenCodeInstalled();
51742
52506
  const openCodeVersion = await getOpenCodeVersion2();
51743
52507
  if (!installed) {
51744
- spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
52508
+ spinner.stop(`OpenCode binary not found ${import_picocolors5.default.yellow("[!]")}`);
51745
52509
  M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
51746
52510
  Me("Visit https://opencode.ai/docs for installation instructions", "Installation Guide");
51747
52511
  } else {
51748
- 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
+ }
51749
52519
  }
51750
52520
  const config = await promptInstallConfig(detected);
51751
52521
  if (!config)
@@ -51754,55 +52524,46 @@ async function runTuiInstaller(args, version) {
51754
52524
  const pluginResult = await addPluginToOpenCodeConfig(version);
51755
52525
  if (!pluginResult.success) {
51756
52526
  spinner.stop(`Failed to add plugin: ${pluginResult.error}`);
51757
- Se(import_picocolors4.default.red("Installation failed."));
52527
+ Se(import_picocolors5.default.red("Installation failed."));
51758
52528
  return 1;
51759
52529
  }
51760
- spinner.stop(`Plugin added to ${import_picocolors4.default.cyan(pluginResult.configPath)}`);
52530
+ spinner.stop(`Plugin added to ${import_picocolors5.default.cyan(pluginResult.configPath)}`);
51761
52531
  spinner.start(`Writing ${PLUGIN_NAME} configuration`);
51762
52532
  const omoResult = writeOmoConfig(config);
51763
52533
  if (!omoResult.success) {
51764
52534
  spinner.stop(`Failed to write config: ${omoResult.error}`);
51765
- Se(import_picocolors4.default.red("Installation failed."));
52535
+ Se(import_picocolors5.default.red("Installation failed."));
51766
52536
  return 1;
51767
52537
  }
51768
- spinner.stop(`Config written to ${import_picocolors4.default.cyan(omoResult.configPath)}`);
52538
+ spinner.stop(`Config written to ${import_picocolors5.default.cyan(omoResult.configPath)}`);
51769
52539
  if (!config.hasClaude) {
51770
- console.log();
51771
- console.log(import_picocolors4.default.bgRed(import_picocolors4.default.white(import_picocolors4.default.bold(" CRITICAL WARNING "))));
51772
- console.log();
51773
- console.log(import_picocolors4.default.red(import_picocolors4.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
51774
- console.log(import_picocolors4.default.red(" Without Claude, you may experience significantly degraded performance:"));
51775
- console.log(import_picocolors4.default.dim(" \u2022 Reduced orchestration quality"));
51776
- console.log(import_picocolors4.default.dim(" \u2022 Weaker tool selection and delegation"));
51777
- console.log(import_picocolors4.default.dim(" \u2022 Less reliable task completion"));
51778
- console.log();
51779
- console.log(import_picocolors4.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
51780
- 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.`);
51781
52542
  }
51782
52543
  if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
51783
52544
  M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
51784
52545
  }
51785
52546
  Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
51786
- M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51787
- M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
51788
- 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.
51789
52550
  ` + `All features work like magic-parallel agents, background tasks,
51790
52551
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51791
- M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51792
- M2.message(` ${import_picocolors4.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
51793
- 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!"));
51794
52555
  if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
51795
52556
  const providers = [];
51796
52557
  if (config.hasClaude)
51797
- providers.push(`Anthropic ${import_picocolors4.default.gray("\u2192 Claude Pro/Max")}`);
52558
+ providers.push(`Anthropic ${import_picocolors5.default.gray("\u2192 Claude Pro/Max")}`);
51798
52559
  if (config.hasGemini)
51799
- providers.push(`Google ${import_picocolors4.default.gray("\u2192 Gemini")}`);
52560
+ providers.push(`Google ${import_picocolors5.default.gray("\u2192 Gemini")}`);
51800
52561
  if (config.hasCopilot)
51801
- providers.push(`GitHub ${import_picocolors4.default.gray("\u2192 Copilot")}`);
52562
+ providers.push(`GitHub ${import_picocolors5.default.gray("\u2192 Copilot")}`);
51802
52563
  console.log();
51803
- console.log(import_picocolors4.default.bold("Authenticate Your Providers"));
52564
+ console.log(import_picocolors5.default.bold("Authenticate Your Providers"));
51804
52565
  console.log();
51805
- 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:`);
51806
52567
  for (const provider of providers) {
51807
52568
  console.log(` ${SYMBOLS.bullet} ${provider}`);
51808
52569
  }
@@ -51818,7 +52579,7 @@ async function install(args) {
51818
52579
  }
51819
52580
 
51820
52581
  // src/cli/run/runner.ts
51821
- var import_picocolors14 = __toESM(require_picocolors(), 1);
52582
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
51822
52583
 
51823
52584
  // src/cli/run/event-state.ts
51824
52585
  function createEventState() {
@@ -51852,7 +52613,7 @@ function createEventState() {
51852
52613
  };
51853
52614
  }
51854
52615
  // src/cli/run/event-formatting.ts
51855
- var import_picocolors5 = __toESM(require_picocolors(), 1);
52616
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
51856
52617
  function serializeError(error) {
51857
52618
  if (!error)
51858
52619
  return "Unknown error";
@@ -51896,10 +52657,10 @@ function getSessionTag(ctx, payload) {
51896
52657
  const sessionID = props?.sessionID ?? props?.sessionId ?? info?.sessionID ?? info?.sessionId ?? part?.sessionID ?? part?.sessionId;
51897
52658
  const isMainSession = sessionID === ctx.sessionID;
51898
52659
  if (isMainSession)
51899
- return import_picocolors5.default.green("[MAIN]");
52660
+ return import_picocolors6.default.green("[MAIN]");
51900
52661
  if (sessionID)
51901
- return import_picocolors5.default.yellow(`[${String(sessionID).slice(0, 8)}]`);
51902
- return import_picocolors5.default.dim("[system]");
52662
+ return import_picocolors6.default.yellow(`[${String(sessionID).slice(0, 8)}]`);
52663
+ return import_picocolors6.default.dim("[system]");
51903
52664
  }
51904
52665
  function logEventVerbose(ctx, payload) {
51905
52666
  const sessionTag = getSessionTag(ctx, payload);
@@ -51908,7 +52669,7 @@ function logEventVerbose(ctx, payload) {
51908
52669
  case "session.idle":
51909
52670
  case "session.status": {
51910
52671
  const status = props?.status?.type ?? "idle";
51911
- console.error(import_picocolors5.default.dim(`${sessionTag} ${payload.type}: ${status}`));
52672
+ console.error(import_picocolors6.default.dim(`${sessionTag} ${payload.type}: ${status}`));
51912
52673
  break;
51913
52674
  }
51914
52675
  case "message.part.updated": {
@@ -51916,10 +52677,10 @@ function logEventVerbose(ctx, payload) {
51916
52677
  const part = partProps?.part;
51917
52678
  if (part?.type === "tool") {
51918
52679
  const status = part.state?.status ?? "unknown";
51919
- 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}]`));
51920
52681
  } else if (part?.type === "text" && part.text) {
51921
52682
  const preview = part.text.slice(0, 80).replace(/\n/g, "\\n");
51922
- 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 ? "..." : ""}"`));
51923
52684
  }
51924
52685
  break;
51925
52686
  }
@@ -51928,7 +52689,7 @@ function logEventVerbose(ctx, payload) {
51928
52689
  const field = deltaProps?.field ?? "unknown";
51929
52690
  const delta = deltaProps?.delta ?? "";
51930
52691
  const preview = delta.slice(0, 80).replace(/\n/g, "\\n");
51931
- 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 ? "..." : ""}"`));
51932
52693
  break;
51933
52694
  }
51934
52695
  case "message.updated": {
@@ -51937,7 +52698,7 @@ function logEventVerbose(ctx, payload) {
51937
52698
  const model = msgProps?.info?.modelID;
51938
52699
  const agent = msgProps?.info?.agent;
51939
52700
  const details = [role, agent, model].filter(Boolean).join(", ");
51940
- console.error(import_picocolors5.default.dim(`${sessionTag} message.updated (${details})`));
52701
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.updated (${details})`));
51941
52702
  break;
51942
52703
  }
51943
52704
  case "tool.execute": {
@@ -51955,32 +52716,32 @@ function logEventVerbose(ctx, payload) {
51955
52716
  }
51956
52717
  }
51957
52718
  const inputPreview = inputStr.slice(0, 150);
51958
- console.error(import_picocolors5.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors5.default.bold(toolName)}`));
51959
- 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 ? "..." : ""}`));
51960
52721
  break;
51961
52722
  }
51962
52723
  case "tool.result": {
51963
52724
  const resultProps = props;
51964
52725
  const output = resultProps?.output ?? "";
51965
52726
  const preview = output.slice(0, 200).replace(/\n/g, "\\n");
51966
- 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 ? "..." : ""}"`));
51967
52728
  break;
51968
52729
  }
51969
52730
  case "session.error": {
51970
52731
  const errorProps = props;
51971
52732
  const errorMsg = serializeError(errorProps?.error);
51972
- console.error(import_picocolors5.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
52733
+ console.error(import_picocolors6.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
51973
52734
  break;
51974
52735
  }
51975
52736
  default:
51976
- console.error(import_picocolors5.default.dim(`${sessionTag} ${payload.type}`));
52737
+ console.error(import_picocolors6.default.dim(`${sessionTag} ${payload.type}`));
51977
52738
  }
51978
52739
  }
51979
52740
  // src/cli/run/event-stream-processor.ts
51980
- var import_picocolors8 = __toESM(require_picocolors(), 1);
52741
+ var import_picocolors9 = __toESM(require_picocolors(), 1);
51981
52742
 
51982
52743
  // src/cli/run/event-handlers.ts
51983
- var import_picocolors7 = __toESM(require_picocolors(), 1);
52744
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
51984
52745
 
51985
52746
  // src/cli/run/tool-input-preview.ts
51986
52747
  function formatToolHeader(toolName, input) {
@@ -52116,14 +52877,14 @@ var displayChars = {
52116
52877
  };
52117
52878
 
52118
52879
  // src/cli/run/output-renderer.ts
52119
- var import_picocolors6 = __toESM(require_picocolors(), 1);
52880
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
52120
52881
  function renderAgentHeader(agent, model, variant, agentColorsByName) {
52121
52882
  if (!agent && !model)
52122
52883
  return;
52123
- const agentLabel = agent ? import_picocolors6.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
52884
+ const agentLabel = agent ? import_picocolors7.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
52124
52885
  const modelBase = model ?? "";
52125
52886
  const variantSuffix = variant ? ` (${variant})` : "";
52126
- const modelLabel = model ? import_picocolors6.default.dim(`${modelBase}${variantSuffix}`) : "";
52887
+ const modelLabel = model ? import_picocolors7.default.dim(`${modelBase}${variantSuffix}`) : "";
52127
52888
  process.stdout.write(`
52128
52889
  `);
52129
52890
  if (modelLabel) {
@@ -52131,7 +52892,7 @@ function renderAgentHeader(agent, model, variant, agentColorsByName) {
52131
52892
  `);
52132
52893
  }
52133
52894
  if (agentLabel) {
52134
- process.stdout.write(` ${import_picocolors6.default.dim("\u2514\u2500")} ${agentLabel}
52895
+ process.stdout.write(` ${import_picocolors7.default.dim("\u2514\u2500")} ${agentLabel}
52135
52896
  `);
52136
52897
  }
52137
52898
  process.stdout.write(`
@@ -52139,7 +52900,7 @@ function renderAgentHeader(agent, model, variant, agentColorsByName) {
52139
52900
  }
52140
52901
  function openThinkBlock() {
52141
52902
  process.stdout.write(`
52142
- ${import_picocolors6.default.dim("\u2503 Thinking:")} `);
52903
+ ${import_picocolors7.default.dim("\u2503 Thinking:")} `);
52143
52904
  }
52144
52905
  function closeThinkBlock() {
52145
52906
  process.stdout.write(`
@@ -52173,10 +52934,10 @@ function writePaddedText(text, atLineStart) {
52173
52934
  }
52174
52935
  function colorizeWithProfileColor(text, hexColor) {
52175
52936
  if (!hexColor)
52176
- return import_picocolors6.default.magenta(text);
52937
+ return import_picocolors7.default.magenta(text);
52177
52938
  const rgb = parseHexColor(hexColor);
52178
52939
  if (!rgb)
52179
- return import_picocolors6.default.magenta(text);
52940
+ return import_picocolors7.default.magenta(text);
52180
52941
  const [r2, g2, b3] = rgb;
52181
52942
  return `\x1B[38;2;${r2};${g2};${b3}m${text}\x1B[39m`;
52182
52943
  }
@@ -52216,7 +52977,7 @@ function renderCompletionMetaLine(state, messageID) {
52216
52977
  const agent = state.currentAgent ?? "assistant";
52217
52978
  const model = state.currentModel ?? "unknown-model";
52218
52979
  const variant = state.currentVariant ? ` (${state.currentVariant})` : "";
52219
- process.stdout.write(import_picocolors7.default.dim(`
52980
+ process.stdout.write(import_picocolors8.default.dim(`
52220
52981
  ${displayChars.treeEnd} ${agent} \xB7 ${model}${variant} \xB7 ${elapsedSec}s
52221
52982
  `));
52222
52983
  state.completionMetaPrintedByMessageId[messageID] = true;
@@ -52250,7 +53011,7 @@ function handleSessionError(ctx, payload, state) {
52250
53011
  if (getSessionId(props) === ctx.sessionID) {
52251
53012
  state.mainSessionError = true;
52252
53013
  state.lastError = serializeError(props?.error);
52253
- console.error(import_picocolors7.default.red(`
53014
+ console.error(import_picocolors8.default.red(`
52254
53015
  [session.error] ${state.lastError}`));
52255
53016
  }
52256
53017
  }
@@ -52278,7 +53039,7 @@ function handleMessagePartUpdated(ctx, payload, state) {
52278
53039
  const newText = reasoningText.slice(state.lastReasoningText.length);
52279
53040
  if (newText) {
52280
53041
  const padded = writePaddedText(newText, state.thinkingAtLineStart);
52281
- process.stdout.write(import_picocolors7.default.dim(padded.output));
53042
+ process.stdout.write(import_picocolors8.default.dim(padded.output));
52282
53043
  state.thinkingAtLineStart = padded.atLineStart;
52283
53044
  state.hasReceivedMeaningfulWork = true;
52284
53045
  }
@@ -52325,7 +53086,7 @@ function handleMessagePartDelta(ctx, payload, state) {
52325
53086
  if (partType === "reasoning") {
52326
53087
  ensureThinkBlockOpen(state);
52327
53088
  const padded2 = writePaddedText(delta, state.thinkingAtLineStart);
52328
- process.stdout.write(import_picocolors7.default.dim(padded2.output));
53089
+ process.stdout.write(import_picocolors8.default.dim(padded2.output));
52329
53090
  state.thinkingAtLineStart = padded2.atLineStart;
52330
53091
  state.lastReasoningText += delta;
52331
53092
  state.hasReceivedMeaningfulWork = true;
@@ -52346,10 +53107,10 @@ function handleToolPart(_ctx, part, state) {
52346
53107
  return;
52347
53108
  state.currentTool = toolName;
52348
53109
  const header = formatToolHeader(toolName, part.state?.input ?? {});
52349
- const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
53110
+ const suffix = header.description ? ` ${import_picocolors8.default.dim(header.description)}` : "";
52350
53111
  state.hasReceivedMeaningfulWork = true;
52351
53112
  process.stdout.write(`
52352
- ${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}
52353
53114
  `);
52354
53115
  }
52355
53116
  if (status === "completed" || status === "error") {
@@ -52357,10 +53118,10 @@ function handleToolPart(_ctx, part, state) {
52357
53118
  return;
52358
53119
  const output = part.state?.output || "";
52359
53120
  if (output.trim()) {
52360
- process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
53121
+ process.stdout.write(import_picocolors8.default.dim(` ${displayChars.treeEnd} output
52361
53122
  `));
52362
53123
  const padded = writePaddedText(output, true);
52363
- process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
53124
+ process.stdout.write(import_picocolors8.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52364
53125
  process.stdout.write(`
52365
53126
  `);
52366
53127
  }
@@ -52422,10 +53183,10 @@ function handleToolExecute(ctx, payload, state) {
52422
53183
  const toolName = props?.name || "unknown";
52423
53184
  state.currentTool = toolName;
52424
53185
  const header = formatToolHeader(toolName, props?.input ?? {});
52425
- const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
53186
+ const suffix = header.description ? ` ${import_picocolors8.default.dim(header.description)}` : "";
52426
53187
  state.hasReceivedMeaningfulWork = true;
52427
53188
  process.stdout.write(`
52428
- ${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}
52429
53190
  `);
52430
53191
  }
52431
53192
  function handleToolResult(ctx, payload, state) {
@@ -52439,10 +53200,10 @@ function handleToolResult(ctx, payload, state) {
52439
53200
  return;
52440
53201
  const output = props?.output || "";
52441
53202
  if (output.trim()) {
52442
- process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
53203
+ process.stdout.write(import_picocolors8.default.dim(` ${displayChars.treeEnd} output
52443
53204
  `));
52444
53205
  const padded = writePaddedText(output, true);
52445
- process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
53206
+ process.stdout.write(import_picocolors8.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52446
53207
  process.stdout.write(`
52447
53208
  `);
52448
53209
  }
@@ -52491,7 +53252,7 @@ async function processEvents(ctx, stream, state) {
52491
53252
  const payload = event;
52492
53253
  if (!payload?.type) {
52493
53254
  if (ctx.verbose) {
52494
- 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)}`));
52495
53256
  }
52496
53257
  continue;
52497
53258
  }
@@ -52509,7 +53270,7 @@ async function processEvents(ctx, stream, state) {
52509
53270
  handleToolResult(ctx, payload, state);
52510
53271
  handleTuiToast(ctx, payload, state);
52511
53272
  } catch (err) {
52512
- console.error(import_picocolors8.default.red(`[event error] ${err}`));
53273
+ console.error(import_picocolors9.default.red(`[event error] ${err}`));
52513
53274
  }
52514
53275
  }
52515
53276
  }
@@ -66584,12 +67345,12 @@ init_shared();
66584
67345
  // src/shared/migrate-legacy-config-file.ts
66585
67346
  init_logger();
66586
67347
  init_write_file_atomically();
66587
- import { existsSync as existsSync12, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
66588
- import { join as join11, 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";
66589
67350
  function buildCanonicalPath(legacyPath) {
66590
- const dir = dirname(legacyPath);
67351
+ const dir = dirname2(legacyPath);
66591
67352
  const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
66592
- return join11(dir, `${CONFIG_BASENAME}${ext}`);
67353
+ return join12(dir, `${CONFIG_BASENAME}${ext}`);
66593
67354
  }
66594
67355
  function archiveLegacyConfigFile(legacyPath) {
66595
67356
  const backupPath = `${legacyPath}.bak`;
@@ -66621,15 +67382,15 @@ function archiveLegacyConfigFile(legacyPath) {
66621
67382
  }
66622
67383
  }
66623
67384
  function migrateLegacyConfigFile(legacyPath) {
66624
- if (!existsSync12(legacyPath))
67385
+ if (!existsSync14(legacyPath))
66625
67386
  return false;
66626
67387
  if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
66627
67388
  return false;
66628
67389
  const canonicalPath = buildCanonicalPath(legacyPath);
66629
- if (existsSync12(canonicalPath))
67390
+ if (existsSync14(canonicalPath))
66630
67391
  return false;
66631
67392
  try {
66632
- const content = readFileSync8(legacyPath, "utf-8");
67393
+ const content = readFileSync9(legacyPath, "utf-8");
66633
67394
  writeFileAtomically(canonicalPath, content);
66634
67395
  const archivedLegacyConfig = archiveLegacyConfigFile(legacyPath);
66635
67396
  log("[migrateLegacyConfigFile] Migrated legacy config to canonical path", {
@@ -68160,6 +68921,31 @@ class OpencodeClient extends _HeyApiClient {
68160
68921
  }
68161
68922
 
68162
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
+ }
68163
68949
  function createOpencodeClient(config2) {
68164
68950
  if (!config2?.fetch) {
68165
68951
  const customFetch = (req) => {
@@ -68178,10 +68964,46 @@ function createOpencodeClient(config2) {
68178
68964
  };
68179
68965
  }
68180
68966
  const client2 = createClient(config2);
68967
+ client2.interceptors.request.use((request) => rewrite(request, config2?.directory));
68181
68968
  return new OpencodeClient({ client: client2 });
68182
68969
  }
68183
68970
  // node_modules/@opencode-ai/sdk/dist/server.js
68184
- 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
68185
69007
  async function createOpencodeServer(options) {
68186
69008
  options = Object.assign({
68187
69009
  hostname: "127.0.0.1",
@@ -68191,19 +69013,24 @@ async function createOpencodeServer(options) {
68191
69013
  const args = [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`];
68192
69014
  if (options.config?.logLevel)
68193
69015
  args.push(`--log-level=${options.config.logLevel}`);
68194
- const proc = spawn(`opencode`, args, {
68195
- signal: options.signal,
69016
+ const proc = import_cross_spawn.default(`opencode`, args, {
68196
69017
  env: {
68197
69018
  ...process.env,
68198
69019
  OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {})
68199
69020
  }
68200
69021
  });
69022
+ let clear = () => {};
68201
69023
  const url2 = await new Promise((resolve2, reject) => {
68202
69024
  const id = setTimeout(() => {
69025
+ clear();
69026
+ stop(proc);
68203
69027
  reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`));
68204
69028
  }, options.timeout);
68205
69029
  let output = "";
69030
+ let resolved = false;
68206
69031
  proc.stdout?.on("data", (chunk) => {
69032
+ if (resolved)
69033
+ return;
68207
69034
  output += chunk.toString();
68208
69035
  const lines = output.split(`
68209
69036
  `);
@@ -68211,9 +69038,14 @@ async function createOpencodeServer(options) {
68211
69038
  if (line.startsWith("opencode server listening")) {
68212
69039
  const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
68213
69040
  if (!match) {
68214
- 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;
68215
69046
  }
68216
69047
  clearTimeout(id);
69048
+ resolved = true;
68217
69049
  resolve2(match[1]);
68218
69050
  return;
68219
69051
  }
@@ -68235,17 +69067,16 @@ Server output: ${output}`;
68235
69067
  clearTimeout(id);
68236
69068
  reject(error48);
68237
69069
  });
68238
- if (options.signal) {
68239
- options.signal.addEventListener("abort", () => {
68240
- clearTimeout(id);
68241
- reject(new Error("Aborted"));
68242
- });
68243
- }
69070
+ clear = bindAbort(proc, options.signal, () => {
69071
+ clearTimeout(id);
69072
+ reject(options.signal?.reason);
69073
+ });
68244
69074
  });
68245
69075
  return {
68246
69076
  url: url2,
68247
69077
  close() {
68248
- proc.kill();
69078
+ clear();
69079
+ stop(proc);
68249
69080
  }
68250
69081
  };
68251
69082
  }
@@ -68265,11 +69096,11 @@ async function createOpencode(options) {
68265
69096
 
68266
69097
  // src/cli/run/server-connection.ts
68267
69098
  init_port_utils();
68268
- var import_picocolors9 = __toESM(require_picocolors(), 1);
69099
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
68269
69100
 
68270
69101
  // src/cli/run/opencode-binary-resolver.ts
68271
69102
  init_spawn_with_windows_hide();
68272
- import { delimiter, dirname as dirname3, join as join13 } from "path";
69103
+ import { delimiter, dirname as dirname4, join as join14 } from "path";
68273
69104
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
68274
69105
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
68275
69106
  function getCommandCandidates(platform) {
@@ -68292,7 +69123,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
68292
69123
  }
68293
69124
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
68294
69125
  for (const command of commandCandidates) {
68295
- addCandidate(join13(entry, command));
69126
+ addCandidate(join14(entry, command));
68296
69127
  }
68297
69128
  }
68298
69129
  return candidates;
@@ -68319,7 +69150,7 @@ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = can
68319
69150
  return null;
68320
69151
  }
68321
69152
  function buildPathWithBinaryFirst(pathEnv, binaryPath) {
68322
- const preferredDir = dirname3(binaryPath);
69153
+ const preferredDir = dirname4(binaryPath);
68323
69154
  const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
68324
69155
  return [preferredDir, ...existing].join(delimiter);
68325
69156
  }
@@ -68353,13 +69184,13 @@ function isPortRangeExhausted(error48) {
68353
69184
  async function startServer(options) {
68354
69185
  const { signal, port } = options;
68355
69186
  const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
68356
- 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));
68357
69188
  return { client: client3, cleanup: () => server2.close() };
68358
69189
  }
68359
69190
  async function createServerConnection(options) {
68360
69191
  const { port, attach, signal } = options;
68361
69192
  if (attach !== undefined) {
68362
- 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));
68363
69194
  const client3 = createOpencodeClient({ baseUrl: attach });
68364
69195
  return { client: client3, cleanup: () => {} };
68365
69196
  }
@@ -68369,7 +69200,7 @@ async function createServerConnection(options) {
68369
69200
  }
68370
69201
  const available = await isPortAvailable(port, "127.0.0.1");
68371
69202
  if (available) {
68372
- 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()));
68373
69204
  try {
68374
69205
  return await startServer({ signal, port });
68375
69206
  } catch (error48) {
@@ -68380,12 +69211,12 @@ async function createServerConnection(options) {
68380
69211
  if (stillAvailable) {
68381
69212
  throw error48;
68382
69213
  }
68383
- 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"));
68384
69215
  const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
68385
69216
  return { client: client4, cleanup: () => {} };
68386
69217
  }
68387
69218
  }
68388
- 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"));
68389
69220
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
68390
69221
  return { client: client3, cleanup: () => {} };
68391
69222
  }
@@ -68403,14 +69234,14 @@ async function createServerConnection(options) {
68403
69234
  if (defaultPortIsAvailable) {
68404
69235
  throw error48;
68405
69236
  }
68406
- 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()));
68407
69238
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${DEFAULT_SERVER_PORT}` });
68408
69239
  return { client: client3, cleanup: () => {} };
68409
69240
  }
68410
69241
  if (wasAutoSelected) {
68411
- 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()));
68412
69243
  } else {
68413
- 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()));
68414
69245
  }
68415
69246
  try {
68416
69247
  return await startServer({ signal, port: selectedPort });
@@ -68419,13 +69250,13 @@ async function createServerConnection(options) {
68419
69250
  throw error48;
68420
69251
  }
68421
69252
  const { port: retryPort } = await getAvailableServerPort(selectedPort + 1, "127.0.0.1");
68422
- 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()));
68423
69254
  return await startServer({ signal, port: retryPort });
68424
69255
  }
68425
69256
  }
68426
69257
 
68427
69258
  // src/cli/run/session-resolver.ts
68428
- var import_picocolors10 = __toESM(require_picocolors(), 1);
69259
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
68429
69260
  var SESSION_CREATE_MAX_RETRIES = 3;
68430
69261
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
68431
69262
  async function resolveSession(options) {
@@ -68451,11 +69282,11 @@ async function resolveSession(options) {
68451
69282
  query: { directory }
68452
69283
  });
68453
69284
  if (res.error) {
68454
- console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
68455
- 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)}`));
68456
69287
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
68457
69288
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
68458
- console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
69289
+ console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
68459
69290
  await new Promise((resolve2) => setTimeout(resolve2, delay));
68460
69291
  }
68461
69292
  continue;
@@ -68463,10 +69294,10 @@ async function resolveSession(options) {
68463
69294
  if (res.data?.id) {
68464
69295
  return res.data.id;
68465
69296
  }
68466
- 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`));
68467
69298
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
68468
69299
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
68469
- console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
69300
+ console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
68470
69301
  await new Promise((resolve2) => setTimeout(resolve2, delay));
68471
69302
  }
68472
69303
  }
@@ -68584,7 +69415,7 @@ async function executeOnCompleteHook(options) {
68584
69415
 
68585
69416
  // src/cli/run/agent-resolver.ts
68586
69417
  init_agent_display_names();
68587
- var import_picocolors11 = __toESM(require_picocolors(), 1);
69418
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
68588
69419
  var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
68589
69420
  var DEFAULT_AGENT = "sisyphus";
68590
69421
  var normalizeAgentName = (agent) => {
@@ -68629,10 +69460,10 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
68629
69460
  const fallbackName = getAgentDisplayName(fallback);
68630
69461
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
68631
69462
  if (fallbackDisabled) {
68632
- 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}".`));
68633
69464
  return fallbackName;
68634
69465
  }
68635
- 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}".`));
68636
69467
  return fallbackName;
68637
69468
  }
68638
69469
  return resolved.resolvedName;
@@ -68663,11 +69494,11 @@ function resolveRunModel(modelString) {
68663
69494
  }
68664
69495
 
68665
69496
  // src/cli/run/poll-for-completion.ts
68666
- var import_picocolors13 = __toESM(require_picocolors(), 1);
69497
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
68667
69498
 
68668
69499
  // src/cli/run/completion.ts
68669
69500
  init_shared();
68670
- var import_picocolors12 = __toESM(require_picocolors(), 1);
69501
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
68671
69502
  // src/features/boulder-state/constants.ts
68672
69503
  var BOULDER_DIR = ".sisyphus";
68673
69504
  var BOULDER_FILE = "boulder.json";
@@ -68675,19 +69506,19 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68675
69506
  var NOTEPAD_DIR = "notepads";
68676
69507
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68677
69508
  // src/features/boulder-state/storage.ts
68678
- import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
68679
- import { dirname as dirname4, join as join14, basename as basename3 } from "path";
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";
68680
69511
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68681
69512
  function getBoulderFilePath(directory) {
68682
- return join14(directory, BOULDER_DIR, BOULDER_FILE);
69513
+ return join15(directory, BOULDER_DIR, BOULDER_FILE);
68683
69514
  }
68684
69515
  function readBoulderState(directory) {
68685
69516
  const filePath = getBoulderFilePath(directory);
68686
- if (!existsSync14(filePath)) {
69517
+ if (!existsSync16(filePath)) {
68687
69518
  return null;
68688
69519
  }
68689
69520
  try {
68690
- const content = readFileSync10(filePath, "utf-8");
69521
+ const content = readFileSync11(filePath, "utf-8");
68691
69522
  const parsed = JSON.parse(content);
68692
69523
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
68693
69524
  return null;
@@ -68712,30 +69543,83 @@ function readBoulderState(directory) {
68712
69543
  return null;
68713
69544
  }
68714
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;
68715
69553
  function getPlanProgress(planPath) {
68716
- if (!existsSync14(planPath)) {
69554
+ if (!existsSync16(planPath)) {
68717
69555
  return { total: 0, completed: 0, isComplete: true };
68718
69556
  }
68719
69557
  try {
68720
- const content = readFileSync10(planPath, "utf-8");
68721
- const uncheckedMatches = content.match(/^\s*[-*]\s*\[\s*\]/gm) || [];
68722
- const checkedMatches = content.match(/^\s*[-*]\s*\[[xX]\]/gm) || [];
68723
- const total = uncheckedMatches.length + checkedMatches.length;
68724
- const completed = checkedMatches.length;
68725
- return {
68726
- total,
68727
- completed,
68728
- isComplete: total > 0 && completed === total
68729
- };
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);
68730
69565
  } catch {
68731
69566
  return { total: 0, completed: 0, isComplete: true };
68732
69567
  }
68733
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
+ }
68734
69617
  // src/features/claude-code-session-state/state.ts
68735
69618
  init_agent_display_names();
68736
69619
  var subagentSessions = new Set;
68737
69620
  var syncSubagentSessions = new Set;
68738
69621
  var registeredAgentNames = new Set;
69622
+ var registeredAgentAliases = new Map;
68739
69623
  var sessionAgentMap = new Map;
68740
69624
  function getSessionAgent(sessionID) {
68741
69625
  return sessionAgentMap.get(sessionID);
@@ -68743,17 +69627,17 @@ function getSessionAgent(sessionID) {
68743
69627
  // src/features/run-continuation-state/constants.ts
68744
69628
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68745
69629
  // src/features/run-continuation-state/storage.ts
68746
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
68747
- import { join as join15 } from "path";
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";
68748
69632
  function getMarkerPath(directory, sessionID) {
68749
- return join15(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
69633
+ return join16(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68750
69634
  }
68751
69635
  function readContinuationMarker(directory, sessionID) {
68752
69636
  const markerPath = getMarkerPath(directory, sessionID);
68753
- if (!existsSync15(markerPath))
69637
+ if (!existsSync17(markerPath))
68754
69638
  return null;
68755
69639
  try {
68756
- const raw = readFileSync11(markerPath, "utf-8");
69640
+ const raw = readFileSync12(markerPath, "utf-8");
68757
69641
  const parsed = JSON.parse(raw);
68758
69642
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
68759
69643
  return null;
@@ -68813,28 +69697,32 @@ async function isSessionInBoulderLineage(input) {
68813
69697
 
68814
69698
  // src/hooks/atlas/session-last-agent.ts
68815
69699
  init_shared();
68816
- import { readFileSync as readFileSync12, readdirSync as readdirSync3 } from "fs";
68817
- import { join as join16 } from "path";
68818
- function isCompactionAgent(agent) {
68819
- return typeof agent === "string" && agent.toLowerCase() === "compaction";
68820
- }
69700
+ init_compaction_marker();
69701
+ import { readFileSync as readFileSync13, readdirSync as readdirSync4 } from "fs";
69702
+ import { join as join17 } from "path";
68821
69703
  function getLastAgentFromMessageDir(messageDir) {
68822
69704
  try {
68823
- const messages = readdirSync3(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
69705
+ const messages = readdirSync4(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
68824
69706
  try {
68825
- const content = readFileSync12(join16(messageDir, fileName), "utf-8");
69707
+ const content = readFileSync13(join17(messageDir, fileName), "utf-8");
68826
69708
  const parsed = JSON.parse(content);
68827
69709
  return {
68828
69710
  fileName,
69711
+ id: parsed.id,
68829
69712
  agent: parsed.agent,
68830
69713
  createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
68831
69714
  };
68832
69715
  } catch {
68833
69716
  return null;
68834
69717
  }
68835
- }).filter((message) => message !== null).sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName));
69718
+ }).filter((message) => message !== null).sort((left, right) => (right?.createdAt ?? 0) - (left?.createdAt ?? 0) || (right?.fileName ?? "").localeCompare(left?.fileName ?? ""));
68836
69719
  for (const message of messages) {
68837
- if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
69720
+ if (!message)
69721
+ continue;
69722
+ if (isCompactionMessage({ agent: message.agent }) || hasCompactionPartInStorage(message?.id)) {
69723
+ continue;
69724
+ }
69725
+ if (typeof message.agent === "string") {
68838
69726
  return message.agent.toLowerCase();
68839
69727
  }
68840
69728
  }
@@ -68860,8 +69748,11 @@ async function getLastAgentFromSession(sessionID, client3) {
68860
69748
  return rightId.localeCompare(leftId);
68861
69749
  });
68862
69750
  for (const message of messages) {
69751
+ if (isCompactionMessage(message)) {
69752
+ continue;
69753
+ }
68863
69754
  const agent = message.info?.agent;
68864
- if (typeof agent === "string" && !isCompactionAgent(agent)) {
69755
+ if (typeof agent === "string") {
68865
69756
  return agent.toLowerCase();
68866
69757
  }
68867
69758
  }
@@ -68881,8 +69772,8 @@ init_agent_display_names();
68881
69772
 
68882
69773
  // src/hooks/ralph-loop/storage.ts
68883
69774
  init_frontmatter();
68884
- import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
68885
- import { dirname as dirname5, join as join17 } from "path";
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";
68886
69777
 
68887
69778
  // src/hooks/ralph-loop/constants.ts
68888
69779
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -68891,15 +69782,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
68891
69782
 
68892
69783
  // src/hooks/ralph-loop/storage.ts
68893
69784
  function getStateFilePath(directory, customPath) {
68894
- return customPath ? join17(directory, customPath) : join17(directory, DEFAULT_STATE_FILE);
69785
+ return customPath ? join18(directory, customPath) : join18(directory, DEFAULT_STATE_FILE);
68895
69786
  }
68896
69787
  function readState(directory, customPath) {
68897
69788
  const filePath = getStateFilePath(directory, customPath);
68898
- if (!existsSync16(filePath)) {
69789
+ if (!existsSync18(filePath)) {
68899
69790
  return null;
68900
69791
  }
68901
69792
  try {
68902
- const content = readFileSync13(filePath, "utf-8");
69793
+ const content = readFileSync14(filePath, "utf-8");
68903
69794
  const { data, body } = parseFrontmatter(content);
68904
69795
  const active = data.active;
68905
69796
  const iteration = data.iteration;
@@ -69023,7 +69914,7 @@ async function checkCompletionConditions(ctx) {
69023
69914
  }
69024
69915
  return true;
69025
69916
  } catch (err) {
69026
- console.error(import_picocolors12.default.red(`[completion] API error: ${err}`));
69917
+ console.error(import_picocolors13.default.red(`[completion] API error: ${err}`));
69027
69918
  return false;
69028
69919
  }
69029
69920
  }
@@ -69084,7 +69975,7 @@ function logWaiting(ctx, message) {
69084
69975
  if (!ctx.verbose) {
69085
69976
  return;
69086
69977
  }
69087
- console.log(import_picocolors12.default.dim(` Waiting: ${message}`));
69978
+ console.log(import_picocolors13.default.dim(` Waiting: ${message}`));
69088
69979
  }
69089
69980
 
69090
69981
  // src/cli/run/poll-for-completion.ts
@@ -69115,10 +70006,10 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
69115
70006
  if (eventState.mainSessionError) {
69116
70007
  errorCycleCount++;
69117
70008
  if (errorCycleCount >= ERROR_GRACE_CYCLES) {
69118
- console.error(import_picocolors13.default.red(`
70009
+ console.error(import_picocolors14.default.red(`
69119
70010
 
69120
70011
  Session ended with error: ${eventState.lastError}`));
69121
- 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."));
69122
70013
  return 1;
69123
70014
  }
69124
70015
  continue;
@@ -69129,7 +70020,7 @@ Session ended with error: ${eventState.lastError}`));
69129
70020
  if (eventState.lastEventTimestamp !== null) {
69130
70021
  const timeSinceLastEvent = Date.now() - eventState.lastEventTimestamp;
69131
70022
  if (timeSinceLastEvent > eventWatchdogMs) {
69132
- console.log(import_picocolors13.default.yellow(`
70023
+ console.log(import_picocolors14.default.yellow(`
69133
70024
  No events for ${Math.round(timeSinceLastEvent / 1000)}s, verifying session status...`));
69134
70025
  mainSessionStatus = await getMainSessionStatus(ctx);
69135
70026
  if (mainSessionStatus === "idle") {
@@ -69178,7 +70069,7 @@ Session ended with error: ${eventState.lastError}`));
69178
70069
  const hasActiveWork = hasActiveChildren || hasActiveTodos;
69179
70070
  if (hasActiveWork) {
69180
70071
  eventState.hasReceivedMeaningfulWork = true;
69181
- console.log(import_picocolors13.default.yellow(`
70072
+ console.log(import_picocolors14.default.yellow(`
69182
70073
  No meaningful work events for ${Math.round(secondaryMeaningfulWorkTimeoutMs / 1000)}s but session has active work - assuming in progress`));
69183
70074
  }
69184
70075
  }
@@ -69198,7 +70089,7 @@ Session ended with error: ${eventState.lastError}`));
69198
70089
  }
69199
70090
  consecutiveCompleteChecks++;
69200
70091
  if (consecutiveCompleteChecks >= requiredConsecutive) {
69201
- console.log(import_picocolors13.default.green(`
70092
+ console.log(import_picocolors14.default.green(`
69202
70093
 
69203
70094
  All tasks completed.`));
69204
70095
  return 0;
@@ -69367,7 +70258,7 @@ async function run(options) {
69367
70258
  };
69368
70259
  const restoreInput = suppressRunInput();
69369
70260
  const handleSigint = () => {
69370
- console.log(import_picocolors14.default.yellow(`
70261
+ console.log(import_picocolors15.default.yellow(`
69371
70262
  Interrupted. Shutting down...`));
69372
70263
  restoreInput();
69373
70264
  cleanup();
@@ -69380,9 +70271,9 @@ Interrupted. Shutting down...`));
69380
70271
  sessionId: options.sessionId,
69381
70272
  directory
69382
70273
  });
69383
- console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
70274
+ console.log(import_picocolors15.default.dim(`Session: ${sessionID}`));
69384
70275
  if (resolvedModel) {
69385
- console.log(import_picocolors14.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
70276
+ console.log(import_picocolors15.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
69386
70277
  }
69387
70278
  const ctx = {
69388
70279
  client: client3,
@@ -69445,7 +70336,7 @@ Interrupted. Shutting down...`));
69445
70336
  if (err instanceof Error && err.name === "AbortError") {
69446
70337
  return 130;
69447
70338
  }
69448
- console.error(import_picocolors14.default.red(`Error: ${serializeError(err)}`));
70339
+ console.error(import_picocolors15.default.red(`Error: ${serializeError(err)}`));
69449
70340
  return 1;
69450
70341
  } finally {
69451
70342
  timestampOutput?.restore();
@@ -69455,53 +70346,53 @@ Interrupted. Shutting down...`));
69455
70346
  init_checker();
69456
70347
 
69457
70348
  // src/cli/get-local-version/formatter.ts
69458
- var import_picocolors15 = __toESM(require_picocolors(), 1);
69459
- var SYMBOLS2 = {
69460
- check: import_picocolors15.default.green("[OK]"),
69461
- cross: import_picocolors15.default.red("[X]"),
69462
- arrow: import_picocolors15.default.cyan("->"),
69463
- info: import_picocolors15.default.blue("[i]"),
69464
- warn: import_picocolors15.default.yellow("[!]"),
69465
- pin: import_picocolors15.default.magenta("[PINNED]"),
69466
- 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]")
69467
70358
  };
69468
70359
  function formatVersionOutput(info) {
69469
70360
  const lines = [];
69470
70361
  lines.push("");
69471
- lines.push(import_picocolors15.default.bold(import_picocolors15.default.white("oh-my-opencode Version Information")));
69472
- 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)));
69473
70364
  lines.push("");
69474
70365
  if (info.currentVersion) {
69475
- lines.push(` Current Version: ${import_picocolors15.default.cyan(info.currentVersion)}`);
70366
+ lines.push(` Current Version: ${import_picocolors16.default.cyan(info.currentVersion)}`);
69476
70367
  } else {
69477
- lines.push(` Current Version: ${import_picocolors15.default.dim("unknown")}`);
70368
+ lines.push(` Current Version: ${import_picocolors16.default.dim("unknown")}`);
69478
70369
  }
69479
70370
  if (!info.isLocalDev && info.latestVersion) {
69480
- lines.push(` Latest Version: ${import_picocolors15.default.cyan(info.latestVersion)}`);
70371
+ lines.push(` Latest Version: ${import_picocolors16.default.cyan(info.latestVersion)}`);
69481
70372
  }
69482
70373
  lines.push("");
69483
70374
  switch (info.status) {
69484
70375
  case "up-to-date":
69485
- 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!")}`);
69486
70377
  break;
69487
70378
  case "outdated":
69488
- lines.push(` ${SYMBOLS2.warn} ${import_picocolors15.default.yellow("Update available")}`);
69489
- 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")}`);
69490
70381
  break;
69491
70382
  case "local-dev":
69492
- lines.push(` ${SYMBOLS2.dev} ${import_picocolors15.default.cyan("Running in local development mode")}`);
69493
- 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")}`);
69494
70385
  break;
69495
70386
  case "pinned":
69496
- lines.push(` ${SYMBOLS2.pin} ${import_picocolors15.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
69497
- 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")}`);
69498
70389
  break;
69499
70390
  case "error":
69500
- lines.push(` ${SYMBOLS2.cross} ${import_picocolors15.default.red("Unable to check for updates")}`);
69501
- 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")}`);
69502
70393
  break;
69503
70394
  case "unknown":
69504
- lines.push(` ${SYMBOLS2.info} ${import_picocolors15.default.yellow("Version information unavailable")}`);
70395
+ lines.push(` ${SYMBOLS3.info} ${import_picocolors16.default.yellow("Version information unavailable")}`);
69505
70396
  break;
69506
70397
  }
69507
70398
  lines.push("");
@@ -69600,69 +70491,31 @@ async function getLocalVersion(options = {}) {
69600
70491
  return 1;
69601
70492
  }
69602
70493
  }
69603
- // src/cli/doctor/constants.ts
69604
- init_shared();
69605
- var import_picocolors16 = __toESM(require_picocolors(), 1);
69606
- var SYMBOLS3 = {
69607
- check: import_picocolors16.default.green("\u2713"),
69608
- cross: import_picocolors16.default.red("\u2717"),
69609
- warn: import_picocolors16.default.yellow("\u26A0"),
69610
- info: import_picocolors16.default.blue("\u2139"),
69611
- arrow: import_picocolors16.default.cyan("\u2192"),
69612
- bullet: import_picocolors16.default.dim("\u2022"),
69613
- skip: import_picocolors16.default.dim("\u25CB")
69614
- };
69615
- var STATUS_COLORS = {
69616
- pass: import_picocolors16.default.green,
69617
- fail: import_picocolors16.default.red,
69618
- warn: import_picocolors16.default.yellow,
69619
- skip: import_picocolors16.default.dim
69620
- };
69621
- var CHECK_IDS = {
69622
- SYSTEM: "system",
69623
- CONFIG: "config",
69624
- TOOLS: "tools",
69625
- MODELS: "models"
69626
- };
69627
- var CHECK_NAMES = {
69628
- [CHECK_IDS.SYSTEM]: "System",
69629
- [CHECK_IDS.CONFIG]: "Configuration",
69630
- [CHECK_IDS.TOOLS]: "Tools",
69631
- [CHECK_IDS.MODELS]: "Models"
69632
- };
69633
- var EXIT_CODES = {
69634
- SUCCESS: 0,
69635
- FAILURE: 1
69636
- };
69637
- var MIN_OPENCODE_VERSION = "1.0.150";
69638
- var PACKAGE_NAME2 = PLUGIN_NAME;
69639
- var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
69640
-
69641
70494
  // src/cli/doctor/checks/system.ts
69642
- import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
70495
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
69643
70496
 
69644
70497
  // src/cli/doctor/checks/system-binary.ts
69645
70498
  init_spawn_with_windows_hide();
69646
- import { existsSync as existsSync24 } from "fs";
70499
+ import { existsSync as existsSync26 } from "fs";
69647
70500
  import { homedir as homedir5 } from "os";
69648
- import { join as join24 } from "path";
70501
+ import { join as join25 } from "path";
69649
70502
  function getDesktopAppPaths(platform) {
69650
70503
  const home = homedir5();
69651
70504
  switch (platform) {
69652
70505
  case "darwin":
69653
70506
  return [
69654
70507
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
69655
- join24(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
70508
+ join25(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69656
70509
  ];
69657
70510
  case "win32": {
69658
70511
  const programFiles = process.env.ProgramFiles;
69659
70512
  const localAppData = process.env.LOCALAPPDATA;
69660
70513
  const paths = [];
69661
70514
  if (programFiles) {
69662
- paths.push(join24(programFiles, "OpenCode", "OpenCode.exe"));
70515
+ paths.push(join25(programFiles, "OpenCode", "OpenCode.exe"));
69663
70516
  }
69664
70517
  if (localAppData) {
69665
- paths.push(join24(localAppData, "OpenCode", "OpenCode.exe"));
70518
+ paths.push(join25(localAppData, "OpenCode", "OpenCode.exe"));
69666
70519
  }
69667
70520
  return paths;
69668
70521
  }
@@ -69670,8 +70523,8 @@ function getDesktopAppPaths(platform) {
69670
70523
  return [
69671
70524
  "/usr/bin/opencode",
69672
70525
  "/usr/lib/opencode/opencode",
69673
- join24(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69674
- join24(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")
69675
70528
  ];
69676
70529
  default:
69677
70530
  return [];
@@ -69683,7 +70536,7 @@ function buildVersionCommand(binaryPath, platform) {
69683
70536
  }
69684
70537
  return [binaryPath, "--version"];
69685
70538
  }
69686
- function findDesktopBinary(platform = process.platform, checkExists = existsSync24) {
70539
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync26) {
69687
70540
  for (const desktopPath of getDesktopAppPaths(platform)) {
69688
70541
  if (checkExists(desktopPath)) {
69689
70542
  return { binary: "opencode", path: desktopPath };
@@ -69713,10 +70566,10 @@ async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
69713
70566
  return null;
69714
70567
  }
69715
70568
  }
69716
- function compareVersions2(current, minimum) {
69717
- const parseVersion2 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
69718
- const currentParts = parseVersion2(current);
69719
- const minimumParts = parseVersion2(minimum);
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);
69720
70573
  const length = Math.max(currentParts.length, minimumParts.length);
69721
70574
  for (let index = 0;index < length; index++) {
69722
70575
  const currentPart = currentParts[index] ?? 0;
@@ -69731,12 +70584,12 @@ function compareVersions2(current, minimum) {
69731
70584
 
69732
70585
  // src/cli/doctor/checks/system-plugin.ts
69733
70586
  init_shared();
69734
- import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
70587
+ import { existsSync as existsSync27, readFileSync as readFileSync22 } from "fs";
69735
70588
  function detectConfigPath() {
69736
70589
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
69737
- if (existsSync25(paths.configJsonc))
70590
+ if (existsSync27(paths.configJsonc))
69738
70591
  return paths.configJsonc;
69739
- if (existsSync25(paths.configJson))
70592
+ if (existsSync27(paths.configJson))
69740
70593
  return paths.configJson;
69741
70594
  return null;
69742
70595
  }
@@ -69782,7 +70635,7 @@ function getPluginInfo() {
69782
70635
  };
69783
70636
  }
69784
70637
  try {
69785
- const content = readFileSync21(configPath, "utf-8");
70638
+ const content = readFileSync22(configPath, "utf-8");
69786
70639
  const parsedConfig = parseJsonc(content);
69787
70640
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
69788
70641
  if (!pluginEntry) {
@@ -69820,37 +70673,37 @@ function getPluginInfo() {
69820
70673
  init_file_utils();
69821
70674
  init_checker();
69822
70675
  init_auto_update_checker();
69823
- import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
70676
+ import { existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
69824
70677
  import { homedir as homedir6 } from "os";
69825
- import { join as join25 } from "path";
70678
+ import { join as join26 } from "path";
69826
70679
  init_shared();
69827
70680
  function getPlatformDefaultCacheDir(platform = process.platform) {
69828
70681
  if (platform === "darwin")
69829
- return join25(homedir6(), "Library", "Caches");
70682
+ return join26(homedir6(), "Library", "Caches");
69830
70683
  if (platform === "win32")
69831
- return process.env.LOCALAPPDATA ?? join25(homedir6(), "AppData", "Local");
69832
- return join25(homedir6(), ".cache");
70684
+ return process.env.LOCALAPPDATA ?? join26(homedir6(), "AppData", "Local");
70685
+ return join26(homedir6(), ".cache");
69833
70686
  }
69834
70687
  function resolveOpenCodeCacheDir() {
69835
70688
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
69836
70689
  if (xdgCacheHome)
69837
- return join25(xdgCacheHome, "opencode");
70690
+ return join26(xdgCacheHome, "opencode");
69838
70691
  const fromShared = getOpenCodeCacheDir();
69839
- const platformDefault = join25(getPlatformDefaultCacheDir(), "opencode");
69840
- if (existsSync26(fromShared) || !existsSync26(platformDefault))
70692
+ const platformDefault = join26(getPlatformDefaultCacheDir(), "opencode");
70693
+ if (existsSync28(fromShared) || !existsSync28(platformDefault))
69841
70694
  return fromShared;
69842
70695
  return platformDefault;
69843
70696
  }
69844
70697
  function resolveExistingDir(dirPath) {
69845
- if (!existsSync26(dirPath))
70698
+ if (!existsSync28(dirPath))
69846
70699
  return dirPath;
69847
70700
  return resolveSymlink(dirPath);
69848
70701
  }
69849
70702
  function readPackageJson(filePath) {
69850
- if (!existsSync26(filePath))
70703
+ if (!existsSync28(filePath))
69851
70704
  return null;
69852
70705
  try {
69853
- const content = readFileSync22(filePath, "utf-8");
70706
+ const content = readFileSync23(filePath, "utf-8");
69854
70707
  return parseJsonc(content);
69855
70708
  } catch {
69856
70709
  return null;
@@ -69869,20 +70722,20 @@ function getLoadedPluginVersion() {
69869
70722
  const candidates = [
69870
70723
  {
69871
70724
  cacheDir: configDir,
69872
- cachePackagePath: join25(configDir, "package.json"),
69873
- installedPackagePath: join25(configDir, "node_modules", PACKAGE_NAME2, "package.json")
70725
+ cachePackagePath: join26(configDir, "package.json"),
70726
+ installedPackagePath: join26(configDir, "node_modules", PACKAGE_NAME, "package.json")
69874
70727
  },
69875
70728
  {
69876
70729
  cacheDir,
69877
- cachePackagePath: join25(cacheDir, "package.json"),
69878
- installedPackagePath: join25(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
70730
+ cachePackagePath: join26(cacheDir, "package.json"),
70731
+ installedPackagePath: join26(cacheDir, "node_modules", PACKAGE_NAME, "package.json")
69879
70732
  }
69880
70733
  ];
69881
- const selectedCandidate = candidates.find((candidate) => existsSync26(candidate.installedPackagePath)) ?? candidates[0];
70734
+ const selectedCandidate = candidates.find((candidate) => existsSync28(candidate.installedPackagePath)) ?? candidates[0];
69882
70735
  const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
69883
70736
  const cachePackage = readPackageJson(cachePackagePath);
69884
70737
  const installedPackage = readPackageJson(installedPackagePath);
69885
- const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME2]);
70738
+ const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME]);
69886
70739
  const loadedVersion = normalizeVersion(installedPackage?.version);
69887
70740
  return {
69888
70741
  cacheDir: selectedDir,
@@ -69905,10 +70758,10 @@ init_shared();
69905
70758
  function isConfigValid(configPath) {
69906
70759
  if (!configPath)
69907
70760
  return true;
69908
- if (!existsSync27(configPath))
70761
+ if (!existsSync29(configPath))
69909
70762
  return false;
69910
70763
  try {
69911
- parseJsonc(readFileSync23(configPath, "utf-8"));
70764
+ parseJsonc(readFileSync24(configPath, "utf-8"));
69912
70765
  return true;
69913
70766
  } catch {
69914
70767
  return false;
@@ -69959,7 +70812,7 @@ async function checkSystem() {
69959
70812
  affects: ["doctor", "run"]
69960
70813
  });
69961
70814
  }
69962
- if (systemInfo.opencodeVersion && !compareVersions2(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
70815
+ if (systemInfo.opencodeVersion && !compareVersions3(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69963
70816
  issues.push({
69964
70817
  title: "OpenCode version below minimum",
69965
70818
  description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
@@ -69999,7 +70852,7 @@ async function checkSystem() {
69999
70852
  affects: ["plugin loading"]
70000
70853
  });
70001
70854
  }
70002
- if (systemInfo.loadedVersion && latestVersion && !compareVersions2(systemInfo.loadedVersion, latestVersion)) {
70855
+ if (systemInfo.loadedVersion && latestVersion && !compareVersions3(systemInfo.loadedVersion, latestVersion)) {
70003
70856
  issues.push({
70004
70857
  title: "Loaded plugin is outdated",
70005
70858
  description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
@@ -70024,28 +70877,28 @@ async function checkSystem() {
70024
70877
  }
70025
70878
 
70026
70879
  // src/cli/doctor/checks/config.ts
70027
- import { readFileSync as readFileSync26 } from "fs";
70028
- import { join as join29 } from "path";
70880
+ import { readFileSync as readFileSync27 } from "fs";
70881
+ import { join as join30 } from "path";
70029
70882
  init_shared();
70030
70883
 
70031
70884
  // src/cli/doctor/checks/model-resolution-cache.ts
70032
70885
  init_shared();
70033
- import { existsSync as existsSync28, readFileSync as readFileSync24 } from "fs";
70886
+ import { existsSync as existsSync30, readFileSync as readFileSync25 } from "fs";
70034
70887
  import { homedir as homedir7 } from "os";
70035
- import { join as join26 } from "path";
70888
+ import { join as join27 } from "path";
70036
70889
  function getOpenCodeCacheDir2() {
70037
70890
  const xdgCache = process.env.XDG_CACHE_HOME;
70038
70891
  if (xdgCache)
70039
- return join26(xdgCache, "opencode");
70040
- return join26(homedir7(), ".cache", "opencode");
70892
+ return join27(xdgCache, "opencode");
70893
+ return join27(homedir7(), ".cache", "opencode");
70041
70894
  }
70042
70895
  function loadAvailableModelsFromCache() {
70043
- const cacheFile = join26(getOpenCodeCacheDir2(), "models.json");
70044
- if (!existsSync28(cacheFile)) {
70896
+ const cacheFile = join27(getOpenCodeCacheDir2(), "models.json");
70897
+ if (!existsSync30(cacheFile)) {
70045
70898
  return { providers: [], modelCount: 0, cacheExists: false };
70046
70899
  }
70047
70900
  try {
70048
- const content = readFileSync24(cacheFile, "utf-8");
70901
+ const content = readFileSync25(cacheFile, "utf-8");
70049
70902
  const data = parseJsonc(content);
70050
70903
  const providers = Object.keys(data);
70051
70904
  let modelCount = 0;
@@ -70067,14 +70920,14 @@ init_model_capabilities();
70067
70920
 
70068
70921
  // src/cli/doctor/checks/model-resolution-config.ts
70069
70922
  init_shared();
70070
- import { readFileSync as readFileSync25 } from "fs";
70071
- import { join as join27 } from "path";
70072
- var PROJECT_CONFIG_DIR = join27(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");
70073
70926
  function loadOmoConfig() {
70074
70927
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
70075
70928
  if (projectDetected.format !== "none") {
70076
70929
  try {
70077
- const content = readFileSync25(projectDetected.path, "utf-8");
70930
+ const content = readFileSync26(projectDetected.path, "utf-8");
70078
70931
  return parseJsonc(content);
70079
70932
  } catch {
70080
70933
  return null;
@@ -70084,7 +70937,7 @@ function loadOmoConfig() {
70084
70937
  const userDetected = detectPluginConfigFile(userConfigDir);
70085
70938
  if (userDetected.format !== "none") {
70086
70939
  try {
70087
- const content = readFileSync25(userDetected.path, "utf-8");
70940
+ const content = readFileSync26(userDetected.path, "utf-8");
70088
70941
  return parseJsonc(content);
70089
70942
  } catch {
70090
70943
  return null;
@@ -70095,7 +70948,7 @@ function loadOmoConfig() {
70095
70948
 
70096
70949
  // src/cli/doctor/checks/model-resolution-details.ts
70097
70950
  init_shared();
70098
- import { join as join28 } from "path";
70951
+ import { join as join29 } from "path";
70099
70952
 
70100
70953
  // src/cli/doctor/checks/model-resolution-variant.ts
70101
70954
  function formatModelWithVariant(model, variant) {
@@ -70137,7 +70990,7 @@ function formatCapabilityResolutionLabel(mode) {
70137
70990
  }
70138
70991
  function buildModelResolutionDetails(options) {
70139
70992
  const details = [];
70140
- const cacheFile = join28(getOpenCodeCacheDir(), "models.json");
70993
+ const cacheFile = join29(getOpenCodeCacheDir(), "models.json");
70141
70994
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
70142
70995
  details.push("");
70143
70996
  if (options.available.cacheExists) {
@@ -70292,7 +71145,7 @@ async function checkModels() {
70292
71145
  }
70293
71146
 
70294
71147
  // src/cli/doctor/checks/config.ts
70295
- var PROJECT_CONFIG_DIR2 = join29(process.cwd(), ".opencode");
71148
+ var PROJECT_CONFIG_DIR2 = join30(process.cwd(), ".opencode");
70296
71149
  function findConfigPath() {
70297
71150
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
70298
71151
  if (projectConfig.format !== "none")
@@ -70309,7 +71162,7 @@ function validateConfig() {
70309
71162
  return { exists: false, path: null, valid: true, config: null, errors: [] };
70310
71163
  }
70311
71164
  try {
70312
- const content = readFileSync26(configPath, "utf-8");
71165
+ const content = readFileSync27(configPath, "utf-8");
70313
71166
  const rawConfig = parseJsonc(content);
70314
71167
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
70315
71168
  if (!schemaResult.success) {
@@ -70413,9 +71266,9 @@ async function checkConfig() {
70413
71266
 
70414
71267
  // src/cli/doctor/checks/dependencies.ts
70415
71268
  init_spawn_with_windows_hide();
70416
- import { existsSync as existsSync29 } from "fs";
71269
+ import { existsSync as existsSync31 } from "fs";
70417
71270
  import { createRequire } from "module";
70418
- import { dirname as dirname9, join as join30 } from "path";
71271
+ import { dirname as dirname10, join as join31 } from "path";
70419
71272
  async function checkBinaryExists(binary2) {
70420
71273
  try {
70421
71274
  const path10 = Bun.which(binary2);
@@ -70471,15 +71324,15 @@ async function checkAstGrepNapi() {
70471
71324
  path: null
70472
71325
  };
70473
71326
  } catch {
70474
- const { existsSync: existsSync30 } = await import("fs");
70475
- const { join: join31 } = await import("path");
71327
+ const { existsSync: existsSync32 } = await import("fs");
71328
+ const { join: join32 } = await import("path");
70476
71329
  const { homedir: homedir8 } = await import("os");
70477
71330
  const pathsToCheck = [
70478
- join31(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70479
- join31(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")
70480
71333
  ];
70481
71334
  for (const napiPath of pathsToCheck) {
70482
- if (existsSync30(napiPath)) {
71335
+ if (existsSync32(napiPath)) {
70483
71336
  return {
70484
71337
  name: "AST-Grep NAPI",
70485
71338
  required: false,
@@ -70504,8 +71357,8 @@ function findCommentCheckerPackageBinary() {
70504
71357
  try {
70505
71358
  const require2 = createRequire(import.meta.url);
70506
71359
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
70507
- const binaryPath = join30(dirname9(pkgPath), "bin", binaryName);
70508
- if (existsSync29(binaryPath))
71360
+ const binaryPath = join31(dirname10(pkgPath), "bin", binaryName);
71361
+ if (existsSync31(binaryPath))
70509
71362
  return binaryPath;
70510
71363
  } catch {}
70511
71364
  return null;
@@ -70662,15 +71515,15 @@ var BUILTIN_SERVERS = {
70662
71515
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
70663
71516
  };
70664
71517
  // src/tools/lsp/server-config-loader.ts
70665
- import { existsSync as existsSync30, readFileSync as readFileSync27 } from "fs";
70666
- import { join as join31 } from "path";
71518
+ import { existsSync as existsSync32, readFileSync as readFileSync28 } from "fs";
71519
+ import { join as join32 } from "path";
70667
71520
  init_shared();
70668
71521
  init_jsonc_parser();
70669
71522
  function loadJsonFile(path10) {
70670
- if (!existsSync30(path10))
71523
+ if (!existsSync32(path10))
70671
71524
  return null;
70672
71525
  try {
70673
- return parseJsonc(readFileSync27(path10, "utf-8"));
71526
+ return parseJsonc(readFileSync28(path10, "utf-8"));
70674
71527
  } catch {
70675
71528
  return null;
70676
71529
  }
@@ -70679,9 +71532,9 @@ function getConfigPaths2() {
70679
71532
  const cwd = process.cwd();
70680
71533
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70681
71534
  return {
70682
- project: detectPluginConfigFile(join31(cwd, ".opencode")).path,
71535
+ project: detectPluginConfigFile(join32(cwd, ".opencode")).path,
70683
71536
  user: detectPluginConfigFile(configDir).path,
70684
- opencode: detectConfigFile(join31(configDir, "opencode")).path
71537
+ opencode: detectConfigFile(join32(configDir, "opencode")).path
70685
71538
  };
70686
71539
  }
70687
71540
  function loadAllConfigs() {
@@ -70750,21 +71603,21 @@ function getMergedServers() {
70750
71603
  }
70751
71604
 
70752
71605
  // src/tools/lsp/server-installation.ts
70753
- import { existsSync as existsSync31 } from "fs";
70754
- import { delimiter as delimiter2, join as join33 } from "path";
71606
+ import { existsSync as existsSync33 } from "fs";
71607
+ import { delimiter as delimiter2, join as join34 } from "path";
70755
71608
 
70756
71609
  // src/tools/lsp/server-path-bases.ts
70757
71610
  init_shared();
70758
- import { join as join32 } from "path";
71611
+ import { join as join33 } from "path";
70759
71612
  function getLspServerAdditionalPathBases(workingDirectory) {
70760
71613
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70761
- const dataDir = join32(getDataDir(), "opencode");
71614
+ const dataDir = join33(getDataDir(), "opencode");
70762
71615
  return [
70763
- join32(workingDirectory, "node_modules", ".bin"),
70764
- join32(configDir, "bin"),
70765
- join32(configDir, "node_modules", ".bin"),
70766
- join32(dataDir, "bin"),
70767
- join32(dataDir, "bin", "node_modules", ".bin")
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")
70768
71621
  ];
70769
71622
  }
70770
71623
 
@@ -70774,7 +71627,7 @@ function isServerInstalled(command) {
70774
71627
  return false;
70775
71628
  const cmd = command[0];
70776
71629
  if (cmd.includes("/") || cmd.includes("\\")) {
70777
- if (existsSync31(cmd))
71630
+ if (existsSync33(cmd))
70778
71631
  return true;
70779
71632
  }
70780
71633
  const isWindows = process.platform === "win32";
@@ -70795,14 +71648,14 @@ function isServerInstalled(command) {
70795
71648
  const paths = pathEnv.split(delimiter2);
70796
71649
  for (const p2 of paths) {
70797
71650
  for (const suffix of exts) {
70798
- if (existsSync31(join33(p2, cmd + suffix))) {
71651
+ if (existsSync33(join34(p2, cmd + suffix))) {
70799
71652
  return true;
70800
71653
  }
70801
71654
  }
70802
71655
  }
70803
71656
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
70804
71657
  for (const suffix of exts) {
70805
- if (existsSync31(join33(base, cmd + suffix))) {
71658
+ if (existsSync33(join34(base, cmd + suffix))) {
70806
71659
  return true;
70807
71660
  }
70808
71661
  }
@@ -70864,24 +71717,24 @@ function getInstalledLspServers() {
70864
71717
 
70865
71718
  // src/cli/doctor/checks/tools-mcp.ts
70866
71719
  init_shared();
70867
- import { existsSync as existsSync32, readFileSync as readFileSync28 } from "fs";
71720
+ import { existsSync as existsSync34, readFileSync as readFileSync29 } from "fs";
70868
71721
  import { homedir as homedir8 } from "os";
70869
- import { join as join34 } from "path";
71722
+ import { join as join35 } from "path";
70870
71723
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
70871
71724
  function getMcpConfigPaths() {
70872
71725
  return [
70873
- join34(homedir8(), ".claude", ".mcp.json"),
70874
- join34(process.cwd(), ".mcp.json"),
70875
- join34(process.cwd(), ".claude", ".mcp.json")
71726
+ join35(homedir8(), ".claude", ".mcp.json"),
71727
+ join35(process.cwd(), ".mcp.json"),
71728
+ join35(process.cwd(), ".claude", ".mcp.json")
70876
71729
  ];
70877
71730
  }
70878
71731
  function loadUserMcpConfig() {
70879
71732
  const servers = {};
70880
71733
  for (const configPath of getMcpConfigPaths()) {
70881
- if (!existsSync32(configPath))
71734
+ if (!existsSync34(configPath))
70882
71735
  continue;
70883
71736
  try {
70884
- const content = readFileSync28(configPath, "utf-8");
71737
+ const content = readFileSync29(configPath, "utf-8");
70885
71738
  const config2 = parseJsonc(content);
70886
71739
  if (config2.mcpServers) {
70887
71740
  Object.assign(servers, config2.mcpServers);
@@ -71048,17 +71901,17 @@ function formatStatusSymbol(status) {
71048
71901
  const colorFn = STATUS_COLORS[status];
71049
71902
  switch (status) {
71050
71903
  case "pass":
71051
- return colorFn(SYMBOLS3.check);
71904
+ return colorFn(SYMBOLS2.check);
71052
71905
  case "fail":
71053
- return colorFn(SYMBOLS3.cross);
71906
+ return colorFn(SYMBOLS2.cross);
71054
71907
  case "warn":
71055
- return colorFn(SYMBOLS3.warn);
71908
+ return colorFn(SYMBOLS2.warn);
71056
71909
  case "skip":
71057
- return colorFn(SYMBOLS3.skip);
71910
+ return colorFn(SYMBOLS2.skip);
71058
71911
  }
71059
71912
  }
71060
71913
  function formatStatusMark(available) {
71061
- 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);
71062
71915
  }
71063
71916
  function formatHeader() {
71064
71917
  return `
@@ -71088,12 +71941,12 @@ function formatDefault(result) {
71088
71941
  if (allIssues.length === 0) {
71089
71942
  const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
71090
71943
  const pluginVer = result.systemInfo.pluginVersion ?? "unknown";
71091
- 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})`)}`);
71092
71945
  } else {
71093
71946
  const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
71094
71947
  const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
71095
71948
  const totalStr = `${issueCount + warnCount} ${issueCount + warnCount === 1 ? "issue" : "issues"}`;
71096
- lines.push(` ${import_picocolors18.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
71949
+ lines.push(` ${import_picocolors18.default.yellow(SYMBOLS2.warn)} ${totalStr} found:
71097
71950
  `);
71098
71951
  allIssues.forEach((issue2, index) => {
71099
71952
  lines.push(formatIssue(issue2, index + 1));
@@ -71334,11 +72187,11 @@ async function refreshModelCapabilities(options, deps = {}) {
71334
72187
 
71335
72188
  // src/features/mcp-oauth/storage.ts
71336
72189
  init_shared();
71337
- import { chmodSync, existsSync as existsSync33, mkdirSync as mkdirSync8, readFileSync as readFileSync29, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
71338
- import { dirname as dirname10, join as join35 } from "path";
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";
71339
72192
  var STORAGE_FILE_NAME = "mcp-oauth.json";
71340
72193
  function getMcpOauthStoragePath() {
71341
- return join35(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
72194
+ return join36(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71342
72195
  }
71343
72196
  function normalizeHost(serverHost) {
71344
72197
  let host = serverHost.trim();
@@ -71375,11 +72228,11 @@ function buildKey(serverHost, resource) {
71375
72228
  }
71376
72229
  function readStore() {
71377
72230
  const filePath = getMcpOauthStoragePath();
71378
- if (!existsSync33(filePath)) {
72231
+ if (!existsSync35(filePath)) {
71379
72232
  return null;
71380
72233
  }
71381
72234
  try {
71382
- const content = readFileSync29(filePath, "utf-8");
72235
+ const content = readFileSync30(filePath, "utf-8");
71383
72236
  return JSON.parse(content);
71384
72237
  } catch {
71385
72238
  return null;
@@ -71388,12 +72241,14 @@ function readStore() {
71388
72241
  function writeStore(store2) {
71389
72242
  const filePath = getMcpOauthStoragePath();
71390
72243
  try {
71391
- const dir = dirname10(filePath);
71392
- if (!existsSync33(dir)) {
71393
- mkdirSync8(dir, { recursive: true });
71394
- }
71395
- writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
71396
- 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);
71397
72252
  return true;
71398
72253
  } catch {
71399
72254
  return false;
@@ -71424,7 +72279,7 @@ function deleteToken(serverHost, resource) {
71424
72279
  if (Object.keys(store2).length === 0) {
71425
72280
  try {
71426
72281
  const filePath = getMcpOauthStoragePath();
71427
- if (existsSync33(filePath)) {
72282
+ if (existsSync35(filePath)) {
71428
72283
  unlinkSync4(filePath);
71429
72284
  }
71430
72285
  return true;
@@ -71614,7 +72469,7 @@ async function findAvailablePort2(startPort = DEFAULT_PORT) {
71614
72469
  }
71615
72470
 
71616
72471
  // src/features/mcp-oauth/oauth-authorization-flow.ts
71617
- import { spawn as spawn2 } from "child_process";
72472
+ import { spawn } from "child_process";
71618
72473
  import { createHash, randomBytes as randomBytes2 } from "crypto";
71619
72474
  import { createServer } from "http";
71620
72475
  function generateCodeVerifier() {
@@ -71695,7 +72550,7 @@ function openBrowser(url2) {
71695
72550
  args = [url2];
71696
72551
  }
71697
72552
  try {
71698
- const child = spawn2(command, args, { stdio: "ignore", detached: true });
72553
+ const child = spawn(command, args, { stdio: "ignore", detached: true });
71699
72554
  child.on("error", () => {});
71700
72555
  child.unref();
71701
72556
  } catch {}
@@ -71722,6 +72577,38 @@ async function runAuthorizationCodeRedirect(options) {
71722
72577
  }
71723
72578
 
71724
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
+
71725
72612
  class McpOAuthProvider {
71726
72613
  serverUrl;
71727
72614
  configClientId;
@@ -71816,33 +72703,34 @@ class McpOAuthProvider {
71816
72703
  ...metadata.resource ? { resource: metadata.resource } : {}
71817
72704
  }).toString()
71818
72705
  });
71819
- if (!tokenResponse.ok) {
71820
- let errorDetail = `${tokenResponse.status}`;
71821
- try {
71822
- const body = await tokenResponse.json();
71823
- if (body.error) {
71824
- errorDetail = `${tokenResponse.status} ${body.error}`;
71825
- if (body.error_description) {
71826
- errorDetail += `: ${body.error_description}`;
71827
- }
71828
- }
71829
- } catch {}
71830
- throw new Error(`Token exchange failed: ${errorDetail}`);
71831
- }
71832
- const tokenData = await tokenResponse.json();
71833
- const accessToken = tokenData.access_token;
71834
- if (typeof accessToken !== "string") {
71835
- 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.");
71836
72717
  }
71837
- const oauthTokenData = {
71838
- accessToken,
71839
- refreshToken: typeof tokenData.refresh_token === "string" ? tokenData.refresh_token : undefined,
71840
- expiresAt: typeof tokenData.expires_in === "number" ? Math.floor(Date.now() / 1000) + tokenData.expires_in : undefined,
71841
- clientInfo: {
71842
- clientId: clientInfo.clientId,
71843
- clientSecret: clientInfo.clientSecret
71844
- }
71845
- };
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);
71846
72734
  this.saveTokens(oauthTokenData);
71847
72735
  return oauthTokenData;
71848
72736
  }