oh-my-opencode 3.0.0-beta.8 → 3.0.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 (126) hide show
  1. package/README.ja.md +52 -811
  2. package/README.ko.md +377 -0
  3. package/README.md +61 -940
  4. package/README.zh-cn.md +53 -935
  5. package/dist/agents/atlas.d.ts +19 -0
  6. package/dist/agents/{sisyphus-prompt-builder.d.ts → dynamic-agent-prompt-builder.d.ts} +10 -6
  7. package/dist/agents/explore.d.ts +1 -2
  8. package/dist/agents/index.d.ts +9 -3
  9. package/dist/agents/librarian.d.ts +1 -2
  10. package/dist/agents/metis.d.ts +1 -2
  11. package/dist/agents/momus.d.ts +15 -3
  12. package/dist/agents/multimodal-looker.d.ts +1 -2
  13. package/dist/agents/oracle.d.ts +1 -2
  14. package/dist/agents/prometheus-prompt.d.ts +1 -1
  15. package/dist/agents/sisyphus-junior.d.ts +1 -2
  16. package/dist/agents/sisyphus.d.ts +2 -3
  17. package/dist/agents/types.d.ts +2 -2
  18. package/dist/agents/utils.d.ts +5 -4
  19. package/dist/cli/doctor/checks/dependencies.d.ts +1 -1
  20. package/dist/cli/doctor/checks/index.d.ts +1 -0
  21. package/dist/cli/doctor/checks/model-resolution.d.ts +33 -0
  22. package/dist/cli/doctor/checks/opencode.d.ts +5 -1
  23. package/dist/cli/doctor/constants.d.ts +1 -0
  24. package/dist/cli/index.js +988 -420
  25. package/dist/cli/model-fallback.d.ts +18 -0
  26. package/dist/cli/types.d.ts +9 -3
  27. package/dist/config/schema.d.ts +217 -421
  28. package/dist/features/background-agent/concurrency.d.ts +17 -0
  29. package/dist/features/background-agent/manager.d.ts +34 -5
  30. package/dist/features/background-agent/types.d.ts +7 -4
  31. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  32. package/dist/features/builtin-commands/templates/refactor.d.ts +1 -1
  33. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  34. package/dist/features/builtin-commands/types.d.ts +1 -1
  35. package/dist/features/claude-code-session-state/state.d.ts +2 -1
  36. package/dist/features/claude-code-session-state/state.test.d.ts +1 -0
  37. package/dist/features/context-injector/index.d.ts +1 -1
  38. package/dist/features/opencode-skill-loader/skill-content.d.ts +1 -0
  39. package/dist/features/skill-mcp-manager/manager.d.ts +1 -0
  40. package/dist/features/task-toast-manager/manager.d.ts +1 -0
  41. package/dist/features/task-toast-manager/types.d.ts +3 -0
  42. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  43. package/dist/hooks/anthropic-context-window-limit-recovery/executor.d.ts +1 -1
  44. package/dist/hooks/anthropic-context-window-limit-recovery/index.d.ts +1 -2
  45. package/dist/hooks/anthropic-context-window-limit-recovery/types.d.ts +0 -5
  46. package/dist/hooks/{sisyphus-orchestrator → atlas}/index.d.ts +3 -3
  47. package/dist/hooks/atlas/index.test.d.ts +1 -0
  48. package/dist/hooks/auto-update-checker/constants.d.ts +0 -3
  49. package/dist/hooks/compaction-context-injector/index.d.ts +7 -1
  50. package/dist/hooks/{sisyphus-task-retry → delegate-task-retry}/index.d.ts +4 -4
  51. package/dist/hooks/delegate-task-retry/index.test.d.ts +1 -0
  52. package/dist/hooks/index.d.ts +3 -5
  53. package/dist/hooks/prometheus-md-only/constants.d.ts +2 -1
  54. package/dist/hooks/question-label-truncator/index.d.ts +7 -0
  55. package/dist/hooks/question-label-truncator/index.test.d.ts +1 -0
  56. package/dist/hooks/ralph-loop/index.d.ts +1 -0
  57. package/dist/hooks/ralph-loop/types.d.ts +1 -0
  58. package/dist/index.js +13920 -14528
  59. package/dist/index.test.d.ts +1 -0
  60. package/dist/mcp/context7.d.ts +1 -0
  61. package/dist/mcp/grep-app.d.ts +1 -0
  62. package/dist/mcp/index.d.ts +1 -0
  63. package/dist/mcp/websearch.d.ts +1 -0
  64. package/dist/plugin-handlers/config-handler.d.ts +1 -0
  65. package/dist/shared/agent-config-integration.test.d.ts +1 -0
  66. package/dist/shared/agent-display-names.d.ts +12 -0
  67. package/dist/shared/agent-display-names.test.d.ts +1 -0
  68. package/dist/shared/agent-tool-restrictions.d.ts +7 -0
  69. package/dist/shared/case-insensitive.d.ts +24 -0
  70. package/dist/shared/case-insensitive.test.d.ts +1 -0
  71. package/dist/shared/config-path.d.ts +1 -5
  72. package/dist/shared/index.d.ts +6 -0
  73. package/dist/shared/migration.d.ts +15 -1
  74. package/dist/shared/model-availability.d.ts +8 -0
  75. package/dist/shared/model-availability.test.d.ts +1 -0
  76. package/dist/shared/model-requirements.d.ts +11 -0
  77. package/dist/shared/model-requirements.test.d.ts +1 -0
  78. package/dist/shared/model-resolver.d.ts +20 -0
  79. package/dist/shared/model-resolver.test.d.ts +1 -0
  80. package/dist/shared/opencode-version.d.ts +6 -3
  81. package/dist/shared/permission-compat.d.ts +22 -9
  82. package/dist/shared/system-directive.d.ts +31 -0
  83. package/dist/tools/delegate-task/constants.d.ts +11 -0
  84. package/dist/tools/{sisyphus-task → delegate-task}/index.d.ts +1 -1
  85. package/dist/tools/{sisyphus-task → delegate-task}/tools.d.ts +13 -3
  86. package/dist/tools/delegate-task/tools.test.d.ts +1 -0
  87. package/dist/tools/{sisyphus-task → delegate-task}/types.d.ts +2 -2
  88. package/dist/tools/index.d.ts +1 -1
  89. package/dist/tools/interactive-bash/constants.d.ts +1 -1
  90. package/dist/tools/lsp/client.d.ts +4 -0
  91. package/dist/tools/lsp/config.test.d.ts +1 -0
  92. package/dist/tools/lsp/constants.d.ts +3 -0
  93. package/dist/tools/lsp/index.d.ts +1 -1
  94. package/dist/tools/lsp/tools.d.ts +3 -1
  95. package/dist/tools/lsp/types.d.ts +23 -0
  96. package/dist/tools/lsp/utils.d.ts +5 -1
  97. package/dist/tools/skill/types.d.ts +4 -1
  98. package/package.json +8 -12
  99. package/dist/agents/build-prompt.d.ts +0 -31
  100. package/dist/agents/document-writer.d.ts +0 -5
  101. package/dist/agents/frontend-ui-ux-engineer.d.ts +0 -5
  102. package/dist/agents/orchestrator-sisyphus.d.ts +0 -20
  103. package/dist/agents/plan-prompt.d.ts +0 -64
  104. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-executor.d.ts +0 -3
  105. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-purge-errors.d.ts +0 -7
  106. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-storage.d.ts +0 -2
  107. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-supersede.d.ts +0 -6
  108. package/dist/hooks/comment-checker/constants.d.ts +0 -3
  109. package/dist/hooks/comment-checker/filters/bdd.d.ts +0 -2
  110. package/dist/hooks/comment-checker/filters/directive.d.ts +0 -2
  111. package/dist/hooks/comment-checker/filters/docstring.d.ts +0 -2
  112. package/dist/hooks/comment-checker/filters/index.d.ts +0 -7
  113. package/dist/hooks/comment-checker/filters/shebang.d.ts +0 -2
  114. package/dist/hooks/comment-checker/output/formatter.d.ts +0 -2
  115. package/dist/hooks/comment-checker/output/index.d.ts +0 -2
  116. package/dist/hooks/comment-checker/output/xml-builder.d.ts +0 -2
  117. package/dist/hooks/empty-message-sanitizer/index.d.ts +0 -12
  118. package/dist/hooks/preemptive-compaction/constants.d.ts +0 -3
  119. package/dist/hooks/preemptive-compaction/index.d.ts +0 -24
  120. package/dist/hooks/preemptive-compaction/types.d.ts +0 -17
  121. package/dist/tools/ast-grep/napi.d.ts +0 -13
  122. package/dist/tools/interactive-bash/types.d.ts +0 -3
  123. package/dist/tools/sisyphus-task/constants.d.ts +0 -12
  124. /package/dist/{hooks/sisyphus-orchestrator/index.test.d.ts → cli/doctor/checks/model-resolution.test.d.ts} +0 -0
  125. /package/dist/{hooks/sisyphus-task-retry/index.test.d.ts → cli/install.test.d.ts} +0 -0
  126. /package/dist/{tools/sisyphus-task/tools.test.d.ts → cli/model-fallback.test.d.ts} +0 -0
package/dist/cli/index.js CHANGED
@@ -4917,6 +4917,11 @@ var init_dynamic_truncator = __esm(() => {
4917
4917
  var init_config_path = () => {};
4918
4918
 
4919
4919
  // src/shared/data-path.ts
4920
+ import * as path2 from "path";
4921
+ import * as os2 from "os";
4922
+ function getDataDir() {
4923
+ return process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
4924
+ }
4920
4925
  var init_data_path = () => {};
4921
4926
 
4922
4927
  // src/shared/config-errors.ts
@@ -5832,25 +5837,23 @@ var BUILTIN_AGENT_NAMES;
5832
5837
  var init_migration = __esm(() => {
5833
5838
  init_logger();
5834
5839
  BUILTIN_AGENT_NAMES = new Set([
5835
- "Sisyphus",
5840
+ "sisyphus",
5836
5841
  "oracle",
5837
5842
  "librarian",
5838
5843
  "explore",
5839
- "frontend-ui-ux-engineer",
5840
- "document-writer",
5841
5844
  "multimodal-looker",
5842
- "Metis (Plan Consultant)",
5843
- "Momus (Plan Reviewer)",
5844
- "Prometheus (Planner)",
5845
- "orchestrator-sisyphus",
5845
+ "metis",
5846
+ "momus",
5847
+ "prometheus",
5848
+ "atlas",
5846
5849
  "build"
5847
5850
  ]);
5848
5851
  });
5849
5852
 
5850
5853
  // src/shared/opencode-config-dir.ts
5851
5854
  import { existsSync as existsSync2 } from "fs";
5852
- import { homedir } from "os";
5853
- import { join as join2, resolve } from "path";
5855
+ import { homedir as homedir2 } from "os";
5856
+ import { join as join3, resolve } from "path";
5854
5857
  function isDevBuild(version) {
5855
5858
  if (!version)
5856
5859
  return false;
@@ -5860,15 +5863,15 @@ function getTauriConfigDir(identifier) {
5860
5863
  const platform = process.platform;
5861
5864
  switch (platform) {
5862
5865
  case "darwin":
5863
- return join2(homedir(), "Library", "Application Support", identifier);
5866
+ return join3(homedir2(), "Library", "Application Support", identifier);
5864
5867
  case "win32": {
5865
- const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
5866
- return join2(appData, identifier);
5868
+ const appData = process.env.APPDATA || join3(homedir2(), "AppData", "Roaming");
5869
+ return join3(appData, identifier);
5867
5870
  }
5868
5871
  case "linux":
5869
5872
  default: {
5870
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
5871
- return join2(xdgConfig, identifier);
5873
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
5874
+ return join3(xdgConfig, identifier);
5872
5875
  }
5873
5876
  }
5874
5877
  }
@@ -5878,21 +5881,21 @@ function getCliConfigDir() {
5878
5881
  return resolve(envConfigDir);
5879
5882
  }
5880
5883
  if (process.platform === "win32") {
5881
- const crossPlatformDir = join2(homedir(), ".config", "opencode");
5882
- const crossPlatformConfig = join2(crossPlatformDir, "opencode.json");
5884
+ const crossPlatformDir = join3(homedir2(), ".config", "opencode");
5885
+ const crossPlatformConfig = join3(crossPlatformDir, "opencode.json");
5883
5886
  if (existsSync2(crossPlatformConfig)) {
5884
5887
  return crossPlatformDir;
5885
5888
  }
5886
- const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
5887
- const appdataDir = join2(appData, "opencode");
5888
- const appdataConfig = join2(appdataDir, "opencode.json");
5889
+ const appData = process.env.APPDATA || join3(homedir2(), "AppData", "Roaming");
5890
+ const appdataDir = join3(appData, "opencode");
5891
+ const appdataConfig = join3(appdataDir, "opencode.json");
5889
5892
  if (existsSync2(appdataConfig)) {
5890
5893
  return appdataDir;
5891
5894
  }
5892
5895
  return crossPlatformDir;
5893
5896
  }
5894
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
5895
- return join2(xdgConfig, "opencode");
5897
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
5898
+ return join3(xdgConfig, "opencode");
5896
5899
  }
5897
5900
  function getOpenCodeConfigDir(options) {
5898
5901
  const { binary: binary2, version, checkExisting = true } = options;
@@ -5903,8 +5906,8 @@ function getOpenCodeConfigDir(options) {
5903
5906
  const tauriDir = getTauriConfigDir(identifier);
5904
5907
  if (checkExisting) {
5905
5908
  const legacyDir = getCliConfigDir();
5906
- const legacyConfig = join2(legacyDir, "opencode.json");
5907
- const legacyConfigC = join2(legacyDir, "opencode.jsonc");
5909
+ const legacyConfig = join3(legacyDir, "opencode.json");
5910
+ const legacyConfigC = join3(legacyDir, "opencode.jsonc");
5908
5911
  if (existsSync2(legacyConfig) || existsSync2(legacyConfigC)) {
5909
5912
  return legacyDir;
5910
5913
  }
@@ -5915,10 +5918,10 @@ function getOpenCodeConfigPaths(options) {
5915
5918
  const configDir = getOpenCodeConfigDir(options);
5916
5919
  return {
5917
5920
  configDir,
5918
- configJson: join2(configDir, "opencode.json"),
5919
- configJsonc: join2(configDir, "opencode.jsonc"),
5920
- packageJson: join2(configDir, "package.json"),
5921
- omoConfig: join2(configDir, "oh-my-opencode.json")
5921
+ configJson: join3(configDir, "opencode.json"),
5922
+ configJsonc: join3(configDir, "opencode.jsonc"),
5923
+ packageJson: join3(configDir, "package.json"),
5924
+ omoConfig: join3(configDir, "oh-my-opencode.json")
5922
5925
  };
5923
5926
  }
5924
5927
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
@@ -5929,12 +5932,6 @@ var NOT_CACHED;
5929
5932
  var init_opencode_version = __esm(() => {
5930
5933
  NOT_CACHED = Symbol("NOT_CACHED");
5931
5934
  });
5932
-
5933
- // src/shared/permission-compat.ts
5934
- var init_permission_compat = __esm(() => {
5935
- init_opencode_version();
5936
- });
5937
-
5938
5935
  // src/shared/external-plugin-detector.ts
5939
5936
  var init_external_plugin_detector = __esm(() => {
5940
5937
  init_logger();
@@ -5943,11 +5940,168 @@ var init_external_plugin_detector = __esm(() => {
5943
5940
 
5944
5941
  // src/shared/zip-extractor.ts
5945
5942
  var init_zip_extractor = () => {};
5943
+ // src/shared/agent-variant.ts
5944
+ var init_agent_variant = () => {};
5945
+
5946
5946
  // src/shared/session-cursor.ts
5947
5947
  var sessionCursors;
5948
5948
  var init_session_cursor = __esm(() => {
5949
5949
  sessionCursors = new Map;
5950
5950
  });
5951
+ // src/shared/system-directive.ts
5952
+ var init_system_directive = () => {};
5953
+
5954
+ // src/shared/agent-tool-restrictions.ts
5955
+ var init_agent_tool_restrictions = () => {};
5956
+
5957
+ // src/shared/model-requirements.ts
5958
+ var AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS;
5959
+ var init_model_requirements = __esm(() => {
5960
+ AGENT_MODEL_REQUIREMENTS = {
5961
+ sisyphus: {
5962
+ fallbackChain: [
5963
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
5964
+ { providers: ["zai-coding-plan"], model: "glm-4.7" },
5965
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
5966
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
5967
+ ]
5968
+ },
5969
+ oracle: {
5970
+ fallbackChain: [
5971
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
5972
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
5973
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
5974
+ ]
5975
+ },
5976
+ librarian: {
5977
+ fallbackChain: [
5978
+ { providers: ["zai-coding-plan"], model: "glm-4.7" },
5979
+ { providers: ["opencode"], model: "big-pickle" },
5980
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }
5981
+ ]
5982
+ },
5983
+ explore: {
5984
+ fallbackChain: [
5985
+ { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
5986
+ { providers: ["opencode"], model: "gpt-5-nano" }
5987
+ ]
5988
+ },
5989
+ "multimodal-looker": {
5990
+ fallbackChain: [
5991
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
5992
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
5993
+ { providers: ["zai-coding-plan"], model: "glm-4.6v" },
5994
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
5995
+ { providers: ["opencode"], model: "gpt-5-nano" }
5996
+ ]
5997
+ },
5998
+ prometheus: {
5999
+ fallbackChain: [
6000
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6001
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6002
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6003
+ ]
6004
+ },
6005
+ metis: {
6006
+ fallbackChain: [
6007
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6008
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6009
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
6010
+ ]
6011
+ },
6012
+ momus: {
6013
+ fallbackChain: [
6014
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" },
6015
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" },
6016
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
6017
+ ]
6018
+ },
6019
+ atlas: {
6020
+ fallbackChain: [
6021
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6022
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
6023
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6024
+ ]
6025
+ }
6026
+ };
6027
+ CATEGORY_MODEL_REQUIREMENTS = {
6028
+ "visual-engineering": {
6029
+ fallbackChain: [
6030
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },
6031
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6032
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }
6033
+ ]
6034
+ },
6035
+ ultrabrain: {
6036
+ fallbackChain: [
6037
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
6038
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6039
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6040
+ ]
6041
+ },
6042
+ artistry: {
6043
+ fallbackChain: [
6044
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
6045
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6046
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
6047
+ ]
6048
+ },
6049
+ quick: {
6050
+ fallbackChain: [
6051
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
6052
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
6053
+ { providers: ["opencode"], model: "gpt-5-nano" }
6054
+ ]
6055
+ },
6056
+ "unspecified-low": {
6057
+ fallbackChain: [
6058
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6059
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
6060
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }
6061
+ ]
6062
+ },
6063
+ "unspecified-high": {
6064
+ fallbackChain: [
6065
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6066
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6067
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6068
+ ]
6069
+ },
6070
+ writing: {
6071
+ fallbackChain: [
6072
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
6073
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6074
+ { providers: ["zai-coding-plan"], model: "glm-4.7" },
6075
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
6076
+ ]
6077
+ }
6078
+ };
6079
+ });
6080
+
6081
+ // src/shared/model-availability.ts
6082
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
6083
+ import { homedir as homedir3 } from "os";
6084
+ import { join as join4 } from "path";
6085
+ function getOpenCodeCacheDir() {
6086
+ const xdgCache = process.env.XDG_CACHE_HOME;
6087
+ if (xdgCache)
6088
+ return join4(xdgCache, "opencode");
6089
+ return join4(homedir3(), ".cache", "opencode");
6090
+ }
6091
+ function isModelCacheAvailable() {
6092
+ const cacheFile = join4(getOpenCodeCacheDir(), "models.json");
6093
+ return existsSync3(cacheFile);
6094
+ }
6095
+ var init_model_availability = __esm(() => {
6096
+ init_logger();
6097
+ });
6098
+
6099
+ // src/shared/model-resolver.ts
6100
+ var init_model_resolver = __esm(() => {
6101
+ init_logger();
6102
+ init_model_availability();
6103
+ });
6104
+
5951
6105
  // src/shared/index.ts
5952
6106
  var init_shared = __esm(() => {
5953
6107
  init_frontmatter();
@@ -5967,14 +6121,131 @@ var init_shared = __esm(() => {
5967
6121
  init_migration();
5968
6122
  init_opencode_config_dir();
5969
6123
  init_opencode_version();
5970
- init_permission_compat();
5971
6124
  init_external_plugin_detector();
5972
6125
  init_zip_extractor();
6126
+ init_agent_variant();
5973
6127
  init_session_cursor();
6128
+ init_system_directive();
6129
+ init_agent_tool_restrictions();
6130
+ init_model_requirements();
6131
+ init_model_resolver();
6132
+ init_model_availability();
6133
+ });
6134
+
6135
+ // src/cli/model-fallback.ts
6136
+ function toProviderAvailability(config) {
6137
+ return {
6138
+ native: {
6139
+ claude: config.hasClaude,
6140
+ openai: config.hasOpenAI,
6141
+ gemini: config.hasGemini
6142
+ },
6143
+ opencodeZen: config.hasOpencodeZen,
6144
+ copilot: config.hasCopilot,
6145
+ zai: config.hasZaiCodingPlan,
6146
+ isMaxPlan: config.isMax20
6147
+ };
6148
+ }
6149
+ function isProviderAvailable(provider, avail) {
6150
+ const mapping = {
6151
+ anthropic: avail.native.claude,
6152
+ openai: avail.native.openai,
6153
+ google: avail.native.gemini,
6154
+ "github-copilot": avail.copilot,
6155
+ opencode: avail.opencodeZen,
6156
+ "zai-coding-plan": avail.zai
6157
+ };
6158
+ return mapping[provider] ?? false;
6159
+ }
6160
+ function transformModelForProvider(provider, model) {
6161
+ if (provider === "github-copilot") {
6162
+ return model.replace("claude-opus-4-5", "claude-opus-4.5").replace("claude-sonnet-4-5", "claude-sonnet-4.5").replace("claude-haiku-4-5", "claude-haiku-4.5").replace("claude-sonnet-4", "claude-sonnet-4");
6163
+ }
6164
+ return model;
6165
+ }
6166
+ function resolveModelFromChain(fallbackChain, avail) {
6167
+ for (const entry of fallbackChain) {
6168
+ for (const provider of entry.providers) {
6169
+ if (isProviderAvailable(provider, avail)) {
6170
+ const transformedModel = transformModelForProvider(provider, entry.model);
6171
+ return {
6172
+ model: `${provider}/${transformedModel}`,
6173
+ variant: entry.variant
6174
+ };
6175
+ }
6176
+ }
6177
+ }
6178
+ return null;
6179
+ }
6180
+ function getSisyphusFallbackChain(isMaxPlan) {
6181
+ if (isMaxPlan) {
6182
+ return AGENT_MODEL_REQUIREMENTS.sisyphus.fallbackChain;
6183
+ }
6184
+ return [
6185
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6186
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6187
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6188
+ ];
6189
+ }
6190
+ function generateModelConfig(config) {
6191
+ const avail = toProviderAvailability(config);
6192
+ const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai;
6193
+ if (!hasAnyProvider) {
6194
+ return {
6195
+ $schema: SCHEMA_URL,
6196
+ agents: Object.fromEntries(Object.keys(AGENT_MODEL_REQUIREMENTS).map((role) => [role, { model: ULTIMATE_FALLBACK }])),
6197
+ categories: Object.fromEntries(Object.keys(CATEGORY_MODEL_REQUIREMENTS).map((cat) => [cat, { model: ULTIMATE_FALLBACK }]))
6198
+ };
6199
+ }
6200
+ const agents = {};
6201
+ const categories = {};
6202
+ for (const [role, req] of Object.entries(AGENT_MODEL_REQUIREMENTS)) {
6203
+ if (role === "librarian" && avail.zai) {
6204
+ agents[role] = { model: ZAI_MODEL };
6205
+ continue;
6206
+ }
6207
+ if (role === "explore") {
6208
+ if (avail.native.claude) {
6209
+ agents[role] = { model: "anthropic/claude-haiku-4-5" };
6210
+ } else if (avail.opencodeZen) {
6211
+ agents[role] = { model: "opencode/claude-haiku-4-5" };
6212
+ } else {
6213
+ agents[role] = { model: "opencode/gpt-5-nano" };
6214
+ }
6215
+ continue;
6216
+ }
6217
+ const fallbackChain = role === "sisyphus" ? getSisyphusFallbackChain(avail.isMaxPlan) : req.fallbackChain;
6218
+ const resolved = resolveModelFromChain(fallbackChain, avail);
6219
+ if (resolved) {
6220
+ const variant = resolved.variant ?? req.variant;
6221
+ agents[role] = variant ? { model: resolved.model, variant } : { model: resolved.model };
6222
+ } else {
6223
+ agents[role] = { model: ULTIMATE_FALLBACK };
6224
+ }
6225
+ }
6226
+ for (const [cat, req] of Object.entries(CATEGORY_MODEL_REQUIREMENTS)) {
6227
+ const fallbackChain = cat === "unspecified-high" && !avail.isMaxPlan ? CATEGORY_MODEL_REQUIREMENTS["unspecified-low"].fallbackChain : req.fallbackChain;
6228
+ const resolved = resolveModelFromChain(fallbackChain, avail);
6229
+ if (resolved) {
6230
+ const variant = resolved.variant ?? req.variant;
6231
+ categories[cat] = variant ? { model: resolved.model, variant } : { model: resolved.model };
6232
+ } else {
6233
+ categories[cat] = { model: ULTIMATE_FALLBACK };
6234
+ }
6235
+ }
6236
+ return {
6237
+ $schema: SCHEMA_URL,
6238
+ agents,
6239
+ categories
6240
+ };
6241
+ }
6242
+ var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/big-pickle", SCHEMA_URL = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json";
6243
+ var init_model_fallback = __esm(() => {
6244
+ init_model_requirements();
5974
6245
  });
5975
6246
 
5976
6247
  // src/cli/config-manager.ts
5977
- import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, writeFileSync, statSync } from "fs";
6248
+ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3, writeFileSync, statSync } from "fs";
5978
6249
  function initConfigContext(binary2, version) {
5979
6250
  const paths = getOpenCodeConfigPaths({ binary: binary2, version });
5980
6251
  configContext = { binary: binary2, version, paths };
@@ -6064,10 +6335,10 @@ async function getPluginNameWithVersion(currentVersion) {
6064
6335
  function detectConfigFormat() {
6065
6336
  const configJsonc = getConfigJsonc();
6066
6337
  const configJson = getConfigJson();
6067
- if (existsSync3(configJsonc)) {
6338
+ if (existsSync4(configJsonc)) {
6068
6339
  return { format: "jsonc", path: configJsonc };
6069
6340
  }
6070
- if (existsSync3(configJson)) {
6341
+ if (existsSync4(configJson)) {
6071
6342
  return { format: "json", path: configJson };
6072
6343
  }
6073
6344
  return { format: "none", path: configJson };
@@ -6075,31 +6346,31 @@ function detectConfigFormat() {
6075
6346
  function isEmptyOrWhitespace(content) {
6076
6347
  return content.trim().length === 0;
6077
6348
  }
6078
- function parseConfigWithError(path2) {
6349
+ function parseConfigWithError(path3) {
6079
6350
  try {
6080
- const stat = statSync(path2);
6351
+ const stat = statSync(path3);
6081
6352
  if (stat.size === 0) {
6082
- return { config: null, error: `Config file is empty: ${path2}. Delete it or add valid JSON content.` };
6353
+ return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
6083
6354
  }
6084
- const content = readFileSync2(path2, "utf-8");
6355
+ const content = readFileSync3(path3, "utf-8");
6085
6356
  if (isEmptyOrWhitespace(content)) {
6086
- return { config: null, error: `Config file contains only whitespace: ${path2}. Delete it or add valid JSON content.` };
6357
+ return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
6087
6358
  }
6088
6359
  const config = parseJsonc(content);
6089
6360
  if (config === null || config === undefined) {
6090
- return { config: null, error: `Config file parsed to null/undefined: ${path2}. Ensure it contains valid JSON.` };
6361
+ return { config: null, error: `Config file parsed to null/undefined: ${path3}. Ensure it contains valid JSON.` };
6091
6362
  }
6092
6363
  if (typeof config !== "object" || Array.isArray(config)) {
6093
- return { config: null, error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path2}` };
6364
+ return { config: null, error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path3}` };
6094
6365
  }
6095
6366
  return { config };
6096
6367
  } catch (err) {
6097
- return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path2}`) };
6368
+ return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path3}`) };
6098
6369
  }
6099
6370
  }
6100
6371
  function ensureConfigDir() {
6101
6372
  const configDir = getConfigDir();
6102
- if (!existsSync3(configDir)) {
6373
+ if (!existsSync4(configDir)) {
6103
6374
  mkdirSync(configDir, { recursive: true });
6104
6375
  }
6105
6376
  }
@@ -6109,25 +6380,25 @@ async function addPluginToOpenCodeConfig(currentVersion) {
6109
6380
  } catch (err) {
6110
6381
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6111
6382
  }
6112
- const { format: format2, path: path2 } = detectConfigFormat();
6383
+ const { format: format2, path: path3 } = detectConfigFormat();
6113
6384
  const pluginEntry = await getPluginNameWithVersion(currentVersion);
6114
6385
  try {
6115
6386
  if (format2 === "none") {
6116
6387
  const config2 = { plugin: [pluginEntry] };
6117
- writeFileSync(path2, JSON.stringify(config2, null, 2) + `
6388
+ writeFileSync(path3, JSON.stringify(config2, null, 2) + `
6118
6389
  `);
6119
- return { success: true, configPath: path2 };
6390
+ return { success: true, configPath: path3 };
6120
6391
  }
6121
- const parseResult = parseConfigWithError(path2);
6392
+ const parseResult = parseConfigWithError(path3);
6122
6393
  if (!parseResult.config) {
6123
- return { success: false, configPath: path2, error: parseResult.error ?? "Failed to parse config file" };
6394
+ return { success: false, configPath: path3, error: parseResult.error ?? "Failed to parse config file" };
6124
6395
  }
6125
6396
  const config = parseResult.config;
6126
6397
  const plugins = config.plugin ?? [];
6127
6398
  const existingIndex = plugins.findIndex((p2) => p2 === PACKAGE_NAME || p2.startsWith(`${PACKAGE_NAME}@`));
6128
6399
  if (existingIndex !== -1) {
6129
6400
  if (plugins[existingIndex] === pluginEntry) {
6130
- return { success: true, configPath: path2 };
6401
+ return { success: true, configPath: path3 };
6131
6402
  }
6132
6403
  plugins[existingIndex] = pluginEntry;
6133
6404
  } else {
@@ -6135,7 +6406,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
6135
6406
  }
6136
6407
  config.plugin = plugins;
6137
6408
  if (format2 === "jsonc") {
6138
- const content = readFileSync2(path2, "utf-8");
6409
+ const content = readFileSync3(path3, "utf-8");
6139
6410
  const pluginArrayRegex = /"plugin"\s*:\s*\[([\s\S]*?)\]/;
6140
6411
  const match = content.match(pluginArrayRegex);
6141
6412
  if (match) {
@@ -6144,19 +6415,19 @@ async function addPluginToOpenCodeConfig(currentVersion) {
6144
6415
  const newContent = content.replace(pluginArrayRegex, `"plugin": [
6145
6416
  ${formattedPlugins}
6146
6417
  ]`);
6147
- writeFileSync(path2, newContent);
6418
+ writeFileSync(path3, newContent);
6148
6419
  } else {
6149
6420
  const newContent = content.replace(/^(\s*\{)/, `$1
6150
6421
  "plugin": ["${pluginEntry}"],`);
6151
- writeFileSync(path2, newContent);
6422
+ writeFileSync(path3, newContent);
6152
6423
  }
6153
6424
  } else {
6154
- writeFileSync(path2, JSON.stringify(config, null, 2) + `
6425
+ writeFileSync(path3, JSON.stringify(config, null, 2) + `
6155
6426
  `);
6156
6427
  }
6157
- return { success: true, configPath: path2 };
6428
+ return { success: true, configPath: path3 };
6158
6429
  } catch (err) {
6159
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "update opencode config") };
6430
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "update opencode config") };
6160
6431
  }
6161
6432
  }
6162
6433
  function deepMerge(target, source) {
@@ -6173,63 +6444,7 @@ function deepMerge(target, source) {
6173
6444
  return result;
6174
6445
  }
6175
6446
  function generateOmoConfig(installConfig) {
6176
- const config = {
6177
- $schema: "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json"
6178
- };
6179
- const agents = {};
6180
- if (!installConfig.hasClaude) {
6181
- agents["Sisyphus"] = {
6182
- model: installConfig.hasCopilot ? "github-copilot/claude-opus-4.5" : "opencode/glm-4.7-free"
6183
- };
6184
- }
6185
- agents["librarian"] = { model: "opencode/glm-4.7-free" };
6186
- if (installConfig.hasGemini) {
6187
- agents["explore"] = { model: "google/antigravity-gemini-3-flash" };
6188
- } else if (installConfig.hasClaude && installConfig.isMax20) {
6189
- agents["explore"] = { model: "anthropic/claude-haiku-4-5" };
6190
- } else if (installConfig.hasCopilot) {
6191
- agents["explore"] = { model: "github-copilot/grok-code-fast-1" };
6192
- } else {
6193
- agents["explore"] = { model: "opencode/glm-4.7-free" };
6194
- }
6195
- if (!installConfig.hasChatGPT) {
6196
- const oracleFallback = installConfig.hasCopilot ? "github-copilot/gpt-5.2" : installConfig.hasClaude ? "anthropic/claude-opus-4-5" : "opencode/glm-4.7-free";
6197
- agents["oracle"] = { model: oracleFallback };
6198
- }
6199
- if (installConfig.hasGemini) {
6200
- agents["frontend-ui-ux-engineer"] = { model: "google/antigravity-gemini-3-pro-high" };
6201
- agents["document-writer"] = { model: "google/antigravity-gemini-3-flash" };
6202
- agents["multimodal-looker"] = { model: "google/antigravity-gemini-3-flash" };
6203
- } else if (installConfig.hasClaude) {
6204
- agents["frontend-ui-ux-engineer"] = { model: "anthropic/claude-opus-4-5" };
6205
- agents["document-writer"] = { model: "anthropic/claude-opus-4-5" };
6206
- agents["multimodal-looker"] = { model: "anthropic/claude-opus-4-5" };
6207
- } else if (installConfig.hasCopilot) {
6208
- agents["frontend-ui-ux-engineer"] = { model: "github-copilot/gemini-3-pro-preview" };
6209
- agents["document-writer"] = { model: "github-copilot/gemini-3-flash-preview" };
6210
- agents["multimodal-looker"] = { model: "github-copilot/gemini-3-flash-preview" };
6211
- } else {
6212
- agents["frontend-ui-ux-engineer"] = { model: "opencode/glm-4.7-free" };
6213
- agents["document-writer"] = { model: "opencode/glm-4.7-free" };
6214
- agents["multimodal-looker"] = { model: "opencode/glm-4.7-free" };
6215
- }
6216
- if (Object.keys(agents).length > 0) {
6217
- config.agents = agents;
6218
- }
6219
- if (installConfig.hasGemini) {
6220
- config.categories = {
6221
- "visual-engineering": { model: "google/gemini-3-pro-high" },
6222
- artistry: { model: "google/gemini-3-pro-high" },
6223
- writing: { model: "google/gemini-3-flash-high" }
6224
- };
6225
- } else if (installConfig.hasCopilot) {
6226
- config.categories = {
6227
- "visual-engineering": { model: "github-copilot/gemini-3-pro-preview" },
6228
- artistry: { model: "github-copilot/gemini-3-pro-preview" },
6229
- writing: { model: "github-copilot/gemini-3-flash-preview" }
6230
- };
6231
- }
6232
- return config;
6447
+ return generateModelConfig(installConfig);
6233
6448
  }
6234
6449
  function writeOmoConfig(installConfig) {
6235
6450
  try {
@@ -6240,10 +6455,10 @@ function writeOmoConfig(installConfig) {
6240
6455
  const omoConfigPath = getOmoConfig();
6241
6456
  try {
6242
6457
  const newConfig = generateOmoConfig(installConfig);
6243
- if (existsSync3(omoConfigPath)) {
6458
+ if (existsSync4(omoConfigPath)) {
6244
6459
  try {
6245
6460
  const stat = statSync(omoConfigPath);
6246
- const content = readFileSync2(omoConfigPath, "utf-8");
6461
+ const content = readFileSync3(omoConfigPath, "utf-8");
6247
6462
  if (stat.size === 0 || isEmptyOrWhitespace(content)) {
6248
6463
  writeFileSync(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
6249
6464
  `);
@@ -6309,11 +6524,11 @@ async function addAuthPlugins(config) {
6309
6524
  } catch (err) {
6310
6525
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6311
6526
  }
6312
- const { format: format2, path: path2 } = detectConfigFormat();
6527
+ const { format: format2, path: path3 } = detectConfigFormat();
6313
6528
  try {
6314
6529
  let existingConfig = null;
6315
6530
  if (format2 !== "none") {
6316
- const parseResult = parseConfigWithError(path2);
6531
+ const parseResult = parseConfigWithError(path3);
6317
6532
  if (parseResult.error && !parseResult.config) {
6318
6533
  existingConfig = {};
6319
6534
  } else {
@@ -6329,11 +6544,11 @@ async function addAuthPlugins(config) {
6329
6544
  }
6330
6545
  }
6331
6546
  const newConfig = { ...existingConfig ?? {}, plugin: plugins };
6332
- writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
6547
+ writeFileSync(path3, JSON.stringify(newConfig, null, 2) + `
6333
6548
  `);
6334
- return { success: true, configPath: path2 };
6549
+ return { success: true, configPath: path3 };
6335
6550
  } catch (err) {
6336
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "add auth plugins to config") };
6551
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "add auth plugins to config") };
6337
6552
  }
6338
6553
  }
6339
6554
  async function runBunInstall() {
@@ -6382,11 +6597,11 @@ function addProviderConfig(config) {
6382
6597
  } catch (err) {
6383
6598
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6384
6599
  }
6385
- const { format: format2, path: path2 } = detectConfigFormat();
6600
+ const { format: format2, path: path3 } = detectConfigFormat();
6386
6601
  try {
6387
6602
  let existingConfig = null;
6388
6603
  if (format2 !== "none") {
6389
- const parseResult = parseConfigWithError(path2);
6604
+ const parseResult = parseConfigWithError(path3);
6390
6605
  if (parseResult.error && !parseResult.config) {
6391
6606
  existingConfig = {};
6392
6607
  } else {
@@ -6401,11 +6616,31 @@ function addProviderConfig(config) {
6401
6616
  if (Object.keys(providers).length > 0) {
6402
6617
  newConfig.provider = providers;
6403
6618
  }
6404
- writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
6619
+ writeFileSync(path3, JSON.stringify(newConfig, null, 2) + `
6405
6620
  `);
6406
- return { success: true, configPath: path2 };
6621
+ return { success: true, configPath: path3 };
6407
6622
  } catch (err) {
6408
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "add provider config") };
6623
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "add provider config") };
6624
+ }
6625
+ }
6626
+ function detectProvidersFromOmoConfig() {
6627
+ const omoConfigPath = getOmoConfig();
6628
+ if (!existsSync4(omoConfigPath)) {
6629
+ return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false };
6630
+ }
6631
+ try {
6632
+ const content = readFileSync3(omoConfigPath, "utf-8");
6633
+ const omoConfig = parseJsonc(content);
6634
+ if (!omoConfig || typeof omoConfig !== "object") {
6635
+ return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false };
6636
+ }
6637
+ const configStr = JSON.stringify(omoConfig);
6638
+ const hasOpenAI = configStr.includes('"openai/');
6639
+ const hasOpencodeZen = configStr.includes('"opencode/');
6640
+ const hasZaiCodingPlan = configStr.includes('"zai-coding-plan/');
6641
+ return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan };
6642
+ } catch {
6643
+ return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false };
6409
6644
  }
6410
6645
  }
6411
6646
  function detectCurrentConfig() {
@@ -6413,15 +6648,17 @@ function detectCurrentConfig() {
6413
6648
  isInstalled: false,
6414
6649
  hasClaude: true,
6415
6650
  isMax20: true,
6416
- hasChatGPT: true,
6651
+ hasOpenAI: true,
6417
6652
  hasGemini: false,
6418
- hasCopilot: false
6653
+ hasCopilot: false,
6654
+ hasOpencodeZen: true,
6655
+ hasZaiCodingPlan: false
6419
6656
  };
6420
- const { format: format2, path: path2 } = detectConfigFormat();
6657
+ const { format: format2, path: path3 } = detectConfigFormat();
6421
6658
  if (format2 === "none") {
6422
6659
  return result;
6423
6660
  }
6424
- const parseResult = parseConfigWithError(path2);
6661
+ const parseResult = parseConfigWithError(path3);
6425
6662
  if (!parseResult.config) {
6426
6663
  return result;
6427
6664
  }
@@ -6432,44 +6669,16 @@ function detectCurrentConfig() {
6432
6669
  return result;
6433
6670
  }
6434
6671
  result.hasGemini = plugins.some((p2) => p2.startsWith("opencode-antigravity-auth"));
6435
- const omoConfigPath = getOmoConfig();
6436
- if (!existsSync3(omoConfigPath)) {
6437
- return result;
6438
- }
6439
- try {
6440
- const stat = statSync(omoConfigPath);
6441
- if (stat.size === 0) {
6442
- return result;
6443
- }
6444
- const content = readFileSync2(omoConfigPath, "utf-8");
6445
- if (isEmptyOrWhitespace(content)) {
6446
- return result;
6447
- }
6448
- const omoConfig = parseJsonc(content);
6449
- if (!omoConfig || typeof omoConfig !== "object") {
6450
- return result;
6451
- }
6452
- const agents = omoConfig.agents ?? {};
6453
- if (agents["Sisyphus"]?.model === "opencode/glm-4.7-free") {
6454
- result.hasClaude = false;
6455
- result.isMax20 = false;
6456
- } else if (agents["librarian"]?.model === "opencode/glm-4.7-free") {
6457
- result.hasClaude = true;
6458
- result.isMax20 = false;
6459
- }
6460
- if (agents["oracle"]?.model?.startsWith("anthropic/")) {
6461
- result.hasChatGPT = false;
6462
- } else if (agents["oracle"]?.model === "opencode/glm-4.7-free") {
6463
- result.hasChatGPT = false;
6464
- }
6465
- const hasAnyCopilotModel = Object.values(agents).some((agent) => agent?.model?.startsWith("github-copilot/"));
6466
- result.hasCopilot = hasAnyCopilotModel;
6467
- } catch {}
6672
+ const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan } = detectProvidersFromOmoConfig();
6673
+ result.hasOpenAI = hasOpenAI;
6674
+ result.hasOpencodeZen = hasOpencodeZen;
6675
+ result.hasZaiCodingPlan = hasZaiCodingPlan;
6468
6676
  return result;
6469
6677
  }
6470
6678
  var OPENCODE_BINARIES, configContext = null, BUN_INSTALL_TIMEOUT_SECONDS = 60, BUN_INSTALL_TIMEOUT_MS, NPM_FETCH_TIMEOUT_MS = 5000, PACKAGE_NAME = "oh-my-opencode", PRIORITIZED_TAGS, ANTIGRAVITY_PROVIDER_CONFIG;
6471
6679
  var init_config_manager = __esm(() => {
6472
6680
  init_shared();
6681
+ init_model_fallback();
6473
6682
  OPENCODE_BINARIES = ["opencode", "opencode-desktop"];
6474
6683
  BUN_INSTALL_TIMEOUT_MS = BUN_INSTALL_TIMEOUT_SECONDS * 1000;
6475
6684
  PRIORITIZED_TAGS = ["latest", "beta", "next"];
@@ -6503,56 +6712,43 @@ var init_config_manager = __esm(() => {
6503
6712
  });
6504
6713
 
6505
6714
  // src/hooks/auto-update-checker/constants.ts
6506
- import * as path2 from "path";
6507
- import * as os2 from "os";
6508
- import * as fs2 from "fs";
6715
+ import * as path3 from "path";
6716
+ import * as os3 from "os";
6509
6717
  function getCacheDir() {
6510
6718
  if (process.platform === "win32") {
6511
- return path2.join(process.env.LOCALAPPDATA ?? os2.homedir(), "opencode");
6512
- }
6513
- return path2.join(os2.homedir(), ".cache", "opencode");
6514
- }
6515
- function getUserConfigDir() {
6516
- if (process.platform === "win32") {
6517
- const crossPlatformDir = path2.join(os2.homedir(), ".config");
6518
- const appdataDir = process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
6519
- const crossPlatformConfig = path2.join(crossPlatformDir, "opencode", "opencode.json");
6520
- const crossPlatformConfigJsonc = path2.join(crossPlatformDir, "opencode", "opencode.jsonc");
6521
- if (fs2.existsSync(crossPlatformConfig) || fs2.existsSync(crossPlatformConfigJsonc)) {
6522
- return crossPlatformDir;
6523
- }
6524
- return appdataDir;
6719
+ return path3.join(process.env.LOCALAPPDATA ?? os3.homedir(), "opencode");
6525
6720
  }
6526
- return process.env.XDG_CONFIG_HOME ?? path2.join(os2.homedir(), ".config");
6721
+ return path3.join(os3.homedir(), ".cache", "opencode");
6527
6722
  }
6528
6723
  function getWindowsAppdataDir() {
6529
6724
  if (process.platform !== "win32")
6530
6725
  return null;
6531
- return process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
6726
+ return process.env.APPDATA ?? path3.join(os3.homedir(), "AppData", "Roaming");
6532
6727
  }
6533
6728
  var PACKAGE_NAME2 = "oh-my-opencode", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON, USER_CONFIG_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC;
6534
6729
  var init_constants = __esm(() => {
6730
+ init_shared();
6535
6731
  NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
6536
6732
  CACHE_DIR = getCacheDir();
6537
- VERSION_FILE = path2.join(CACHE_DIR, "version");
6538
- INSTALLED_PACKAGE_JSON = path2.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
6539
- USER_CONFIG_DIR = getUserConfigDir();
6540
- USER_OPENCODE_CONFIG = path2.join(USER_CONFIG_DIR, "opencode", "opencode.json");
6541
- USER_OPENCODE_CONFIG_JSONC = path2.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
6733
+ VERSION_FILE = path3.join(CACHE_DIR, "version");
6734
+ INSTALLED_PACKAGE_JSON = path3.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
6735
+ USER_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" });
6736
+ USER_OPENCODE_CONFIG = path3.join(USER_CONFIG_DIR, "opencode.json");
6737
+ USER_OPENCODE_CONFIG_JSONC = path3.join(USER_CONFIG_DIR, "opencode.jsonc");
6542
6738
  });
6543
6739
 
6544
6740
  // src/hooks/auto-update-checker/cache.ts
6545
- import * as fs3 from "fs";
6546
- import * as path3 from "path";
6741
+ import * as fs2 from "fs";
6742
+ import * as path4 from "path";
6547
6743
  function stripTrailingCommas(json2) {
6548
6744
  return json2.replace(/,(\s*[}\]])/g, "$1");
6549
6745
  }
6550
6746
  function removeFromBunLock(packageName) {
6551
- const lockPath = path3.join(CACHE_DIR, "bun.lock");
6552
- if (!fs3.existsSync(lockPath))
6747
+ const lockPath = path4.join(CACHE_DIR, "bun.lock");
6748
+ if (!fs2.existsSync(lockPath))
6553
6749
  return false;
6554
6750
  try {
6555
- const content = fs3.readFileSync(lockPath, "utf-8");
6751
+ const content = fs2.readFileSync(lockPath, "utf-8");
6556
6752
  const lock = JSON.parse(stripTrailingCommas(content));
6557
6753
  let modified = false;
6558
6754
  if (lock.workspaces?.[""]?.dependencies?.[packageName]) {
@@ -6564,7 +6760,7 @@ function removeFromBunLock(packageName) {
6564
6760
  modified = true;
6565
6761
  }
6566
6762
  if (modified) {
6567
- fs3.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
6763
+ fs2.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
6568
6764
  log(`[auto-update-checker] Removed from bun.lock: ${packageName}`);
6569
6765
  }
6570
6766
  return modified;
@@ -6574,22 +6770,22 @@ function removeFromBunLock(packageName) {
6574
6770
  }
6575
6771
  function invalidatePackage(packageName = PACKAGE_NAME2) {
6576
6772
  try {
6577
- const pkgDir = path3.join(CACHE_DIR, "node_modules", packageName);
6578
- const pkgJsonPath = path3.join(CACHE_DIR, "package.json");
6773
+ const pkgDir = path4.join(CACHE_DIR, "node_modules", packageName);
6774
+ const pkgJsonPath = path4.join(CACHE_DIR, "package.json");
6579
6775
  let packageRemoved = false;
6580
6776
  let dependencyRemoved = false;
6581
6777
  let lockRemoved = false;
6582
- if (fs3.existsSync(pkgDir)) {
6583
- fs3.rmSync(pkgDir, { recursive: true, force: true });
6778
+ if (fs2.existsSync(pkgDir)) {
6779
+ fs2.rmSync(pkgDir, { recursive: true, force: true });
6584
6780
  log(`[auto-update-checker] Package removed: ${pkgDir}`);
6585
6781
  packageRemoved = true;
6586
6782
  }
6587
- if (fs3.existsSync(pkgJsonPath)) {
6588
- const content = fs3.readFileSync(pkgJsonPath, "utf-8");
6783
+ if (fs2.existsSync(pkgJsonPath)) {
6784
+ const content = fs2.readFileSync(pkgJsonPath, "utf-8");
6589
6785
  const pkgJson = JSON.parse(content);
6590
6786
  if (pkgJson.dependencies?.[packageName]) {
6591
6787
  delete pkgJson.dependencies[packageName];
6592
- fs3.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
6788
+ fs2.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
6593
6789
  log(`[auto-update-checker] Dependency removed from package.json: ${packageName}`);
6594
6790
  dependencyRemoved = true;
6595
6791
  }
@@ -6681,6 +6877,7 @@ v${latestVersion} available. Restart OpenCode to apply.` : `OpenCode is now on S
6681
6877
  const localDevVersion = getLocalDevVersion(ctx.directory);
6682
6878
  const displayVersion = localDevVersion ?? cachedVersion;
6683
6879
  await showConfigErrorsIfAny(ctx);
6880
+ await showModelCacheWarningIfNeeded(ctx);
6684
6881
  if (localDevVersion) {
6685
6882
  if (showStartupToast) {
6686
6883
  showLocalDevToast(ctx, displayVersion, isSisyphusEnabled).catch(() => {});
@@ -6754,6 +6951,19 @@ async function runBunInstallSafe() {
6754
6951
  return false;
6755
6952
  }
6756
6953
  }
6954
+ async function showModelCacheWarningIfNeeded(ctx) {
6955
+ if (isModelCacheAvailable())
6956
+ return;
6957
+ await ctx.client.tui.showToast({
6958
+ body: {
6959
+ title: "Model Cache Not Found",
6960
+ message: "Run 'opencode models --refresh' or restart OpenCode to populate the models cache for optimal agent model selection.",
6961
+ variant: "warning",
6962
+ duration: 1e4
6963
+ }
6964
+ }).catch(() => {});
6965
+ log("[auto-update-checker] Model cache warning shown");
6966
+ }
6757
6967
  async function showConfigErrorsIfAny(ctx) {
6758
6968
  const errors = getConfigLoadErrors();
6759
6969
  if (errors.length === 0)
@@ -6831,16 +7041,17 @@ var init_auto_update_checker = __esm(() => {
6831
7041
  init_logger();
6832
7042
  init_config_errors();
6833
7043
  init_config_manager();
7044
+ init_model_availability();
6834
7045
  init_checker();
6835
7046
  init_cache();
6836
7047
  SISYPHUS_SPINNER = ["\xB7", "\u2022", "\u25CF", "\u25CB", "\u25CC", "\u25E6", " "];
6837
7048
  });
6838
7049
 
6839
7050
  // src/hooks/auto-update-checker/checker.ts
6840
- import * as fs4 from "fs";
6841
- import * as path4 from "path";
7051
+ import * as fs3 from "fs";
7052
+ import * as path5 from "path";
6842
7053
  import { fileURLToPath } from "url";
6843
- import * as os3 from "os";
7054
+ import * as os4 from "os";
6844
7055
  function isLocalDevMode(directory) {
6845
7056
  return getLocalDevPath(directory) !== null;
6846
7057
  }
@@ -6849,18 +7060,18 @@ function stripJsonComments(json2) {
6849
7060
  }
6850
7061
  function getConfigPaths(directory) {
6851
7062
  const paths = [
6852
- path4.join(directory, ".opencode", "opencode.json"),
6853
- path4.join(directory, ".opencode", "opencode.jsonc"),
7063
+ path5.join(directory, ".opencode", "opencode.json"),
7064
+ path5.join(directory, ".opencode", "opencode.jsonc"),
6854
7065
  USER_OPENCODE_CONFIG,
6855
7066
  USER_OPENCODE_CONFIG_JSONC
6856
7067
  ];
6857
7068
  if (process.platform === "win32") {
6858
- const crossPlatformDir = path4.join(os3.homedir(), ".config");
7069
+ const crossPlatformDir = path5.join(os4.homedir(), ".config");
6859
7070
  const appdataDir = getWindowsAppdataDir();
6860
7071
  if (appdataDir) {
6861
7072
  const alternateDir = USER_CONFIG_DIR === crossPlatformDir ? appdataDir : crossPlatformDir;
6862
- const alternateConfig = path4.join(alternateDir, "opencode", "opencode.json");
6863
- const alternateConfigJsonc = path4.join(alternateDir, "opencode", "opencode.jsonc");
7073
+ const alternateConfig = path5.join(alternateDir, "opencode", "opencode.json");
7074
+ const alternateConfigJsonc = path5.join(alternateDir, "opencode", "opencode.jsonc");
6864
7075
  if (!paths.includes(alternateConfig)) {
6865
7076
  paths.push(alternateConfig);
6866
7077
  }
@@ -6874,9 +7085,9 @@ function getConfigPaths(directory) {
6874
7085
  function getLocalDevPath(directory) {
6875
7086
  for (const configPath of getConfigPaths(directory)) {
6876
7087
  try {
6877
- if (!fs4.existsSync(configPath))
7088
+ if (!fs3.existsSync(configPath))
6878
7089
  continue;
6879
- const content = fs4.readFileSync(configPath, "utf-8");
7090
+ const content = fs3.readFileSync(configPath, "utf-8");
6880
7091
  const config = JSON.parse(stripJsonComments(content));
6881
7092
  const plugins = config.plugin ?? [];
6882
7093
  for (const entry of plugins) {
@@ -6896,19 +7107,19 @@ function getLocalDevPath(directory) {
6896
7107
  }
6897
7108
  function findPackageJsonUp(startPath) {
6898
7109
  try {
6899
- const stat = fs4.statSync(startPath);
6900
- let dir = stat.isDirectory() ? startPath : path4.dirname(startPath);
7110
+ const stat = fs3.statSync(startPath);
7111
+ let dir = stat.isDirectory() ? startPath : path5.dirname(startPath);
6901
7112
  for (let i2 = 0;i2 < 10; i2++) {
6902
- const pkgPath = path4.join(dir, "package.json");
6903
- if (fs4.existsSync(pkgPath)) {
7113
+ const pkgPath = path5.join(dir, "package.json");
7114
+ if (fs3.existsSync(pkgPath)) {
6904
7115
  try {
6905
- const content = fs4.readFileSync(pkgPath, "utf-8");
7116
+ const content = fs3.readFileSync(pkgPath, "utf-8");
6906
7117
  const pkg = JSON.parse(content);
6907
7118
  if (pkg.name === PACKAGE_NAME2)
6908
7119
  return pkgPath;
6909
7120
  } catch {}
6910
7121
  }
6911
- const parent = path4.dirname(dir);
7122
+ const parent = path5.dirname(dir);
6912
7123
  if (parent === dir)
6913
7124
  break;
6914
7125
  dir = parent;
@@ -6924,7 +7135,7 @@ function getLocalDevVersion(directory) {
6924
7135
  const pkgPath = findPackageJsonUp(localPath);
6925
7136
  if (!pkgPath)
6926
7137
  return null;
6927
- const content = fs4.readFileSync(pkgPath, "utf-8");
7138
+ const content = fs3.readFileSync(pkgPath, "utf-8");
6928
7139
  const pkg = JSON.parse(content);
6929
7140
  return pkg.version ?? null;
6930
7141
  } catch {
@@ -6934,9 +7145,9 @@ function getLocalDevVersion(directory) {
6934
7145
  function findPluginEntry(directory) {
6935
7146
  for (const configPath of getConfigPaths(directory)) {
6936
7147
  try {
6937
- if (!fs4.existsSync(configPath))
7148
+ if (!fs3.existsSync(configPath))
6938
7149
  continue;
6939
- const content = fs4.readFileSync(configPath, "utf-8");
7150
+ const content = fs3.readFileSync(configPath, "utf-8");
6940
7151
  const config = JSON.parse(stripJsonComments(content));
6941
7152
  const plugins = config.plugin ?? [];
6942
7153
  for (const entry of plugins) {
@@ -6957,18 +7168,18 @@ function findPluginEntry(directory) {
6957
7168
  }
6958
7169
  function getCachedVersion() {
6959
7170
  try {
6960
- if (fs4.existsSync(INSTALLED_PACKAGE_JSON)) {
6961
- const content = fs4.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
7171
+ if (fs3.existsSync(INSTALLED_PACKAGE_JSON)) {
7172
+ const content = fs3.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
6962
7173
  const pkg = JSON.parse(content);
6963
7174
  if (pkg.version)
6964
7175
  return pkg.version;
6965
7176
  }
6966
7177
  } catch {}
6967
7178
  try {
6968
- const currentDir = path4.dirname(fileURLToPath(import.meta.url));
7179
+ const currentDir = path5.dirname(fileURLToPath(import.meta.url));
6969
7180
  const pkgPath = findPackageJsonUp(currentDir);
6970
7181
  if (pkgPath) {
6971
- const content = fs4.readFileSync(pkgPath, "utf-8");
7182
+ const content = fs3.readFileSync(pkgPath, "utf-8");
6972
7183
  const pkg = JSON.parse(content);
6973
7184
  if (pkg.version)
6974
7185
  return pkg.version;
@@ -6980,7 +7191,7 @@ function getCachedVersion() {
6980
7191
  }
6981
7192
  function updatePinnedVersion(configPath, oldEntry, newVersion) {
6982
7193
  try {
6983
- const content = fs4.readFileSync(configPath, "utf-8");
7194
+ const content = fs3.readFileSync(configPath, "utf-8");
6984
7195
  const newEntry = `${PACKAGE_NAME2}@${newVersion}`;
6985
7196
  const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
6986
7197
  if (!pluginMatch || pluginMatch.index === undefined) {
@@ -7012,7 +7223,7 @@ function updatePinnedVersion(configPath, oldEntry, newVersion) {
7012
7223
  log(`[auto-update-checker] No changes made to ${configPath}`);
7013
7224
  return false;
7014
7225
  }
7015
- fs4.writeFileSync(configPath, updatedContent, "utf-8");
7226
+ fs3.writeFileSync(configPath, updatedContent, "utf-8");
7016
7227
  log(`[auto-update-checker] Updated ${configPath}: ${oldEntry} \u2192 ${newEntry}`);
7017
7228
  return true;
7018
7229
  } catch (err) {
@@ -7671,7 +7882,7 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
7671
7882
  // package.json
7672
7883
  var package_default = {
7673
7884
  name: "oh-my-opencode",
7674
- version: "3.0.0-beta.8",
7885
+ version: "3.0.0",
7675
7886
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
7676
7887
  main: "dist/index.js",
7677
7888
  types: "dist/index.d.ts",
@@ -7727,18 +7938,14 @@ var package_default = {
7727
7938
  "@clack/prompts": "^0.11.0",
7728
7939
  "@code-yeongyu/comment-checker": "^0.6.1",
7729
7940
  "@modelcontextprotocol/sdk": "^1.25.1",
7730
- "@openauthjs/openauth": "^0.4.3",
7731
7941
  "@opencode-ai/plugin": "^1.1.19",
7732
7942
  "@opencode-ai/sdk": "^1.1.19",
7733
7943
  commander: "^14.0.2",
7734
7944
  "detect-libc": "^2.0.0",
7735
- hono: "^4.10.4",
7736
7945
  "js-yaml": "^4.1.1",
7737
7946
  "jsonc-parser": "^3.3.1",
7738
- open: "^11.0.0",
7739
7947
  picocolors: "^1.1.1",
7740
7948
  picomatch: "^4.0.2",
7741
- "xdg-basedir": "^5.1.0",
7742
7949
  zod: "^4.1.8"
7743
7950
  },
7744
7951
  devDependencies: {
@@ -7748,13 +7955,13 @@ var package_default = {
7748
7955
  typescript: "^5.7.3"
7749
7956
  },
7750
7957
  optionalDependencies: {
7751
- "oh-my-opencode-darwin-arm64": "3.0.0-beta.8",
7752
- "oh-my-opencode-darwin-x64": "3.0.0-beta.8",
7753
- "oh-my-opencode-linux-arm64": "3.0.0-beta.8",
7754
- "oh-my-opencode-linux-arm64-musl": "3.0.0-beta.8",
7755
- "oh-my-opencode-linux-x64": "3.0.0-beta.8",
7756
- "oh-my-opencode-linux-x64-musl": "3.0.0-beta.8",
7757
- "oh-my-opencode-windows-x64": "3.0.0-beta.8"
7958
+ "oh-my-opencode-darwin-arm64": "3.0.0",
7959
+ "oh-my-opencode-darwin-x64": "3.0.0",
7960
+ "oh-my-opencode-linux-arm64": "3.0.0",
7961
+ "oh-my-opencode-linux-arm64-musl": "3.0.0",
7962
+ "oh-my-opencode-linux-x64": "3.0.0",
7963
+ "oh-my-opencode-linux-x64-musl": "3.0.0",
7964
+ "oh-my-opencode-windows-x64": "3.0.0"
7758
7965
  },
7759
7966
  trustedDependencies: [
7760
7967
  "@ast-grep/cli",
@@ -7766,13 +7973,13 @@ var package_default = {
7766
7973
  // src/cli/install.ts
7767
7974
  var VERSION = package_default.version;
7768
7975
  var SYMBOLS = {
7769
- check: import_picocolors2.default.green("\u2713"),
7770
- cross: import_picocolors2.default.red("\u2717"),
7771
- arrow: import_picocolors2.default.cyan("\u2192"),
7772
- bullet: import_picocolors2.default.dim("\u2022"),
7773
- info: import_picocolors2.default.blue("\u2139"),
7774
- warn: import_picocolors2.default.yellow("\u26A0"),
7775
- star: import_picocolors2.default.yellow("\u2605")
7976
+ check: import_picocolors2.default.green("[OK]"),
7977
+ cross: import_picocolors2.default.red("[X]"),
7978
+ arrow: import_picocolors2.default.cyan("->"),
7979
+ bullet: import_picocolors2.default.dim("*"),
7980
+ info: import_picocolors2.default.blue("[i]"),
7981
+ warn: import_picocolors2.default.yellow("[!]"),
7982
+ star: import_picocolors2.default.yellow("*")
7776
7983
  };
7777
7984
  function formatProvider(name, enabled, detail) {
7778
7985
  const status = enabled ? SYMBOLS.check : import_picocolors2.default.dim("\u25CB");
@@ -7786,22 +7993,18 @@ function formatConfigSummary(config) {
7786
7993
  lines.push("");
7787
7994
  const claudeDetail = config.hasClaude ? config.isMax20 ? "max20" : "standard" : undefined;
7788
7995
  lines.push(formatProvider("Claude", config.hasClaude, claudeDetail));
7789
- lines.push(formatProvider("ChatGPT", config.hasChatGPT));
7996
+ lines.push(formatProvider("OpenAI/ChatGPT", config.hasOpenAI, "GPT-5.2 for Oracle"));
7790
7997
  lines.push(formatProvider("Gemini", config.hasGemini));
7791
- lines.push(formatProvider("GitHub Copilot", config.hasCopilot, "fallback provider"));
7998
+ lines.push(formatProvider("GitHub Copilot", config.hasCopilot, "fallback"));
7999
+ lines.push(formatProvider("OpenCode Zen", config.hasOpencodeZen, "opencode/ models"));
8000
+ lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "Librarian/Multimodal"));
7792
8001
  lines.push("");
7793
8002
  lines.push(import_picocolors2.default.dim("\u2500".repeat(40)));
7794
8003
  lines.push("");
7795
- lines.push(import_picocolors2.default.bold(import_picocolors2.default.white("Agent Configuration")));
8004
+ lines.push(import_picocolors2.default.bold(import_picocolors2.default.white("Model Assignment")));
7796
8005
  lines.push("");
7797
- const sisyphusModel = config.hasClaude ? "claude-opus-4-5" : config.hasCopilot ? "github-copilot/claude-opus-4.5" : "glm-4.7-free";
7798
- const oracleModel = config.hasChatGPT ? "gpt-5.2" : config.hasCopilot ? "github-copilot/gpt-5.2" : config.hasClaude ? "claude-opus-4-5" : "glm-4.7-free";
7799
- const librarianModel = "glm-4.7-free";
7800
- const frontendModel = config.hasGemini ? "antigravity-gemini-3-pro-high" : config.hasClaude ? "claude-opus-4-5" : "glm-4.7-free";
7801
- lines.push(` ${SYMBOLS.bullet} Sisyphus ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(sisyphusModel)}`);
7802
- lines.push(` ${SYMBOLS.bullet} Oracle ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(oracleModel)}`);
7803
- lines.push(` ${SYMBOLS.bullet} Librarian ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(librarianModel)}`);
7804
- lines.push(` ${SYMBOLS.bullet} Frontend ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(frontendModel)}`);
8006
+ lines.push(` ${SYMBOLS.info} Models auto-configured based on provider priority`);
8007
+ lines.push(` ${SYMBOLS.bullet} Priority: Native > Copilot > OpenCode Zen > Z.ai`);
7805
8008
  return lines.join(`
7806
8009
  `);
7807
8010
  }
@@ -7853,11 +8056,6 @@ function validateNonTuiArgs(args) {
7853
8056
  } else if (!["no", "yes", "max20"].includes(args.claude)) {
7854
8057
  errors.push(`Invalid --claude value: ${args.claude} (expected: no, yes, max20)`);
7855
8058
  }
7856
- if (args.chatgpt === undefined) {
7857
- errors.push("--chatgpt is required (values: no, yes)");
7858
- } else if (!["no", "yes"].includes(args.chatgpt)) {
7859
- errors.push(`Invalid --chatgpt value: ${args.chatgpt} (expected: no, yes)`);
7860
- }
7861
8059
  if (args.gemini === undefined) {
7862
8060
  errors.push("--gemini is required (values: no, yes)");
7863
8061
  } else if (!["no", "yes"].includes(args.gemini)) {
@@ -7868,15 +8066,26 @@ function validateNonTuiArgs(args) {
7868
8066
  } else if (!["no", "yes"].includes(args.copilot)) {
7869
8067
  errors.push(`Invalid --copilot value: ${args.copilot} (expected: no, yes)`);
7870
8068
  }
8069
+ if (args.openai !== undefined && !["no", "yes"].includes(args.openai)) {
8070
+ errors.push(`Invalid --openai value: ${args.openai} (expected: no, yes)`);
8071
+ }
8072
+ if (args.opencodeZen !== undefined && !["no", "yes"].includes(args.opencodeZen)) {
8073
+ errors.push(`Invalid --opencode-zen value: ${args.opencodeZen} (expected: no, yes)`);
8074
+ }
8075
+ if (args.zaiCodingPlan !== undefined && !["no", "yes"].includes(args.zaiCodingPlan)) {
8076
+ errors.push(`Invalid --zai-coding-plan value: ${args.zaiCodingPlan} (expected: no, yes)`);
8077
+ }
7871
8078
  return { valid: errors.length === 0, errors };
7872
8079
  }
7873
8080
  function argsToConfig(args) {
7874
8081
  return {
7875
8082
  hasClaude: args.claude !== "no",
7876
8083
  isMax20: args.claude === "max20",
7877
- hasChatGPT: args.chatgpt === "yes",
8084
+ hasOpenAI: args.openai === "yes",
7878
8085
  hasGemini: args.gemini === "yes",
7879
- hasCopilot: args.copilot === "yes"
8086
+ hasCopilot: args.copilot === "yes",
8087
+ hasOpencodeZen: args.opencodeZen === "yes",
8088
+ hasZaiCodingPlan: args.zaiCodingPlan === "yes"
7880
8089
  };
7881
8090
  }
7882
8091
  function detectedToInitialValues(detected) {
@@ -7886,9 +8095,11 @@ function detectedToInitialValues(detected) {
7886
8095
  }
7887
8096
  return {
7888
8097
  claude,
7889
- chatgpt: detected.hasChatGPT ? "yes" : "no",
8098
+ openai: detected.hasOpenAI ? "yes" : "no",
7890
8099
  gemini: detected.hasGemini ? "yes" : "no",
7891
- copilot: detected.hasCopilot ? "yes" : "no"
8100
+ copilot: detected.hasCopilot ? "yes" : "no",
8101
+ opencodeZen: detected.hasOpencodeZen ? "yes" : "no",
8102
+ zaiCodingPlan: detected.hasZaiCodingPlan ? "yes" : "no"
7892
8103
  };
7893
8104
  }
7894
8105
  async function runTuiMode(detected) {
@@ -7896,7 +8107,7 @@ async function runTuiMode(detected) {
7896
8107
  const claude = await ve({
7897
8108
  message: "Do you have a Claude Pro/Max subscription?",
7898
8109
  options: [
7899
- { value: "no", label: "No", hint: "Will use opencode/glm-4.7-free as fallback" },
8110
+ { value: "no", label: "No", hint: "Will use opencode/big-pickle as fallback" },
7900
8111
  { value: "yes", label: "Yes (standard)", hint: "Claude Opus 4.5 for orchestration" },
7901
8112
  { value: "max20", label: "Yes (max20 mode)", hint: "Full power with Claude Sonnet 4.5 for Librarian" }
7902
8113
  ],
@@ -7906,15 +8117,15 @@ async function runTuiMode(detected) {
7906
8117
  xe("Installation cancelled.");
7907
8118
  return null;
7908
8119
  }
7909
- const chatgpt = await ve({
7910
- message: "Do you have a ChatGPT Plus/Pro subscription?",
8120
+ const openai = await ve({
8121
+ message: "Do you have an OpenAI/ChatGPT Plus subscription?",
7911
8122
  options: [
7912
- { value: "no", label: "No", hint: "Oracle will use fallback model" },
7913
- { value: "yes", label: "Yes", hint: "GPT-5.2 for debugging and architecture" }
8123
+ { value: "no", label: "No", hint: "Oracle will use fallback models" },
8124
+ { value: "yes", label: "Yes", hint: "GPT-5.2 for Oracle (high-IQ debugging)" }
7914
8125
  ],
7915
- initialValue: initial.chatgpt
8126
+ initialValue: initial.openai
7916
8127
  });
7917
- if (pD(chatgpt)) {
8128
+ if (pD(openai)) {
7918
8129
  xe("Installation cancelled.");
7919
8130
  return null;
7920
8131
  }
@@ -7942,12 +8153,38 @@ async function runTuiMode(detected) {
7942
8153
  xe("Installation cancelled.");
7943
8154
  return null;
7944
8155
  }
8156
+ const opencodeZen = await ve({
8157
+ message: "Do you have access to OpenCode Zen (opencode/ models)?",
8158
+ options: [
8159
+ { value: "no", label: "No", hint: "Will use other configured providers" },
8160
+ { value: "yes", label: "Yes", hint: "opencode/claude-opus-4-5, opencode/gpt-5.2, etc." }
8161
+ ],
8162
+ initialValue: initial.opencodeZen
8163
+ });
8164
+ if (pD(opencodeZen)) {
8165
+ xe("Installation cancelled.");
8166
+ return null;
8167
+ }
8168
+ const zaiCodingPlan = await ve({
8169
+ message: "Do you have a Z.ai Coding Plan subscription?",
8170
+ options: [
8171
+ { value: "no", label: "No", hint: "Will use other configured providers" },
8172
+ { value: "yes", label: "Yes", hint: "Fallback for Librarian and Multimodal Looker" }
8173
+ ],
8174
+ initialValue: initial.zaiCodingPlan
8175
+ });
8176
+ if (pD(zaiCodingPlan)) {
8177
+ xe("Installation cancelled.");
8178
+ return null;
8179
+ }
7945
8180
  return {
7946
8181
  hasClaude: claude !== "no",
7947
8182
  isMax20: claude === "max20",
7948
- hasChatGPT: chatgpt === "yes",
8183
+ hasOpenAI: openai === "yes",
7949
8184
  hasGemini: gemini === "yes",
7950
- hasCopilot: copilot === "yes"
8185
+ hasCopilot: copilot === "yes",
8186
+ hasOpencodeZen: opencodeZen === "yes",
8187
+ hasZaiCodingPlan: zaiCodingPlan === "yes"
7951
8188
  };
7952
8189
  }
7953
8190
  async function runNonTuiInstall(args) {
@@ -7959,7 +8196,7 @@ async function runNonTuiInstall(args) {
7959
8196
  console.log(` ${SYMBOLS.bullet} ${err}`);
7960
8197
  }
7961
8198
  console.log();
7962
- printInfo("Usage: bunx oh-my-opencode install --no-tui --claude=<no|yes|max20> --chatgpt=<no|yes> --gemini=<no|yes> --copilot=<no|yes>");
8199
+ printInfo("Usage: bunx oh-my-opencode install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>");
7963
8200
  console.log();
7964
8201
  return 1;
7965
8202
  }
@@ -7970,16 +8207,16 @@ async function runNonTuiInstall(args) {
7970
8207
  let step = 1;
7971
8208
  printStep(step++, totalSteps, "Checking OpenCode installation...");
7972
8209
  const installed = await isOpenCodeInstalled();
8210
+ const version = await getOpenCodeVersion();
7973
8211
  if (!installed) {
7974
- printError("OpenCode is not installed on this system.");
8212
+ printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
7975
8213
  printInfo("Visit https://opencode.ai/docs for installation instructions");
7976
- return 1;
8214
+ } else {
8215
+ printSuccess(`OpenCode ${version ?? ""} detected`);
7977
8216
  }
7978
- const version = await getOpenCodeVersion();
7979
- printSuccess(`OpenCode ${version ?? ""} detected`);
7980
8217
  if (isUpdate) {
7981
8218
  const initial = detectedToInitialValues(detected);
7982
- printInfo(`Current config: Claude=${initial.claude}, ChatGPT=${initial.chatgpt}, Gemini=${initial.gemini}`);
8219
+ printInfo(`Current config: Claude=${initial.claude}, Gemini=${initial.gemini}`);
7983
8220
  }
7984
8221
  const config = argsToConfig(args);
7985
8222
  printStep(step++, totalSteps, "Adding oh-my-opencode plugin...");
@@ -8015,26 +8252,38 @@ async function runNonTuiInstall(args) {
8015
8252
  }
8016
8253
  printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors2.default.dim(omoResult.configPath)}`);
8017
8254
  printBox(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
8018
- if (!config.hasClaude && !config.hasChatGPT && !config.hasGemini && !config.hasCopilot) {
8019
- printWarning("No model providers configured. Using opencode/glm-4.7-free as fallback.");
8255
+ if (!config.hasClaude) {
8256
+ console.log();
8257
+ console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
8258
+ console.log();
8259
+ console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
8260
+ console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
8261
+ console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
8262
+ console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
8263
+ console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
8264
+ console.log();
8265
+ console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
8266
+ console.log();
8267
+ }
8268
+ if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
8269
+ printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
8020
8270
  }
8021
8271
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.bold(import_picocolors2.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
8022
8272
  console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
8023
8273
  console.log();
8024
8274
  printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
8025
8275
  ` + `All features work like magic\u2014parallel agents, background tasks,
8026
- ` + `deep exploration, and relentless execution until completion.`, "\uD83E\uDE84 The Magic Word");
8276
+ ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
8027
8277
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
8028
8278
  console.log(` ${import_picocolors2.default.dim("gh repo star code-yeongyu/oh-my-opencode")}`);
8029
8279
  console.log();
8030
8280
  console.log(import_picocolors2.default.dim("oMoMoMoMo... Enjoy!"));
8031
8281
  console.log();
8032
- if ((config.hasClaude || config.hasChatGPT || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8282
+ if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8033
8283
  printBox(`Run ${import_picocolors2.default.cyan("opencode auth login")} and select your provider:
8034
8284
  ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}
8035
- ` : "") + (config.hasChatGPT ? ` ${SYMBOLS.bullet} OpenAI ${import_picocolors2.default.gray("\u2192 ChatGPT Plus/Pro")}
8036
8285
  ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors2.default.gray("\u2192 OAuth with Antigravity")}
8037
- ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}` : ""), "\uD83D\uDD10 Authenticate Your Providers");
8286
+ ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}` : ""), "Authenticate Your Providers");
8038
8287
  }
8039
8288
  return 0;
8040
8289
  }
@@ -8047,20 +8296,19 @@ async function install(args) {
8047
8296
  Ie(import_picocolors2.default.bgMagenta(import_picocolors2.default.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")));
8048
8297
  if (isUpdate) {
8049
8298
  const initial = detectedToInitialValues(detected);
8050
- M2.info(`Existing configuration detected: Claude=${initial.claude}, ChatGPT=${initial.chatgpt}, Gemini=${initial.gemini}`);
8299
+ M2.info(`Existing configuration detected: Claude=${initial.claude}, Gemini=${initial.gemini}`);
8051
8300
  }
8052
8301
  const s = Y2();
8053
8302
  s.start("Checking OpenCode installation");
8054
8303
  const installed = await isOpenCodeInstalled();
8304
+ const version = await getOpenCodeVersion();
8055
8305
  if (!installed) {
8056
- s.stop("OpenCode is not installed");
8057
- M2.error("OpenCode is not installed on this system.");
8306
+ s.stop(`OpenCode binary not found ${import_picocolors2.default.yellow("[!]")}`);
8307
+ M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
8058
8308
  Me("Visit https://opencode.ai/docs for installation instructions", "Installation Guide");
8059
- Se(import_picocolors2.default.red("Please install OpenCode first."));
8060
- return 1;
8309
+ } else {
8310
+ s.stop(`OpenCode ${version ?? "installed"} ${import_picocolors2.default.green("[OK]")}`);
8061
8311
  }
8062
- const version = await getOpenCodeVersion();
8063
- s.stop(`OpenCode ${version ?? "installed"} ${import_picocolors2.default.green("\u2713")}`);
8064
8312
  const config = await runTuiMode(detected);
8065
8313
  if (!config)
8066
8314
  return 1;
@@ -8098,30 +8346,41 @@ async function install(args) {
8098
8346
  return 1;
8099
8347
  }
8100
8348
  s.stop(`Config written to ${import_picocolors2.default.cyan(omoResult.configPath)}`);
8101
- if (!config.hasClaude && !config.hasChatGPT && !config.hasGemini && !config.hasCopilot) {
8102
- M2.warn("No model providers configured. Using opencode/glm-4.7-free as fallback.");
8349
+ if (!config.hasClaude) {
8350
+ console.log();
8351
+ console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
8352
+ console.log();
8353
+ console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
8354
+ console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
8355
+ console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
8356
+ console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
8357
+ console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
8358
+ console.log();
8359
+ console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
8360
+ console.log();
8361
+ }
8362
+ if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
8363
+ M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
8103
8364
  }
8104
8365
  Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
8105
8366
  M2.success(import_picocolors2.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
8106
8367
  M2.message(`Run ${import_picocolors2.default.cyan("opencode")} to start!`);
8107
8368
  Me(`Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
8108
8369
  ` + `All features work like magic\u2014parallel agents, background tasks,
8109
- ` + `deep exploration, and relentless execution until completion.`, "\uD83E\uDE84 The Magic Word");
8370
+ ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
8110
8371
  M2.message(`${import_picocolors2.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
8111
8372
  M2.message(` ${import_picocolors2.default.dim("gh repo star code-yeongyu/oh-my-opencode")}`);
8112
8373
  Se(import_picocolors2.default.green("oMoMoMoMo... Enjoy!"));
8113
- if ((config.hasClaude || config.hasChatGPT || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8374
+ if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8114
8375
  const providers = [];
8115
8376
  if (config.hasClaude)
8116
8377
  providers.push(`Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}`);
8117
- if (config.hasChatGPT)
8118
- providers.push(`OpenAI ${import_picocolors2.default.gray("\u2192 ChatGPT Plus/Pro")}`);
8119
8378
  if (config.hasGemini)
8120
8379
  providers.push(`Google ${import_picocolors2.default.gray("\u2192 OAuth with Antigravity")}`);
8121
8380
  if (config.hasCopilot)
8122
8381
  providers.push(`GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}`);
8123
8382
  console.log();
8124
- console.log(import_picocolors2.default.bold("\uD83D\uDD10 Authenticate Your Providers"));
8383
+ console.log(import_picocolors2.default.bold("Authenticate Your Providers"));
8125
8384
  console.log();
8126
8385
  console.log(` Run ${import_picocolors2.default.cyan("opencode auth login")} and select:`);
8127
8386
  for (const provider of providers) {
@@ -8365,7 +8624,7 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
8365
8624
 
8366
8625
  // node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
8367
8626
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
8368
- var defaultPathSerializer = ({ path: path2, url: _url }) => {
8627
+ var defaultPathSerializer = ({ path: path3, url: _url }) => {
8369
8628
  let url = _url;
8370
8629
  const matches = _url.match(PATH_PARAM_RE);
8371
8630
  if (matches) {
@@ -8384,7 +8643,7 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
8384
8643
  name = name.substring(1);
8385
8644
  style = "matrix";
8386
8645
  }
8387
- const value = path2[name];
8646
+ const value = path3[name];
8388
8647
  if (value === undefined || value === null) {
8389
8648
  continue;
8390
8649
  }
@@ -8415,11 +8674,11 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
8415
8674
  }
8416
8675
  return url;
8417
8676
  };
8418
- var getUrl = ({ baseUrl, path: path2, query, querySerializer, url: _url }) => {
8677
+ var getUrl = ({ baseUrl, path: path3, query, querySerializer, url: _url }) => {
8419
8678
  const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
8420
8679
  let url = (baseUrl ?? "") + pathUrl;
8421
- if (path2) {
8422
- url = defaultPathSerializer({ path: path2, url });
8680
+ if (path3) {
8681
+ url = defaultPathSerializer({ path: path3, url });
8423
8682
  }
8424
8683
  let search = query ? querySerializer(query) : "";
8425
8684
  if (search.startsWith("?")) {
@@ -9735,7 +9994,7 @@ function logEventVerbose(ctx, payload) {
9735
9994
  const toolName = toolProps?.name ?? "unknown";
9736
9995
  const input = toolProps?.input ?? {};
9737
9996
  const inputStr = JSON.stringify(input).slice(0, 150);
9738
- console.error(import_picocolors4.default.cyan(`${sessionTag} \u26A1 TOOL.EXECUTE: ${import_picocolors4.default.bold(toolName)}`));
9997
+ console.error(import_picocolors4.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors4.default.bold(toolName)}`));
9739
9998
  console.error(import_picocolors4.default.dim(` input: ${inputStr}${inputStr.length >= 150 ? "..." : ""}`));
9740
9999
  break;
9741
10000
  }
@@ -9743,13 +10002,13 @@ function logEventVerbose(ctx, payload) {
9743
10002
  const resultProps = props;
9744
10003
  const output = resultProps?.output ?? "";
9745
10004
  const preview = output.slice(0, 200).replace(/\n/g, "\\n");
9746
- console.error(import_picocolors4.default.green(`${sessionTag} \u2713 TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
10005
+ console.error(import_picocolors4.default.green(`${sessionTag} TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
9747
10006
  break;
9748
10007
  }
9749
10008
  case "session.error": {
9750
10009
  const errorProps = props;
9751
10010
  const errorMsg = serializeError(errorProps?.error);
9752
- console.error(import_picocolors4.default.red(`${sessionTag} \u274C SESSION.ERROR: ${errorMsg}`));
10011
+ console.error(import_picocolors4.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
9753
10012
  break;
9754
10013
  }
9755
10014
  default:
@@ -9843,7 +10102,7 @@ function handleToolExecute(ctx, payload, state) {
9843
10102
  }
9844
10103
  }
9845
10104
  process.stdout.write(`
9846
- ${import_picocolors4.default.cyan("\u26A1")} ${import_picocolors4.default.bold(toolName)}${inputPreview}
10105
+ ${import_picocolors4.default.cyan(">")} ${import_picocolors4.default.bold(toolName)}${inputPreview}
9847
10106
  `);
9848
10107
  }
9849
10108
  function handleToolResult(ctx, payload, state) {
@@ -9869,6 +10128,8 @@ function handleToolResult(ctx, payload, state) {
9869
10128
  // src/cli/run/runner.ts
9870
10129
  var POLL_INTERVAL_MS = 500;
9871
10130
  var DEFAULT_TIMEOUT_MS = 0;
10131
+ var SESSION_CREATE_MAX_RETRIES = 3;
10132
+ var SESSION_CREATE_RETRY_DELAY_MS = 1000;
9872
10133
  async function run(options) {
9873
10134
  const {
9874
10135
  message,
@@ -9902,12 +10163,39 @@ Interrupted. Shutting down...`));
9902
10163
  process.exit(130);
9903
10164
  });
9904
10165
  try {
9905
- const sessionRes = await client3.session.create({
9906
- body: { title: "oh-my-opencode run" }
9907
- });
9908
- const sessionID = sessionRes.data?.id;
10166
+ let sessionID;
10167
+ let lastError;
10168
+ for (let attempt = 1;attempt <= SESSION_CREATE_MAX_RETRIES; attempt++) {
10169
+ const sessionRes = await client3.session.create({
10170
+ body: { title: "oh-my-opencode run" }
10171
+ });
10172
+ if (sessionRes.error) {
10173
+ lastError = sessionRes.error;
10174
+ console.error(import_picocolors5.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
10175
+ console.error(import_picocolors5.default.dim(` Error: ${serializeError(sessionRes.error)}`));
10176
+ if (attempt < SESSION_CREATE_MAX_RETRIES) {
10177
+ const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
10178
+ console.log(import_picocolors5.default.dim(` Retrying in ${delay}ms...`));
10179
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
10180
+ continue;
10181
+ }
10182
+ }
10183
+ sessionID = sessionRes.data?.id;
10184
+ if (sessionID) {
10185
+ break;
10186
+ }
10187
+ lastError = new Error(`Unexpected response: ${JSON.stringify(sessionRes, null, 2)}`);
10188
+ console.error(import_picocolors5.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
10189
+ if (attempt < SESSION_CREATE_MAX_RETRIES) {
10190
+ const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
10191
+ console.log(import_picocolors5.default.dim(` Retrying in ${delay}ms...`));
10192
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
10193
+ }
10194
+ }
9909
10195
  if (!sessionID) {
9910
- console.error(import_picocolors5.default.red("Failed to create session"));
10196
+ console.error(import_picocolors5.default.red("Failed to create session after all retries"));
10197
+ console.error(import_picocolors5.default.dim(`Last error: ${serializeError(lastError)}`));
10198
+ cleanup();
9911
10199
  return 1;
9912
10200
  }
9913
10201
  console.log(import_picocolors5.default.dim(`Session: ${sessionID}`));
@@ -9977,13 +10265,13 @@ init_checker();
9977
10265
  // src/cli/get-local-version/formatter.ts
9978
10266
  var import_picocolors6 = __toESM(require_picocolors(), 1);
9979
10267
  var SYMBOLS2 = {
9980
- check: import_picocolors6.default.green("\u2713"),
9981
- cross: import_picocolors6.default.red("\u2717"),
9982
- arrow: import_picocolors6.default.cyan("\u2192"),
9983
- info: import_picocolors6.default.blue("\u2139"),
9984
- warn: import_picocolors6.default.yellow("\u26A0"),
9985
- pin: import_picocolors6.default.magenta("\uD83D\uDCCC"),
9986
- dev: import_picocolors6.default.cyan("\uD83D\uDD27")
10268
+ check: import_picocolors6.default.green("[OK]"),
10269
+ cross: import_picocolors6.default.red("[X]"),
10270
+ arrow: import_picocolors6.default.cyan("->"),
10271
+ info: import_picocolors6.default.blue("[i]"),
10272
+ warn: import_picocolors6.default.yellow("[!]"),
10273
+ pin: import_picocolors6.default.magenta("[PINNED]"),
10274
+ dev: import_picocolors6.default.cyan("[DEV]")
9987
10275
  };
9988
10276
  function formatVersionOutput(info) {
9989
10277
  const lines = [];
@@ -10142,6 +10430,7 @@ var CHECK_IDS = {
10142
10430
  OPENCODE_INSTALLATION: "opencode-installation",
10143
10431
  PLUGIN_REGISTRATION: "plugin-registration",
10144
10432
  CONFIG_VALIDATION: "config-validation",
10433
+ MODEL_RESOLUTION: "model-resolution",
10145
10434
  AUTH_ANTHROPIC: "auth-anthropic",
10146
10435
  AUTH_OPENAI: "auth-openai",
10147
10436
  AUTH_GOOGLE: "auth-google",
@@ -10158,6 +10447,7 @@ var CHECK_NAMES = {
10158
10447
  [CHECK_IDS.OPENCODE_INSTALLATION]: "OpenCode Installation",
10159
10448
  [CHECK_IDS.PLUGIN_REGISTRATION]: "Plugin Registration",
10160
10449
  [CHECK_IDS.CONFIG_VALIDATION]: "Configuration Validity",
10450
+ [CHECK_IDS.MODEL_RESOLUTION]: "Model Resolution",
10161
10451
  [CHECK_IDS.AUTH_ANTHROPIC]: "Anthropic (Claude) Auth",
10162
10452
  [CHECK_IDS.AUTH_OPENAI]: "OpenAI (ChatGPT) Auth",
10163
10453
  [CHECK_IDS.AUTH_GOOGLE]: "Google (Gemini) Auth",
@@ -10187,14 +10477,53 @@ var PACKAGE_NAME3 = "oh-my-opencode";
10187
10477
  var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
10188
10478
 
10189
10479
  // src/cli/doctor/checks/opencode.ts
10480
+ var WINDOWS_EXECUTABLE_EXTS = [".exe", ".cmd", ".bat", ".ps1"];
10481
+ function getBinaryLookupCommand(platform) {
10482
+ return platform === "win32" ? "where" : "which";
10483
+ }
10484
+ function parseBinaryPaths(output) {
10485
+ return output.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
10486
+ }
10487
+ function selectBinaryPath(paths, platform) {
10488
+ if (paths.length === 0)
10489
+ return null;
10490
+ if (platform !== "win32")
10491
+ return paths[0];
10492
+ const normalized = paths.map((path6) => path6.toLowerCase());
10493
+ for (const ext of WINDOWS_EXECUTABLE_EXTS) {
10494
+ const index = normalized.findIndex((path6) => path6.endsWith(ext));
10495
+ if (index !== -1)
10496
+ return paths[index];
10497
+ }
10498
+ return paths[0];
10499
+ }
10500
+ function buildVersionCommand(binaryPath, platform) {
10501
+ if (platform === "win32" && binaryPath.toLowerCase().endsWith(".ps1")) {
10502
+ return [
10503
+ "powershell",
10504
+ "-NoProfile",
10505
+ "-ExecutionPolicy",
10506
+ "Bypass",
10507
+ "-File",
10508
+ binaryPath,
10509
+ "--version"
10510
+ ];
10511
+ }
10512
+ return [binaryPath, "--version"];
10513
+ }
10190
10514
  async function findOpenCodeBinary() {
10191
10515
  for (const binary2 of OPENCODE_BINARIES2) {
10192
10516
  try {
10193
- const proc = Bun.spawn(["which", binary2], { stdout: "pipe", stderr: "pipe" });
10517
+ const lookupCommand = getBinaryLookupCommand(process.platform);
10518
+ const proc = Bun.spawn([lookupCommand, binary2], { stdout: "pipe", stderr: "pipe" });
10194
10519
  const output = await new Response(proc.stdout).text();
10195
10520
  await proc.exited;
10196
10521
  if (proc.exitCode === 0) {
10197
- return { binary: binary2, path: output.trim() };
10522
+ const paths = parseBinaryPaths(output);
10523
+ const selectedPath = selectBinaryPath(paths, process.platform);
10524
+ if (selectedPath) {
10525
+ return { binary: binary2, path: selectedPath };
10526
+ }
10198
10527
  }
10199
10528
  } catch {
10200
10529
  continue;
@@ -10202,9 +10531,10 @@ async function findOpenCodeBinary() {
10202
10531
  }
10203
10532
  return null;
10204
10533
  }
10205
- async function getOpenCodeVersion2(binary2) {
10534
+ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
10206
10535
  try {
10207
- const proc = Bun.spawn([binary2, "--version"], { stdout: "pipe", stderr: "pipe" });
10536
+ const command = buildVersionCommand(binaryPath, platform);
10537
+ const proc = Bun.spawn(command, { stdout: "pipe", stderr: "pipe" });
10208
10538
  const output = await new Response(proc.stdout).text();
10209
10539
  await proc.exited;
10210
10540
  if (proc.exitCode === 0) {
@@ -10242,7 +10572,7 @@ async function getOpenCodeInfo() {
10242
10572
  binary: null
10243
10573
  };
10244
10574
  }
10245
- const version = await getOpenCodeVersion2(binaryInfo.binary);
10575
+ const version = await getOpenCodeVersion2(binaryInfo.path ?? binaryInfo.binary);
10246
10576
  return {
10247
10577
  installed: true,
10248
10578
  version,
@@ -10293,7 +10623,7 @@ function getOpenCodeCheckDefinition() {
10293
10623
  }
10294
10624
 
10295
10625
  // src/cli/doctor/checks/plugin.ts
10296
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
10626
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
10297
10627
  init_shared();
10298
10628
  function detectConfigPath() {
10299
10629
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
@@ -10312,6 +10642,9 @@ function findPluginEntry2(plugins) {
10312
10642
  const version = isPinned ? plugin.split("@")[1] : null;
10313
10643
  return { entry: plugin, isPinned, version };
10314
10644
  }
10645
+ if (plugin.startsWith("file://") && plugin.includes(PACKAGE_NAME3)) {
10646
+ return { entry: plugin, isPinned: false, version: "local-dev" };
10647
+ }
10315
10648
  }
10316
10649
  return null;
10317
10650
  }
@@ -10327,7 +10660,7 @@ function getPluginInfo() {
10327
10660
  };
10328
10661
  }
10329
10662
  try {
10330
- const content = readFileSync5(configInfo.path, "utf-8");
10663
+ const content = readFileSync6(configInfo.path, "utf-8");
10331
10664
  const config = parseJsonc(content);
10332
10665
  const plugins = config.plugin ?? [];
10333
10666
  const pluginEntry = findPluginEntry2(plugins);
@@ -10401,9 +10734,8 @@ function getPluginCheckDefinition() {
10401
10734
  }
10402
10735
 
10403
10736
  // src/cli/doctor/checks/config.ts
10404
- import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
10405
- import { homedir as homedir4 } from "os";
10406
- import { join as join6 } from "path";
10737
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
10738
+ import { join as join8 } from "path";
10407
10739
  init_shared();
10408
10740
 
10409
10741
  // node_modules/zod/v4/classic/external.js
@@ -11135,10 +11467,10 @@ function mergeDefs(...defs) {
11135
11467
  function cloneDef(schema2) {
11136
11468
  return mergeDefs(schema2._zod.def);
11137
11469
  }
11138
- function getElementAtPath(obj, path5) {
11139
- if (!path5)
11470
+ function getElementAtPath(obj, path6) {
11471
+ if (!path6)
11140
11472
  return obj;
11141
- return path5.reduce((acc, key) => acc?.[key], obj);
11473
+ return path6.reduce((acc, key) => acc?.[key], obj);
11142
11474
  }
11143
11475
  function promiseAllObject(promisesObj) {
11144
11476
  const keys = Object.keys(promisesObj);
@@ -11497,11 +11829,11 @@ function aborted(x2, startIndex = 0) {
11497
11829
  }
11498
11830
  return false;
11499
11831
  }
11500
- function prefixIssues(path5, issues) {
11832
+ function prefixIssues(path6, issues) {
11501
11833
  return issues.map((iss) => {
11502
11834
  var _a;
11503
11835
  (_a = iss).path ?? (_a.path = []);
11504
- iss.path.unshift(path5);
11836
+ iss.path.unshift(path6);
11505
11837
  return iss;
11506
11838
  });
11507
11839
  }
@@ -11669,7 +12001,7 @@ function treeifyError(error, _mapper) {
11669
12001
  return issue2.message;
11670
12002
  };
11671
12003
  const result = { errors: [] };
11672
- const processError = (error2, path5 = []) => {
12004
+ const processError = (error2, path6 = []) => {
11673
12005
  var _a, _b;
11674
12006
  for (const issue2 of error2.issues) {
11675
12007
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -11679,7 +12011,7 @@ function treeifyError(error, _mapper) {
11679
12011
  } else if (issue2.code === "invalid_element") {
11680
12012
  processError({ issues: issue2.issues }, issue2.path);
11681
12013
  } else {
11682
- const fullpath = [...path5, ...issue2.path];
12014
+ const fullpath = [...path6, ...issue2.path];
11683
12015
  if (fullpath.length === 0) {
11684
12016
  result.errors.push(mapper(issue2));
11685
12017
  continue;
@@ -11711,8 +12043,8 @@ function treeifyError(error, _mapper) {
11711
12043
  }
11712
12044
  function toDotPath(_path) {
11713
12045
  const segs = [];
11714
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11715
- for (const seg of path5) {
12046
+ const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12047
+ for (const seg of path6) {
11716
12048
  if (typeof seg === "number")
11717
12049
  segs.push(`[${seg}]`);
11718
12050
  else if (typeof seg === "symbol")
@@ -22739,16 +23071,15 @@ var AgentPermissionSchema = exports_external.object({
22739
23071
  external_directory: PermissionValue.optional()
22740
23072
  });
22741
23073
  var BuiltinAgentNameSchema = exports_external.enum([
22742
- "Sisyphus",
23074
+ "sisyphus",
23075
+ "prometheus",
22743
23076
  "oracle",
22744
23077
  "librarian",
22745
23078
  "explore",
22746
- "frontend-ui-ux-engineer",
22747
- "document-writer",
22748
23079
  "multimodal-looker",
22749
- "Metis (Plan Consultant)",
22750
- "Momus (Plan Reviewer)",
22751
- "orchestrator-sisyphus"
23080
+ "metis",
23081
+ "momus",
23082
+ "atlas"
22752
23083
  ]);
22753
23084
  var BuiltinSkillNameSchema = exports_external.enum([
22754
23085
  "playwright",
@@ -22758,19 +23089,17 @@ var BuiltinSkillNameSchema = exports_external.enum([
22758
23089
  var OverridableAgentNameSchema = exports_external.enum([
22759
23090
  "build",
22760
23091
  "plan",
22761
- "Sisyphus",
22762
- "Sisyphus-Junior",
23092
+ "sisyphus",
23093
+ "sisyphus-junior",
22763
23094
  "OpenCode-Builder",
22764
- "Prometheus (Planner)",
22765
- "Metis (Plan Consultant)",
22766
- "Momus (Plan Reviewer)",
23095
+ "prometheus",
23096
+ "metis",
23097
+ "momus",
22767
23098
  "oracle",
22768
23099
  "librarian",
22769
23100
  "explore",
22770
- "frontend-ui-ux-engineer",
22771
- "document-writer",
22772
23101
  "multimodal-looker",
22773
- "orchestrator-sisyphus"
23102
+ "atlas"
22774
23103
  ]);
22775
23104
  var HookNameSchema = exports_external.enum([
22776
23105
  "todo-continuation-enforcer",
@@ -22793,18 +23122,16 @@ var HookNameSchema = exports_external.enum([
22793
23122
  "agent-usage-reminder",
22794
23123
  "non-interactive-env",
22795
23124
  "interactive-bash-session",
22796
- "empty-message-sanitizer",
22797
23125
  "thinking-block-validator",
22798
23126
  "ralph-loop",
22799
- "preemptive-compaction",
22800
23127
  "compaction-context-injector",
22801
23128
  "claude-code-hooks",
22802
23129
  "auto-slash-command",
22803
23130
  "edit-error-recovery",
22804
- "sisyphus-task-retry",
23131
+ "delegate-task-retry",
22805
23132
  "prometheus-md-only",
22806
23133
  "start-work",
22807
- "sisyphus-orchestrator"
23134
+ "atlas"
22808
23135
  ]);
22809
23136
  var BuiltinCommandNameSchema = exports_external.enum([
22810
23137
  "init-deep",
@@ -22829,19 +23156,17 @@ var AgentOverrideConfigSchema = exports_external.object({
22829
23156
  var AgentOverridesSchema = exports_external.object({
22830
23157
  build: AgentOverrideConfigSchema.optional(),
22831
23158
  plan: AgentOverrideConfigSchema.optional(),
22832
- Sisyphus: AgentOverrideConfigSchema.optional(),
22833
- "Sisyphus-Junior": AgentOverrideConfigSchema.optional(),
23159
+ sisyphus: AgentOverrideConfigSchema.optional(),
23160
+ "sisyphus-junior": AgentOverrideConfigSchema.optional(),
22834
23161
  "OpenCode-Builder": AgentOverrideConfigSchema.optional(),
22835
- "Prometheus (Planner)": AgentOverrideConfigSchema.optional(),
22836
- "Metis (Plan Consultant)": AgentOverrideConfigSchema.optional(),
22837
- "Momus (Plan Reviewer)": AgentOverrideConfigSchema.optional(),
23162
+ prometheus: AgentOverrideConfigSchema.optional(),
23163
+ metis: AgentOverrideConfigSchema.optional(),
23164
+ momus: AgentOverrideConfigSchema.optional(),
22838
23165
  oracle: AgentOverrideConfigSchema.optional(),
22839
23166
  librarian: AgentOverrideConfigSchema.optional(),
22840
23167
  explore: AgentOverrideConfigSchema.optional(),
22841
- "frontend-ui-ux-engineer": AgentOverrideConfigSchema.optional(),
22842
- "document-writer": AgentOverrideConfigSchema.optional(),
22843
23168
  "multimodal-looker": AgentOverrideConfigSchema.optional(),
22844
- "orchestrator-sisyphus": AgentOverrideConfigSchema.optional()
23169
+ atlas: AgentOverrideConfigSchema.optional()
22845
23170
  });
22846
23171
  var ClaudeCodeConfigSchema = exports_external.object({
22847
23172
  mcp: exports_external.boolean().optional(),
@@ -22859,7 +23184,8 @@ var SisyphusAgentConfigSchema = exports_external.object({
22859
23184
  replace_plan: exports_external.boolean().optional()
22860
23185
  });
22861
23186
  var CategoryConfigSchema = exports_external.object({
22862
- model: exports_external.string(),
23187
+ description: exports_external.string().optional(),
23188
+ model: exports_external.string().optional(),
22863
23189
  variant: exports_external.string().optional(),
22864
23190
  temperature: exports_external.number().min(0).max(2).optional(),
22865
23191
  top_p: exports_external.number().min(0).max(1).optional(),
@@ -22868,19 +23194,20 @@ var CategoryConfigSchema = exports_external.object({
22868
23194
  type: exports_external.enum(["enabled", "disabled"]),
22869
23195
  budgetTokens: exports_external.number().optional()
22870
23196
  }).optional(),
22871
- reasoningEffort: exports_external.enum(["low", "medium", "high"]).optional(),
23197
+ reasoningEffort: exports_external.enum(["low", "medium", "high", "xhigh"]).optional(),
22872
23198
  textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
22873
23199
  tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
22874
- prompt_append: exports_external.string().optional()
23200
+ prompt_append: exports_external.string().optional(),
23201
+ is_unstable_agent: exports_external.boolean().optional()
22875
23202
  });
22876
23203
  var BuiltinCategoryNameSchema = exports_external.enum([
22877
23204
  "visual-engineering",
22878
23205
  "ultrabrain",
22879
23206
  "artistry",
22880
23207
  "quick",
22881
- "most-capable",
22882
- "writing",
22883
- "general"
23208
+ "unspecified-low",
23209
+ "unspecified-high",
23210
+ "writing"
22884
23211
  ]);
22885
23212
  var CategoriesConfigSchema = exports_external.record(exports_external.string(), CategoryConfigSchema);
22886
23213
  var CommentCheckerConfigSchema = exports_external.object({
@@ -22919,11 +23246,8 @@ var DynamicContextPruningConfigSchema = exports_external.object({
22919
23246
  var ExperimentalConfigSchema = exports_external.object({
22920
23247
  aggressive_truncation: exports_external.boolean().optional(),
22921
23248
  auto_resume: exports_external.boolean().optional(),
22922
- preemptive_compaction: exports_external.boolean().optional(),
22923
- preemptive_compaction_threshold: exports_external.number().min(0.5).max(0.95).optional(),
22924
23249
  truncate_all_tool_outputs: exports_external.boolean().optional(),
22925
- dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(),
22926
- dcp_for_compaction: exports_external.boolean().optional()
23250
+ dynamic_context_pruning: DynamicContextPruningConfigSchema.optional()
22927
23251
  });
22928
23252
  var SkillSourceSchema = exports_external.union([
22929
23253
  exports_external.string(),
@@ -22966,8 +23290,9 @@ var RalphLoopConfigSchema = exports_external.object({
22966
23290
  });
22967
23291
  var BackgroundTaskConfigSchema = exports_external.object({
22968
23292
  defaultConcurrency: exports_external.number().min(1).optional(),
22969
- providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional(),
22970
- modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional()
23293
+ providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional(),
23294
+ modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional(),
23295
+ staleTimeoutMs: exports_external.number().min(60000).optional()
22971
23296
  });
22972
23297
  var NotificationConfigSchema = exports_external.object({
22973
23298
  force_enable: exports_external.boolean().optional()
@@ -22997,9 +23322,9 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
22997
23322
  git_master: GitMasterConfigSchema.optional()
22998
23323
  });
22999
23324
  // src/cli/doctor/checks/config.ts
23000
- var USER_CONFIG_DIR2 = join6(homedir4(), ".config", "opencode");
23001
- var USER_CONFIG_BASE = join6(USER_CONFIG_DIR2, `${PACKAGE_NAME3}`);
23002
- var PROJECT_CONFIG_BASE = join6(process.cwd(), ".opencode", PACKAGE_NAME3);
23325
+ var USER_CONFIG_DIR2 = getOpenCodeConfigDir({ binary: "opencode" });
23326
+ var USER_CONFIG_BASE = join8(USER_CONFIG_DIR2, `${PACKAGE_NAME3}`);
23327
+ var PROJECT_CONFIG_BASE = join8(process.cwd(), ".opencode", PACKAGE_NAME3);
23003
23328
  function findConfigPath() {
23004
23329
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
23005
23330
  if (projectDetected.format !== "none") {
@@ -23013,7 +23338,7 @@ function findConfigPath() {
23013
23338
  }
23014
23339
  function validateConfig(configPath) {
23015
23340
  try {
23016
- const content = readFileSync6(configPath, "utf-8");
23341
+ const content = readFileSync7(configPath, "utf-8");
23017
23342
  const rawConfig = parseJsonc(content);
23018
23343
  const result = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
23019
23344
  if (!result.success) {
@@ -23095,25 +23420,195 @@ function getConfigCheckDefinition() {
23095
23420
  };
23096
23421
  }
23097
23422
 
23423
+ // src/cli/doctor/checks/model-resolution.ts
23424
+ import { readFileSync as readFileSync8, existsSync as existsSync9 } from "fs";
23425
+ init_shared();
23426
+ init_model_requirements();
23427
+ import { homedir as homedir6 } from "os";
23428
+ import { join as join9 } from "path";
23429
+ function getOpenCodeCacheDir2() {
23430
+ const xdgCache = process.env.XDG_CACHE_HOME;
23431
+ if (xdgCache)
23432
+ return join9(xdgCache, "opencode");
23433
+ return join9(homedir6(), ".cache", "opencode");
23434
+ }
23435
+ function loadAvailableModels() {
23436
+ const cacheFile = join9(getOpenCodeCacheDir2(), "models.json");
23437
+ if (!existsSync9(cacheFile)) {
23438
+ return { providers: [], modelCount: 0, cacheExists: false };
23439
+ }
23440
+ try {
23441
+ const content = readFileSync8(cacheFile, "utf-8");
23442
+ const data = JSON.parse(content);
23443
+ const providers = Object.keys(data);
23444
+ let modelCount = 0;
23445
+ for (const providerId of providers) {
23446
+ const models = data[providerId]?.models;
23447
+ if (models && typeof models === "object") {
23448
+ modelCount += Object.keys(models).length;
23449
+ }
23450
+ }
23451
+ return { providers, modelCount, cacheExists: true };
23452
+ } catch {
23453
+ return { providers: [], modelCount: 0, cacheExists: false };
23454
+ }
23455
+ }
23456
+ var PACKAGE_NAME4 = "oh-my-opencode";
23457
+ var USER_CONFIG_DIR3 = join9(homedir6(), ".config", "opencode");
23458
+ var USER_CONFIG_BASE2 = join9(USER_CONFIG_DIR3, PACKAGE_NAME4);
23459
+ var PROJECT_CONFIG_BASE2 = join9(process.cwd(), ".opencode", PACKAGE_NAME4);
23460
+ function loadConfig() {
23461
+ const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE2);
23462
+ if (projectDetected.format !== "none") {
23463
+ try {
23464
+ const content = readFileSync8(projectDetected.path, "utf-8");
23465
+ return parseJsonc(content);
23466
+ } catch {
23467
+ return null;
23468
+ }
23469
+ }
23470
+ const userDetected = detectConfigFile(USER_CONFIG_BASE2);
23471
+ if (userDetected.format !== "none") {
23472
+ try {
23473
+ const content = readFileSync8(userDetected.path, "utf-8");
23474
+ return parseJsonc(content);
23475
+ } catch {
23476
+ return null;
23477
+ }
23478
+ }
23479
+ return null;
23480
+ }
23481
+ function formatProviderChain(providers) {
23482
+ return providers.join(" \u2192 ");
23483
+ }
23484
+ function getEffectiveModel(requirement, userOverride) {
23485
+ if (userOverride) {
23486
+ return userOverride;
23487
+ }
23488
+ const firstEntry = requirement.fallbackChain[0];
23489
+ if (!firstEntry) {
23490
+ return "unknown";
23491
+ }
23492
+ return `${firstEntry.providers[0]}/${firstEntry.model}`;
23493
+ }
23494
+ function buildEffectiveResolution(requirement, userOverride) {
23495
+ if (userOverride) {
23496
+ return `User override: ${userOverride}`;
23497
+ }
23498
+ const firstEntry = requirement.fallbackChain[0];
23499
+ if (!firstEntry) {
23500
+ return "No fallback chain defined";
23501
+ }
23502
+ return `Provider fallback: ${formatProviderChain(firstEntry.providers)} \u2192 ${firstEntry.model}`;
23503
+ }
23504
+ function getModelResolutionInfoWithOverrides(config2) {
23505
+ const agents = Object.entries(AGENT_MODEL_REQUIREMENTS).map(([name, requirement]) => {
23506
+ const userOverride = config2.agents?.[name]?.model;
23507
+ return {
23508
+ name,
23509
+ requirement,
23510
+ userOverride,
23511
+ effectiveModel: getEffectiveModel(requirement, userOverride),
23512
+ effectiveResolution: buildEffectiveResolution(requirement, userOverride)
23513
+ };
23514
+ });
23515
+ const categories = Object.entries(CATEGORY_MODEL_REQUIREMENTS).map(([name, requirement]) => {
23516
+ const userOverride = config2.categories?.[name]?.model;
23517
+ return {
23518
+ name,
23519
+ requirement,
23520
+ userOverride,
23521
+ effectiveModel: getEffectiveModel(requirement, userOverride),
23522
+ effectiveResolution: buildEffectiveResolution(requirement, userOverride)
23523
+ };
23524
+ });
23525
+ return { agents, categories };
23526
+ }
23527
+ function formatModelWithVariant(model, variant) {
23528
+ return variant ? `${model} (${variant})` : model;
23529
+ }
23530
+ function getEffectiveVariant(requirement) {
23531
+ const firstEntry = requirement.fallbackChain[0];
23532
+ return firstEntry?.variant ?? requirement.variant;
23533
+ }
23534
+ function buildDetailsArray(info, available) {
23535
+ const details = [];
23536
+ details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
23537
+ details.push("");
23538
+ if (available.cacheExists) {
23539
+ details.push(` Providers: ${available.providers.length} (${available.providers.slice(0, 8).join(", ")}${available.providers.length > 8 ? "..." : ""})`);
23540
+ details.push(` Total models: ${available.modelCount}`);
23541
+ details.push(` Cache: ~/.cache/opencode/models.json`);
23542
+ details.push(` Refresh: opencode models --refresh`);
23543
+ } else {
23544
+ details.push(" \u26A0 Cache not found. Run 'opencode' to populate.");
23545
+ }
23546
+ details.push("");
23547
+ details.push("\u2550\u2550\u2550 Configured Models \u2550\u2550\u2550");
23548
+ details.push("");
23549
+ details.push("Agents:");
23550
+ for (const agent of info.agents) {
23551
+ const marker = agent.userOverride ? "\u25CF" : "\u25CB";
23552
+ const display = formatModelWithVariant(agent.effectiveModel, getEffectiveVariant(agent.requirement));
23553
+ details.push(` ${marker} ${agent.name}: ${display}`);
23554
+ }
23555
+ details.push("");
23556
+ details.push("Categories:");
23557
+ for (const category of info.categories) {
23558
+ const marker = category.userOverride ? "\u25CF" : "\u25CB";
23559
+ const display = formatModelWithVariant(category.effectiveModel, getEffectiveVariant(category.requirement));
23560
+ details.push(` ${marker} ${category.name}: ${display}`);
23561
+ }
23562
+ details.push("");
23563
+ details.push("\u25CF = user override, \u25CB = provider fallback");
23564
+ return details;
23565
+ }
23566
+ async function checkModelResolution() {
23567
+ const config2 = loadConfig() ?? {};
23568
+ const info = getModelResolutionInfoWithOverrides(config2);
23569
+ const available = loadAvailableModels();
23570
+ const agentCount = info.agents.length;
23571
+ const categoryCount = info.categories.length;
23572
+ const agentOverrides = info.agents.filter((a) => a.userOverride).length;
23573
+ const categoryOverrides = info.categories.filter((c) => c.userOverride).length;
23574
+ const totalOverrides = agentOverrides + categoryOverrides;
23575
+ const overrideNote = totalOverrides > 0 ? ` (${totalOverrides} override${totalOverrides > 1 ? "s" : ""})` : "";
23576
+ const cacheNote = available.cacheExists ? `, ${available.modelCount} available` : ", cache not found";
23577
+ return {
23578
+ name: CHECK_NAMES[CHECK_IDS.MODEL_RESOLUTION],
23579
+ status: available.cacheExists ? "pass" : "warn",
23580
+ message: `${agentCount} agents, ${categoryCount} categories${overrideNote}${cacheNote}`,
23581
+ details: buildDetailsArray(info, available)
23582
+ };
23583
+ }
23584
+ function getModelResolutionCheckDefinition() {
23585
+ return {
23586
+ id: CHECK_IDS.MODEL_RESOLUTION,
23587
+ name: CHECK_NAMES[CHECK_IDS.MODEL_RESOLUTION],
23588
+ category: "configuration",
23589
+ check: checkModelResolution,
23590
+ critical: false
23591
+ };
23592
+ }
23593
+
23098
23594
  // src/cli/doctor/checks/auth.ts
23099
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
23100
- import { homedir as homedir5 } from "os";
23101
- import { join as join7 } from "path";
23595
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
23596
+ import { join as join10 } from "path";
23102
23597
  init_shared();
23103
- var OPENCODE_CONFIG_DIR = join7(homedir5(), ".config", "opencode");
23104
- var OPENCODE_JSON = join7(OPENCODE_CONFIG_DIR, "opencode.json");
23105
- var OPENCODE_JSONC = join7(OPENCODE_CONFIG_DIR, "opencode.jsonc");
23598
+ var OPENCODE_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" });
23599
+ var OPENCODE_JSON = join10(OPENCODE_CONFIG_DIR, "opencode.json");
23600
+ var OPENCODE_JSONC = join10(OPENCODE_CONFIG_DIR, "opencode.jsonc");
23106
23601
  var AUTH_PLUGINS = {
23107
23602
  anthropic: { plugin: "builtin", name: "Anthropic (Claude)" },
23108
23603
  openai: { plugin: "opencode-openai-codex-auth", name: "OpenAI (ChatGPT)" },
23109
23604
  google: { plugin: "opencode-antigravity-auth", name: "Google (Gemini)" }
23110
23605
  };
23111
23606
  function getOpenCodeConfig() {
23112
- const configPath = existsSync9(OPENCODE_JSONC) ? OPENCODE_JSONC : OPENCODE_JSON;
23113
- if (!existsSync9(configPath))
23607
+ const configPath = existsSync10(OPENCODE_JSONC) ? OPENCODE_JSONC : OPENCODE_JSON;
23608
+ if (!existsSync10(configPath))
23114
23609
  return null;
23115
23610
  try {
23116
- const content = readFileSync7(configPath, "utf-8");
23611
+ const content = readFileSync9(configPath, "utf-8");
23117
23612
  return parseJsonc(content);
23118
23613
  } catch {
23119
23614
  return null;
@@ -23242,9 +23737,9 @@ async function checkAstGrepCli() {
23242
23737
  path: binary2.path
23243
23738
  };
23244
23739
  }
23245
- function checkAstGrepNapi() {
23740
+ async function checkAstGrepNapi() {
23246
23741
  try {
23247
- __require.resolve("@ast-grep/napi");
23742
+ await import("@ast-grep/napi");
23248
23743
  return {
23249
23744
  name: "AST-Grep NAPI",
23250
23745
  required: false,
@@ -23253,6 +23748,24 @@ function checkAstGrepNapi() {
23253
23748
  path: null
23254
23749
  };
23255
23750
  } catch {
23751
+ const { existsSync: existsSync11 } = await import("fs");
23752
+ const { join: join11 } = await import("path");
23753
+ const { homedir: homedir7 } = await import("os");
23754
+ const pathsToCheck = [
23755
+ join11(homedir7(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
23756
+ join11(process.cwd(), "node_modules", "@ast-grep", "napi")
23757
+ ];
23758
+ for (const napiPath of pathsToCheck) {
23759
+ if (existsSync11(napiPath)) {
23760
+ return {
23761
+ name: "AST-Grep NAPI",
23762
+ required: false,
23763
+ installed: true,
23764
+ version: null,
23765
+ path: napiPath
23766
+ };
23767
+ }
23768
+ }
23256
23769
  return {
23257
23770
  name: "AST-Grep NAPI",
23258
23771
  required: false,
@@ -23305,7 +23818,7 @@ async function checkDependencyAstGrepCli() {
23305
23818
  return dependencyToCheckResult(info, CHECK_NAMES[CHECK_IDS.DEP_AST_GREP_CLI]);
23306
23819
  }
23307
23820
  async function checkDependencyAstGrepNapi() {
23308
- const info = checkAstGrepNapi();
23821
+ const info = await checkAstGrepNapi();
23309
23822
  return dependencyToCheckResult(info, CHECK_NAMES[CHECK_IDS.DEP_AST_GREP_NAPI]);
23310
23823
  }
23311
23824
  async function checkDependencyCommentChecker() {
@@ -23471,6 +23984,64 @@ function getGhCliCheckDefinition() {
23471
23984
  };
23472
23985
  }
23473
23986
 
23987
+ // src/tools/lsp/config.ts
23988
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
23989
+ import { join as join11 } from "path";
23990
+ init_shared();
23991
+ function isServerInstalled(command) {
23992
+ if (command.length === 0)
23993
+ return false;
23994
+ const cmd = command[0];
23995
+ if (cmd.includes("/") || cmd.includes("\\")) {
23996
+ if (existsSync11(cmd))
23997
+ return true;
23998
+ }
23999
+ const isWindows = process.platform === "win32";
24000
+ let exts = [""];
24001
+ if (isWindows) {
24002
+ const pathExt = process.env.PATHEXT || "";
24003
+ if (pathExt) {
24004
+ const systemExts = pathExt.split(";").filter(Boolean);
24005
+ exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
24006
+ } else {
24007
+ exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
24008
+ }
24009
+ }
24010
+ let pathEnv = process.env.PATH || "";
24011
+ if (isWindows && !pathEnv) {
24012
+ pathEnv = process.env.Path || "";
24013
+ }
24014
+ const pathSeparator = isWindows ? ";" : ":";
24015
+ const paths = pathEnv.split(pathSeparator);
24016
+ for (const p2 of paths) {
24017
+ for (const suffix of exts) {
24018
+ if (existsSync11(join11(p2, cmd + suffix))) {
24019
+ return true;
24020
+ }
24021
+ }
24022
+ }
24023
+ const cwd = process.cwd();
24024
+ const configDir = getOpenCodeConfigDir({ binary: "opencode" });
24025
+ const dataDir = join11(getDataDir(), "opencode");
24026
+ const additionalBases = [
24027
+ join11(cwd, "node_modules", ".bin"),
24028
+ join11(configDir, "bin"),
24029
+ join11(configDir, "node_modules", ".bin"),
24030
+ join11(dataDir, "bin")
24031
+ ];
24032
+ for (const base of additionalBases) {
24033
+ for (const suffix of exts) {
24034
+ if (existsSync11(join11(base, cmd + suffix))) {
24035
+ return true;
24036
+ }
24037
+ }
24038
+ }
24039
+ if (cmd === "bun" || cmd === "node") {
24040
+ return true;
24041
+ }
24042
+ return false;
24043
+ }
24044
+
23474
24045
  // src/cli/doctor/checks/lsp.ts
23475
24046
  var DEFAULT_LSP_SERVERS = [
23476
24047
  { id: "typescript-language-server", binary: "typescript-language-server", extensions: [".ts", ".tsx", ".js", ".jsx"] },
@@ -23478,19 +24049,10 @@ var DEFAULT_LSP_SERVERS = [
23478
24049
  { id: "rust-analyzer", binary: "rust-analyzer", extensions: [".rs"] },
23479
24050
  { id: "gopls", binary: "gopls", extensions: [".go"] }
23480
24051
  ];
23481
- async function checkBinaryExists3(binary2) {
23482
- try {
23483
- const proc = Bun.spawn(["which", binary2], { stdout: "pipe", stderr: "pipe" });
23484
- await proc.exited;
23485
- return proc.exitCode === 0;
23486
- } catch {
23487
- return false;
23488
- }
23489
- }
23490
24052
  async function getLspServersInfo() {
23491
24053
  const servers = [];
23492
24054
  for (const server2 of DEFAULT_LSP_SERVERS) {
23493
- const installed = await checkBinaryExists3(server2.binary);
24055
+ const installed = isServerInstalled([server2.binary]);
23494
24056
  servers.push({
23495
24057
  id: server2.id,
23496
24058
  installed,
@@ -23542,23 +24104,23 @@ function getLspCheckDefinition() {
23542
24104
  }
23543
24105
 
23544
24106
  // src/cli/doctor/checks/mcp.ts
23545
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
23546
- import { homedir as homedir6 } from "os";
23547
- import { join as join8 } from "path";
24107
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
24108
+ import { homedir as homedir7 } from "os";
24109
+ import { join as join12 } from "path";
23548
24110
  init_shared();
23549
24111
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
23550
24112
  var MCP_CONFIG_PATHS = [
23551
- join8(homedir6(), ".claude", ".mcp.json"),
23552
- join8(process.cwd(), ".mcp.json"),
23553
- join8(process.cwd(), ".claude", ".mcp.json")
24113
+ join12(homedir7(), ".claude", ".mcp.json"),
24114
+ join12(process.cwd(), ".mcp.json"),
24115
+ join12(process.cwd(), ".claude", ".mcp.json")
23554
24116
  ];
23555
24117
  function loadUserMcpConfig() {
23556
24118
  const servers = {};
23557
24119
  for (const configPath of MCP_CONFIG_PATHS) {
23558
- if (!existsSync10(configPath))
24120
+ if (!existsSync12(configPath))
23559
24121
  continue;
23560
24122
  try {
23561
- const content = readFileSync8(configPath, "utf-8");
24123
+ const content = readFileSync11(configPath, "utf-8");
23562
24124
  const config2 = parseJsonc(content);
23563
24125
  if (config2.mcpServers) {
23564
24126
  Object.assign(servers, config2.mcpServers);
@@ -23765,6 +24327,7 @@ function getAllCheckDefinitions() {
23765
24327
  getOpenCodeCheckDefinition(),
23766
24328
  getPluginCheckDefinition(),
23767
24329
  getConfigCheckDefinition(),
24330
+ getModelResolutionCheckDefinition(),
23768
24331
  ...getAuthCheckDefinitions(),
23769
24332
  ...getDependencyCheckDefinitions(),
23770
24333
  getGhCliCheckDefinition(),
@@ -23956,23 +24519,28 @@ async function doctor(options = {}) {
23956
24519
  var VERSION2 = package_default.version;
23957
24520
  var program2 = new Command;
23958
24521
  program2.name("oh-my-opencode").description("The ultimate OpenCode plugin - multi-model orchestration, LSP tools, and more").version(VERSION2, "-v, --version", "Show version number");
23959
- program2.command("install").description("Install and configure oh-my-opencode with interactive setup").option("--no-tui", "Run in non-interactive mode (requires all options)").option("--claude <value>", "Claude subscription: no, yes, max20").option("--chatgpt <value>", "ChatGPT subscription: no, yes").option("--gemini <value>", "Gemini integration: no, yes").option("--copilot <value>", "GitHub Copilot subscription: no, yes").option("--skip-auth", "Skip authentication setup hints").addHelpText("after", `
24522
+ program2.command("install").description("Install and configure oh-my-opencode with interactive setup").option("--no-tui", "Run in non-interactive mode (requires all options)").option("--claude <value>", "Claude subscription: no, yes, max20").option("--openai <value>", "OpenAI/ChatGPT subscription: no, yes (default: no)").option("--gemini <value>", "Gemini integration: no, yes").option("--copilot <value>", "GitHub Copilot subscription: no, yes").option("--opencode-zen <value>", "OpenCode Zen access: no, yes (default: no)").option("--zai-coding-plan <value>", "Z.ai Coding Plan subscription: no, yes (default: no)").option("--skip-auth", "Skip authentication setup hints").addHelpText("after", `
23960
24523
  Examples:
23961
24524
  $ bunx oh-my-opencode install
23962
- $ bunx oh-my-opencode install --no-tui --claude=max20 --chatgpt=yes --gemini=yes --copilot=no
23963
- $ bunx oh-my-opencode install --no-tui --claude=no --chatgpt=no --gemini=no --copilot=yes
24525
+ $ bunx oh-my-opencode install --no-tui --claude=max20 --openai=yes --gemini=yes --copilot=no
24526
+ $ bunx oh-my-opencode install --no-tui --claude=no --gemini=no --copilot=yes --opencode-zen=yes
23964
24527
 
23965
- Model Providers:
23966
- Claude Required for Sisyphus (main orchestrator) and Librarian agents
23967
- ChatGPT Powers the Oracle agent for debugging and architecture
23968
- Gemini Powers frontend, documentation, and multimodal agents
24528
+ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai):
24529
+ Claude Native anthropic/ models (Opus, Sonnet, Haiku)
24530
+ OpenAI Native openai/ models (GPT-5.2 for Oracle)
24531
+ Gemini Native google/ models (Gemini 3 Pro, Flash)
24532
+ Copilot github-copilot/ models (fallback)
24533
+ OpenCode Zen opencode/ models (opencode/claude-opus-4-5, etc.)
24534
+ Z.ai zai-coding-plan/glm-4.7 (Librarian priority)
23969
24535
  `).action(async (options) => {
23970
24536
  const args = {
23971
24537
  tui: options.tui !== false,
23972
24538
  claude: options.claude,
23973
- chatgpt: options.chatgpt,
24539
+ openai: options.openai,
23974
24540
  gemini: options.gemini,
23975
24541
  copilot: options.copilot,
24542
+ opencodeZen: options.opencodeZen,
24543
+ zaiCodingPlan: options.zaiCodingPlan,
23976
24544
  skipAuth: options.skipAuth ?? false
23977
24545
  };
23978
24546
  const exitCode = await install(args);