oh-my-opencode 3.0.0-beta.9 → 3.0.1

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 (97) hide show
  1. package/README.ja.md +52 -804
  2. package/README.ko.md +377 -0
  3. package/README.md +61 -933
  4. package/README.zh-cn.md +53 -928
  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 +4 -3
  19. package/dist/cli/config-manager.d.ts +77 -14
  20. package/dist/cli/doctor/checks/dependencies.d.ts +1 -1
  21. package/dist/cli/doctor/checks/index.d.ts +1 -0
  22. package/dist/cli/doctor/checks/model-resolution.d.ts +33 -0
  23. package/dist/cli/doctor/constants.d.ts +1 -0
  24. package/dist/cli/index.js +922 -418
  25. package/dist/cli/install.test.d.ts +1 -0
  26. package/dist/cli/model-fallback.d.ts +18 -0
  27. package/dist/cli/model-fallback.test.d.ts +1 -0
  28. package/dist/cli/types.d.ts +9 -3
  29. package/dist/config/schema.d.ts +50 -246
  30. package/dist/features/background-agent/manager.d.ts +10 -0
  31. package/dist/features/background-agent/types.d.ts +4 -3
  32. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  33. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +1 -1
  34. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  35. package/dist/features/builtin-commands/types.d.ts +1 -1
  36. package/dist/features/skill-mcp-manager/manager.d.ts +1 -0
  37. package/dist/features/task-toast-manager/manager.d.ts +1 -0
  38. package/dist/features/task-toast-manager/types.d.ts +3 -0
  39. package/dist/hooks/{sisyphus-orchestrator → atlas}/index.d.ts +3 -3
  40. package/dist/hooks/atlas/index.test.d.ts +1 -0
  41. package/dist/hooks/auto-update-checker/constants.d.ts +0 -3
  42. package/dist/hooks/index.d.ts +2 -2
  43. package/dist/hooks/prometheus-md-only/constants.d.ts +1 -0
  44. package/dist/hooks/question-label-truncator/index.d.ts +7 -0
  45. package/dist/hooks/question-label-truncator/index.test.d.ts +1 -0
  46. package/dist/hooks/ralph-loop/index.d.ts +1 -0
  47. package/dist/hooks/ralph-loop/types.d.ts +1 -0
  48. package/dist/index.js +12810 -13083
  49. package/dist/index.test.d.ts +1 -0
  50. package/dist/mcp/context7.d.ts +1 -0
  51. package/dist/mcp/grep-app.d.ts +1 -0
  52. package/dist/mcp/index.d.ts +1 -0
  53. package/dist/mcp/websearch.d.ts +1 -0
  54. package/dist/plugin-handlers/config-handler.d.ts +1 -0
  55. package/dist/shared/agent-config-integration.test.d.ts +1 -0
  56. package/dist/shared/agent-display-names.d.ts +12 -0
  57. package/dist/shared/agent-display-names.test.d.ts +1 -0
  58. package/dist/shared/case-insensitive.d.ts +24 -0
  59. package/dist/shared/case-insensitive.test.d.ts +1 -0
  60. package/dist/shared/index.d.ts +4 -1
  61. package/dist/shared/migration.d.ts +15 -1
  62. package/dist/shared/model-availability.d.ts +8 -0
  63. package/dist/shared/model-availability.test.d.ts +1 -0
  64. package/dist/shared/model-requirements.d.ts +11 -0
  65. package/dist/shared/model-requirements.test.d.ts +1 -0
  66. package/dist/shared/model-resolver.d.ts +20 -0
  67. package/dist/shared/model-resolver.test.d.ts +1 -0
  68. package/dist/tools/call-omo-agent/constants.d.ts +1 -1
  69. package/dist/tools/delegate-task/constants.d.ts +3 -4
  70. package/dist/tools/delegate-task/tools.d.ts +11 -1
  71. package/dist/tools/delegate-task/types.d.ts +3 -2
  72. package/dist/tools/index.d.ts +1 -2
  73. package/dist/tools/skill/types.d.ts +1 -1
  74. package/package.json +8 -12
  75. package/dist/agents/build-prompt.d.ts +0 -31
  76. package/dist/agents/document-writer.d.ts +0 -5
  77. package/dist/agents/frontend-ui-ux-engineer.d.ts +0 -5
  78. package/dist/agents/orchestrator-sisyphus.d.ts +0 -20
  79. package/dist/agents/plan-prompt.d.ts +0 -64
  80. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-executor.d.ts +0 -3
  81. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-purge-errors.d.ts +0 -7
  82. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-storage.d.ts +0 -2
  83. package/dist/hooks/anthropic-context-window-limit-recovery/pruning-supersede.d.ts +0 -6
  84. package/dist/hooks/background-compaction/index.d.ts +0 -19
  85. package/dist/hooks/comment-checker/constants.d.ts +0 -3
  86. package/dist/hooks/comment-checker/filters/bdd.d.ts +0 -2
  87. package/dist/hooks/comment-checker/filters/directive.d.ts +0 -2
  88. package/dist/hooks/comment-checker/filters/docstring.d.ts +0 -2
  89. package/dist/hooks/comment-checker/filters/index.d.ts +0 -7
  90. package/dist/hooks/comment-checker/filters/shebang.d.ts +0 -2
  91. package/dist/hooks/comment-checker/output/formatter.d.ts +0 -2
  92. package/dist/hooks/comment-checker/output/index.d.ts +0 -2
  93. package/dist/hooks/comment-checker/output/xml-builder.d.ts +0 -2
  94. package/dist/shared/config-path.d.ts +0 -17
  95. package/dist/tools/ast-grep/napi.d.ts +0 -13
  96. package/dist/tools/interactive-bash/types.d.ts +0 -3
  97. /package/dist/{hooks/sisyphus-orchestrator/index.test.d.ts → cli/doctor/checks/model-resolution.test.d.ts} +0 -0
package/dist/cli/index.js CHANGED
@@ -4913,10 +4913,12 @@ var init_dynamic_truncator = __esm(() => {
4913
4913
  ANTHROPIC_ACTUAL_LIMIT = process.env.ANTHROPIC_1M_CONTEXT === "true" || process.env.VERTEX_ANTHROPIC_1M_CONTEXT === "true" ? 1e6 : 200000;
4914
4914
  });
4915
4915
 
4916
- // src/shared/config-path.ts
4917
- var init_config_path = () => {};
4918
-
4919
4916
  // src/shared/data-path.ts
4917
+ import * as path2 from "path";
4918
+ import * as os2 from "os";
4919
+ function getDataDir() {
4920
+ return process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
4921
+ }
4920
4922
  var init_data_path = () => {};
4921
4923
 
4922
4924
  // src/shared/config-errors.ts
@@ -5832,25 +5834,23 @@ var BUILTIN_AGENT_NAMES;
5832
5834
  var init_migration = __esm(() => {
5833
5835
  init_logger();
5834
5836
  BUILTIN_AGENT_NAMES = new Set([
5835
- "Sisyphus",
5837
+ "sisyphus",
5836
5838
  "oracle",
5837
5839
  "librarian",
5838
5840
  "explore",
5839
- "frontend-ui-ux-engineer",
5840
- "document-writer",
5841
5841
  "multimodal-looker",
5842
- "Metis (Plan Consultant)",
5843
- "Momus (Plan Reviewer)",
5844
- "Prometheus (Planner)",
5845
- "orchestrator-sisyphus",
5842
+ "metis",
5843
+ "momus",
5844
+ "prometheus",
5845
+ "atlas",
5846
5846
  "build"
5847
5847
  ]);
5848
5848
  });
5849
5849
 
5850
5850
  // src/shared/opencode-config-dir.ts
5851
5851
  import { existsSync as existsSync2 } from "fs";
5852
- import { homedir } from "os";
5853
- import { join as join2, resolve } from "path";
5852
+ import { homedir as homedir2 } from "os";
5853
+ import { join as join3, resolve } from "path";
5854
5854
  function isDevBuild(version) {
5855
5855
  if (!version)
5856
5856
  return false;
@@ -5860,15 +5860,15 @@ function getTauriConfigDir(identifier) {
5860
5860
  const platform = process.platform;
5861
5861
  switch (platform) {
5862
5862
  case "darwin":
5863
- return join2(homedir(), "Library", "Application Support", identifier);
5863
+ return join3(homedir2(), "Library", "Application Support", identifier);
5864
5864
  case "win32": {
5865
- const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
5866
- return join2(appData, identifier);
5865
+ const appData = process.env.APPDATA || join3(homedir2(), "AppData", "Roaming");
5866
+ return join3(appData, identifier);
5867
5867
  }
5868
5868
  case "linux":
5869
5869
  default: {
5870
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
5871
- return join2(xdgConfig, identifier);
5870
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
5871
+ return join3(xdgConfig, identifier);
5872
5872
  }
5873
5873
  }
5874
5874
  }
@@ -5878,21 +5878,21 @@ function getCliConfigDir() {
5878
5878
  return resolve(envConfigDir);
5879
5879
  }
5880
5880
  if (process.platform === "win32") {
5881
- const crossPlatformDir = join2(homedir(), ".config", "opencode");
5882
- const crossPlatformConfig = join2(crossPlatformDir, "opencode.json");
5881
+ const crossPlatformDir = join3(homedir2(), ".config", "opencode");
5882
+ const crossPlatformConfig = join3(crossPlatformDir, "opencode.json");
5883
5883
  if (existsSync2(crossPlatformConfig)) {
5884
5884
  return crossPlatformDir;
5885
5885
  }
5886
- const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
5887
- const appdataDir = join2(appData, "opencode");
5888
- const appdataConfig = join2(appdataDir, "opencode.json");
5886
+ const appData = process.env.APPDATA || join3(homedir2(), "AppData", "Roaming");
5887
+ const appdataDir = join3(appData, "opencode");
5888
+ const appdataConfig = join3(appdataDir, "opencode.json");
5889
5889
  if (existsSync2(appdataConfig)) {
5890
5890
  return appdataDir;
5891
5891
  }
5892
5892
  return crossPlatformDir;
5893
5893
  }
5894
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
5895
- return join2(xdgConfig, "opencode");
5894
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
5895
+ return join3(xdgConfig, "opencode");
5896
5896
  }
5897
5897
  function getOpenCodeConfigDir(options) {
5898
5898
  const { binary: binary2, version, checkExisting = true } = options;
@@ -5903,8 +5903,8 @@ function getOpenCodeConfigDir(options) {
5903
5903
  const tauriDir = getTauriConfigDir(identifier);
5904
5904
  if (checkExisting) {
5905
5905
  const legacyDir = getCliConfigDir();
5906
- const legacyConfig = join2(legacyDir, "opencode.json");
5907
- const legacyConfigC = join2(legacyDir, "opencode.jsonc");
5906
+ const legacyConfig = join3(legacyDir, "opencode.json");
5907
+ const legacyConfigC = join3(legacyDir, "opencode.jsonc");
5908
5908
  if (existsSync2(legacyConfig) || existsSync2(legacyConfigC)) {
5909
5909
  return legacyDir;
5910
5910
  }
@@ -5915,10 +5915,10 @@ function getOpenCodeConfigPaths(options) {
5915
5915
  const configDir = getOpenCodeConfigDir(options);
5916
5916
  return {
5917
5917
  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")
5918
+ configJson: join3(configDir, "opencode.json"),
5919
+ configJsonc: join3(configDir, "opencode.jsonc"),
5920
+ packageJson: join3(configDir, "package.json"),
5921
+ omoConfig: join3(configDir, "oh-my-opencode.json")
5922
5922
  };
5923
5923
  }
5924
5924
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
@@ -5937,6 +5937,9 @@ var init_external_plugin_detector = __esm(() => {
5937
5937
 
5938
5938
  // src/shared/zip-extractor.ts
5939
5939
  var init_zip_extractor = () => {};
5940
+ // src/shared/agent-variant.ts
5941
+ var init_agent_variant = () => {};
5942
+
5940
5943
  // src/shared/session-cursor.ts
5941
5944
  var sessionCursors;
5942
5945
  var init_session_cursor = __esm(() => {
@@ -5948,6 +5951,154 @@ var init_system_directive = () => {};
5948
5951
  // src/shared/agent-tool-restrictions.ts
5949
5952
  var init_agent_tool_restrictions = () => {};
5950
5953
 
5954
+ // src/shared/model-requirements.ts
5955
+ var AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS;
5956
+ var init_model_requirements = __esm(() => {
5957
+ AGENT_MODEL_REQUIREMENTS = {
5958
+ sisyphus: {
5959
+ fallbackChain: [
5960
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
5961
+ { providers: ["zai-coding-plan"], model: "glm-4.7" },
5962
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
5963
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
5964
+ ]
5965
+ },
5966
+ oracle: {
5967
+ fallbackChain: [
5968
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
5969
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
5970
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
5971
+ ]
5972
+ },
5973
+ librarian: {
5974
+ fallbackChain: [
5975
+ { providers: ["zai-coding-plan"], model: "glm-4.7" },
5976
+ { providers: ["opencode"], model: "big-pickle" },
5977
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }
5978
+ ]
5979
+ },
5980
+ explore: {
5981
+ fallbackChain: [
5982
+ { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
5983
+ { providers: ["opencode"], model: "gpt-5-nano" }
5984
+ ]
5985
+ },
5986
+ "multimodal-looker": {
5987
+ fallbackChain: [
5988
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
5989
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
5990
+ { providers: ["zai-coding-plan"], model: "glm-4.6v" },
5991
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
5992
+ { providers: ["opencode"], model: "gpt-5-nano" }
5993
+ ]
5994
+ },
5995
+ prometheus: {
5996
+ fallbackChain: [
5997
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
5998
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
5999
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6000
+ ]
6001
+ },
6002
+ metis: {
6003
+ fallbackChain: [
6004
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6005
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6006
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
6007
+ ]
6008
+ },
6009
+ momus: {
6010
+ fallbackChain: [
6011
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" },
6012
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" },
6013
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
6014
+ ]
6015
+ },
6016
+ atlas: {
6017
+ fallbackChain: [
6018
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6019
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
6020
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6021
+ ]
6022
+ }
6023
+ };
6024
+ CATEGORY_MODEL_REQUIREMENTS = {
6025
+ "visual-engineering": {
6026
+ fallbackChain: [
6027
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },
6028
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6029
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }
6030
+ ]
6031
+ },
6032
+ ultrabrain: {
6033
+ fallbackChain: [
6034
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
6035
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6036
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6037
+ ]
6038
+ },
6039
+ artistry: {
6040
+ fallbackChain: [
6041
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
6042
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6043
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
6044
+ ]
6045
+ },
6046
+ quick: {
6047
+ fallbackChain: [
6048
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
6049
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
6050
+ { providers: ["opencode"], model: "gpt-5-nano" }
6051
+ ]
6052
+ },
6053
+ "unspecified-low": {
6054
+ fallbackChain: [
6055
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6056
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
6057
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }
6058
+ ]
6059
+ },
6060
+ "unspecified-high": {
6061
+ fallbackChain: [
6062
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
6063
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6064
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6065
+ ]
6066
+ },
6067
+ writing: {
6068
+ fallbackChain: [
6069
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
6070
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6071
+ { providers: ["zai-coding-plan"], model: "glm-4.7" },
6072
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
6073
+ ]
6074
+ }
6075
+ };
6076
+ });
6077
+
6078
+ // src/shared/model-availability.ts
6079
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
6080
+ import { homedir as homedir3 } from "os";
6081
+ import { join as join4 } from "path";
6082
+ function getOpenCodeCacheDir() {
6083
+ const xdgCache = process.env.XDG_CACHE_HOME;
6084
+ if (xdgCache)
6085
+ return join4(xdgCache, "opencode");
6086
+ return join4(homedir3(), ".cache", "opencode");
6087
+ }
6088
+ function isModelCacheAvailable() {
6089
+ const cacheFile = join4(getOpenCodeCacheDir(), "models.json");
6090
+ return existsSync3(cacheFile);
6091
+ }
6092
+ var init_model_availability = __esm(() => {
6093
+ init_logger();
6094
+ });
6095
+
6096
+ // src/shared/model-resolver.ts
6097
+ var init_model_resolver = __esm(() => {
6098
+ init_logger();
6099
+ init_model_availability();
6100
+ });
6101
+
5951
6102
  // src/shared/index.ts
5952
6103
  var init_shared = __esm(() => {
5953
6104
  init_frontmatter();
@@ -5959,7 +6110,6 @@ var init_shared = __esm(() => {
5959
6110
  init_deep_merge();
5960
6111
  init_file_utils();
5961
6112
  init_dynamic_truncator();
5962
- init_config_path();
5963
6113
  init_data_path();
5964
6114
  init_config_errors();
5965
6115
  init_claude_config_dir();
@@ -5969,13 +6119,129 @@ var init_shared = __esm(() => {
5969
6119
  init_opencode_version();
5970
6120
  init_external_plugin_detector();
5971
6121
  init_zip_extractor();
6122
+ init_agent_variant();
5972
6123
  init_session_cursor();
5973
6124
  init_system_directive();
5974
6125
  init_agent_tool_restrictions();
6126
+ init_model_requirements();
6127
+ init_model_resolver();
6128
+ init_model_availability();
6129
+ });
6130
+
6131
+ // src/cli/model-fallback.ts
6132
+ function toProviderAvailability(config) {
6133
+ return {
6134
+ native: {
6135
+ claude: config.hasClaude,
6136
+ openai: config.hasOpenAI,
6137
+ gemini: config.hasGemini
6138
+ },
6139
+ opencodeZen: config.hasOpencodeZen,
6140
+ copilot: config.hasCopilot,
6141
+ zai: config.hasZaiCodingPlan,
6142
+ isMaxPlan: config.isMax20
6143
+ };
6144
+ }
6145
+ function isProviderAvailable(provider, avail) {
6146
+ const mapping = {
6147
+ anthropic: avail.native.claude,
6148
+ openai: avail.native.openai,
6149
+ google: avail.native.gemini,
6150
+ "github-copilot": avail.copilot,
6151
+ opencode: avail.opencodeZen,
6152
+ "zai-coding-plan": avail.zai
6153
+ };
6154
+ return mapping[provider] ?? false;
6155
+ }
6156
+ function transformModelForProvider(provider, model) {
6157
+ if (provider === "github-copilot") {
6158
+ 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");
6159
+ }
6160
+ return model;
6161
+ }
6162
+ function resolveModelFromChain(fallbackChain, avail) {
6163
+ for (const entry of fallbackChain) {
6164
+ for (const provider of entry.providers) {
6165
+ if (isProviderAvailable(provider, avail)) {
6166
+ const transformedModel = transformModelForProvider(provider, entry.model);
6167
+ return {
6168
+ model: `${provider}/${transformedModel}`,
6169
+ variant: entry.variant
6170
+ };
6171
+ }
6172
+ }
6173
+ }
6174
+ return null;
6175
+ }
6176
+ function getSisyphusFallbackChain(isMaxPlan) {
6177
+ if (isMaxPlan) {
6178
+ return AGENT_MODEL_REQUIREMENTS.sisyphus.fallbackChain;
6179
+ }
6180
+ return [
6181
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
6182
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
6183
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
6184
+ ];
6185
+ }
6186
+ function generateModelConfig(config) {
6187
+ const avail = toProviderAvailability(config);
6188
+ const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai;
6189
+ if (!hasAnyProvider) {
6190
+ return {
6191
+ $schema: SCHEMA_URL,
6192
+ agents: Object.fromEntries(Object.keys(AGENT_MODEL_REQUIREMENTS).map((role) => [role, { model: ULTIMATE_FALLBACK }])),
6193
+ categories: Object.fromEntries(Object.keys(CATEGORY_MODEL_REQUIREMENTS).map((cat) => [cat, { model: ULTIMATE_FALLBACK }]))
6194
+ };
6195
+ }
6196
+ const agents = {};
6197
+ const categories = {};
6198
+ for (const [role, req] of Object.entries(AGENT_MODEL_REQUIREMENTS)) {
6199
+ if (role === "librarian" && avail.zai) {
6200
+ agents[role] = { model: ZAI_MODEL };
6201
+ continue;
6202
+ }
6203
+ if (role === "explore") {
6204
+ if (avail.native.claude) {
6205
+ agents[role] = { model: "anthropic/claude-haiku-4-5" };
6206
+ } else if (avail.opencodeZen) {
6207
+ agents[role] = { model: "opencode/claude-haiku-4-5" };
6208
+ } else {
6209
+ agents[role] = { model: "opencode/gpt-5-nano" };
6210
+ }
6211
+ continue;
6212
+ }
6213
+ const fallbackChain = role === "sisyphus" ? getSisyphusFallbackChain(avail.isMaxPlan) : req.fallbackChain;
6214
+ const resolved = resolveModelFromChain(fallbackChain, avail);
6215
+ if (resolved) {
6216
+ const variant = resolved.variant ?? req.variant;
6217
+ agents[role] = variant ? { model: resolved.model, variant } : { model: resolved.model };
6218
+ } else {
6219
+ agents[role] = { model: ULTIMATE_FALLBACK };
6220
+ }
6221
+ }
6222
+ for (const [cat, req] of Object.entries(CATEGORY_MODEL_REQUIREMENTS)) {
6223
+ const fallbackChain = cat === "unspecified-high" && !avail.isMaxPlan ? CATEGORY_MODEL_REQUIREMENTS["unspecified-low"].fallbackChain : req.fallbackChain;
6224
+ const resolved = resolveModelFromChain(fallbackChain, avail);
6225
+ if (resolved) {
6226
+ const variant = resolved.variant ?? req.variant;
6227
+ categories[cat] = variant ? { model: resolved.model, variant } : { model: resolved.model };
6228
+ } else {
6229
+ categories[cat] = { model: ULTIMATE_FALLBACK };
6230
+ }
6231
+ }
6232
+ return {
6233
+ $schema: SCHEMA_URL,
6234
+ agents,
6235
+ categories
6236
+ };
6237
+ }
6238
+ 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";
6239
+ var init_model_fallback = __esm(() => {
6240
+ init_model_requirements();
5975
6241
  });
5976
6242
 
5977
6243
  // src/cli/config-manager.ts
5978
- import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, writeFileSync, statSync } from "fs";
6244
+ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3, writeFileSync, statSync } from "fs";
5979
6245
  function initConfigContext(binary2, version) {
5980
6246
  const paths = getOpenCodeConfigPaths({ binary: binary2, version });
5981
6247
  configContext = { binary: binary2, version, paths };
@@ -6065,10 +6331,10 @@ async function getPluginNameWithVersion(currentVersion) {
6065
6331
  function detectConfigFormat() {
6066
6332
  const configJsonc = getConfigJsonc();
6067
6333
  const configJson = getConfigJson();
6068
- if (existsSync3(configJsonc)) {
6334
+ if (existsSync4(configJsonc)) {
6069
6335
  return { format: "jsonc", path: configJsonc };
6070
6336
  }
6071
- if (existsSync3(configJson)) {
6337
+ if (existsSync4(configJson)) {
6072
6338
  return { format: "json", path: configJson };
6073
6339
  }
6074
6340
  return { format: "none", path: configJson };
@@ -6076,31 +6342,31 @@ function detectConfigFormat() {
6076
6342
  function isEmptyOrWhitespace(content) {
6077
6343
  return content.trim().length === 0;
6078
6344
  }
6079
- function parseConfigWithError(path2) {
6345
+ function parseConfigWithError(path3) {
6080
6346
  try {
6081
- const stat = statSync(path2);
6347
+ const stat = statSync(path3);
6082
6348
  if (stat.size === 0) {
6083
- return { config: null, error: `Config file is empty: ${path2}. Delete it or add valid JSON content.` };
6349
+ return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
6084
6350
  }
6085
- const content = readFileSync2(path2, "utf-8");
6351
+ const content = readFileSync3(path3, "utf-8");
6086
6352
  if (isEmptyOrWhitespace(content)) {
6087
- return { config: null, error: `Config file contains only whitespace: ${path2}. Delete it or add valid JSON content.` };
6353
+ return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
6088
6354
  }
6089
6355
  const config = parseJsonc(content);
6090
6356
  if (config === null || config === undefined) {
6091
- return { config: null, error: `Config file parsed to null/undefined: ${path2}. Ensure it contains valid JSON.` };
6357
+ return { config: null, error: `Config file parsed to null/undefined: ${path3}. Ensure it contains valid JSON.` };
6092
6358
  }
6093
6359
  if (typeof config !== "object" || Array.isArray(config)) {
6094
- return { config: null, error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path2}` };
6360
+ return { config: null, error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path3}` };
6095
6361
  }
6096
6362
  return { config };
6097
6363
  } catch (err) {
6098
- return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path2}`) };
6364
+ return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path3}`) };
6099
6365
  }
6100
6366
  }
6101
6367
  function ensureConfigDir() {
6102
6368
  const configDir = getConfigDir();
6103
- if (!existsSync3(configDir)) {
6369
+ if (!existsSync4(configDir)) {
6104
6370
  mkdirSync(configDir, { recursive: true });
6105
6371
  }
6106
6372
  }
@@ -6110,25 +6376,25 @@ async function addPluginToOpenCodeConfig(currentVersion) {
6110
6376
  } catch (err) {
6111
6377
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6112
6378
  }
6113
- const { format: format2, path: path2 } = detectConfigFormat();
6379
+ const { format: format2, path: path3 } = detectConfigFormat();
6114
6380
  const pluginEntry = await getPluginNameWithVersion(currentVersion);
6115
6381
  try {
6116
6382
  if (format2 === "none") {
6117
6383
  const config2 = { plugin: [pluginEntry] };
6118
- writeFileSync(path2, JSON.stringify(config2, null, 2) + `
6384
+ writeFileSync(path3, JSON.stringify(config2, null, 2) + `
6119
6385
  `);
6120
- return { success: true, configPath: path2 };
6386
+ return { success: true, configPath: path3 };
6121
6387
  }
6122
- const parseResult = parseConfigWithError(path2);
6388
+ const parseResult = parseConfigWithError(path3);
6123
6389
  if (!parseResult.config) {
6124
- return { success: false, configPath: path2, error: parseResult.error ?? "Failed to parse config file" };
6390
+ return { success: false, configPath: path3, error: parseResult.error ?? "Failed to parse config file" };
6125
6391
  }
6126
6392
  const config = parseResult.config;
6127
6393
  const plugins = config.plugin ?? [];
6128
6394
  const existingIndex = plugins.findIndex((p2) => p2 === PACKAGE_NAME || p2.startsWith(`${PACKAGE_NAME}@`));
6129
6395
  if (existingIndex !== -1) {
6130
6396
  if (plugins[existingIndex] === pluginEntry) {
6131
- return { success: true, configPath: path2 };
6397
+ return { success: true, configPath: path3 };
6132
6398
  }
6133
6399
  plugins[existingIndex] = pluginEntry;
6134
6400
  } else {
@@ -6136,7 +6402,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
6136
6402
  }
6137
6403
  config.plugin = plugins;
6138
6404
  if (format2 === "jsonc") {
6139
- const content = readFileSync2(path2, "utf-8");
6405
+ const content = readFileSync3(path3, "utf-8");
6140
6406
  const pluginArrayRegex = /"plugin"\s*:\s*\[([\s\S]*?)\]/;
6141
6407
  const match = content.match(pluginArrayRegex);
6142
6408
  if (match) {
@@ -6145,19 +6411,19 @@ async function addPluginToOpenCodeConfig(currentVersion) {
6145
6411
  const newContent = content.replace(pluginArrayRegex, `"plugin": [
6146
6412
  ${formattedPlugins}
6147
6413
  ]`);
6148
- writeFileSync(path2, newContent);
6414
+ writeFileSync(path3, newContent);
6149
6415
  } else {
6150
6416
  const newContent = content.replace(/^(\s*\{)/, `$1
6151
6417
  "plugin": ["${pluginEntry}"],`);
6152
- writeFileSync(path2, newContent);
6418
+ writeFileSync(path3, newContent);
6153
6419
  }
6154
6420
  } else {
6155
- writeFileSync(path2, JSON.stringify(config, null, 2) + `
6421
+ writeFileSync(path3, JSON.stringify(config, null, 2) + `
6156
6422
  `);
6157
6423
  }
6158
- return { success: true, configPath: path2 };
6424
+ return { success: true, configPath: path3 };
6159
6425
  } catch (err) {
6160
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "update opencode config") };
6426
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "update opencode config") };
6161
6427
  }
6162
6428
  }
6163
6429
  function deepMerge(target, source) {
@@ -6174,63 +6440,7 @@ function deepMerge(target, source) {
6174
6440
  return result;
6175
6441
  }
6176
6442
  function generateOmoConfig(installConfig) {
6177
- const config = {
6178
- $schema: "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json"
6179
- };
6180
- const agents = {};
6181
- if (!installConfig.hasClaude) {
6182
- agents["Sisyphus"] = {
6183
- model: installConfig.hasCopilot ? "github-copilot/claude-opus-4.5" : "opencode/glm-4.7-free"
6184
- };
6185
- }
6186
- agents["librarian"] = { model: "opencode/glm-4.7-free" };
6187
- if (installConfig.hasGemini) {
6188
- agents["explore"] = { model: "google/antigravity-gemini-3-flash" };
6189
- } else if (installConfig.hasClaude && installConfig.isMax20) {
6190
- agents["explore"] = { model: "anthropic/claude-haiku-4-5" };
6191
- } else if (installConfig.hasCopilot) {
6192
- agents["explore"] = { model: "github-copilot/grok-code-fast-1" };
6193
- } else {
6194
- agents["explore"] = { model: "opencode/glm-4.7-free" };
6195
- }
6196
- if (!installConfig.hasChatGPT) {
6197
- const oracleFallback = installConfig.hasCopilot ? "github-copilot/gpt-5.2" : installConfig.hasClaude ? "anthropic/claude-opus-4-5" : "opencode/glm-4.7-free";
6198
- agents["oracle"] = { model: oracleFallback };
6199
- }
6200
- if (installConfig.hasGemini) {
6201
- agents["frontend-ui-ux-engineer"] = { model: "google/antigravity-gemini-3-pro-high" };
6202
- agents["document-writer"] = { model: "google/antigravity-gemini-3-flash" };
6203
- agents["multimodal-looker"] = { model: "google/antigravity-gemini-3-flash" };
6204
- } else if (installConfig.hasClaude) {
6205
- agents["frontend-ui-ux-engineer"] = { model: "anthropic/claude-opus-4-5" };
6206
- agents["document-writer"] = { model: "anthropic/claude-opus-4-5" };
6207
- agents["multimodal-looker"] = { model: "anthropic/claude-opus-4-5" };
6208
- } else if (installConfig.hasCopilot) {
6209
- agents["frontend-ui-ux-engineer"] = { model: "github-copilot/gemini-3-pro-preview" };
6210
- agents["document-writer"] = { model: "github-copilot/gemini-3-flash-preview" };
6211
- agents["multimodal-looker"] = { model: "github-copilot/gemini-3-flash-preview" };
6212
- } else {
6213
- agents["frontend-ui-ux-engineer"] = { model: "opencode/glm-4.7-free" };
6214
- agents["document-writer"] = { model: "opencode/glm-4.7-free" };
6215
- agents["multimodal-looker"] = { model: "opencode/glm-4.7-free" };
6216
- }
6217
- if (Object.keys(agents).length > 0) {
6218
- config.agents = agents;
6219
- }
6220
- if (installConfig.hasGemini) {
6221
- config.categories = {
6222
- "visual-engineering": { model: "google/gemini-3-pro-high" },
6223
- artistry: { model: "google/gemini-3-pro-high" },
6224
- writing: { model: "google/gemini-3-flash-high" }
6225
- };
6226
- } else if (installConfig.hasCopilot) {
6227
- config.categories = {
6228
- "visual-engineering": { model: "github-copilot/gemini-3-pro-preview" },
6229
- artistry: { model: "github-copilot/gemini-3-pro-preview" },
6230
- writing: { model: "github-copilot/gemini-3-flash-preview" }
6231
- };
6232
- }
6233
- return config;
6443
+ return generateModelConfig(installConfig);
6234
6444
  }
6235
6445
  function writeOmoConfig(installConfig) {
6236
6446
  try {
@@ -6241,10 +6451,10 @@ function writeOmoConfig(installConfig) {
6241
6451
  const omoConfigPath = getOmoConfig();
6242
6452
  try {
6243
6453
  const newConfig = generateOmoConfig(installConfig);
6244
- if (existsSync3(omoConfigPath)) {
6454
+ if (existsSync4(omoConfigPath)) {
6245
6455
  try {
6246
6456
  const stat = statSync(omoConfigPath);
6247
- const content = readFileSync2(omoConfigPath, "utf-8");
6457
+ const content = readFileSync3(omoConfigPath, "utf-8");
6248
6458
  if (stat.size === 0 || isEmptyOrWhitespace(content)) {
6249
6459
  writeFileSync(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
6250
6460
  `);
@@ -6310,11 +6520,11 @@ async function addAuthPlugins(config) {
6310
6520
  } catch (err) {
6311
6521
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6312
6522
  }
6313
- const { format: format2, path: path2 } = detectConfigFormat();
6523
+ const { format: format2, path: path3 } = detectConfigFormat();
6314
6524
  try {
6315
6525
  let existingConfig = null;
6316
6526
  if (format2 !== "none") {
6317
- const parseResult = parseConfigWithError(path2);
6527
+ const parseResult = parseConfigWithError(path3);
6318
6528
  if (parseResult.error && !parseResult.config) {
6319
6529
  existingConfig = {};
6320
6530
  } else {
@@ -6330,11 +6540,11 @@ async function addAuthPlugins(config) {
6330
6540
  }
6331
6541
  }
6332
6542
  const newConfig = { ...existingConfig ?? {}, plugin: plugins };
6333
- writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
6543
+ writeFileSync(path3, JSON.stringify(newConfig, null, 2) + `
6334
6544
  `);
6335
- return { success: true, configPath: path2 };
6545
+ return { success: true, configPath: path3 };
6336
6546
  } catch (err) {
6337
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "add auth plugins to config") };
6547
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "add auth plugins to config") };
6338
6548
  }
6339
6549
  }
6340
6550
  async function runBunInstall() {
@@ -6383,11 +6593,11 @@ function addProviderConfig(config) {
6383
6593
  } catch (err) {
6384
6594
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6385
6595
  }
6386
- const { format: format2, path: path2 } = detectConfigFormat();
6596
+ const { format: format2, path: path3 } = detectConfigFormat();
6387
6597
  try {
6388
6598
  let existingConfig = null;
6389
6599
  if (format2 !== "none") {
6390
- const parseResult = parseConfigWithError(path2);
6600
+ const parseResult = parseConfigWithError(path3);
6391
6601
  if (parseResult.error && !parseResult.config) {
6392
6602
  existingConfig = {};
6393
6603
  } else {
@@ -6402,11 +6612,31 @@ function addProviderConfig(config) {
6402
6612
  if (Object.keys(providers).length > 0) {
6403
6613
  newConfig.provider = providers;
6404
6614
  }
6405
- writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
6615
+ writeFileSync(path3, JSON.stringify(newConfig, null, 2) + `
6406
6616
  `);
6407
- return { success: true, configPath: path2 };
6617
+ return { success: true, configPath: path3 };
6408
6618
  } catch (err) {
6409
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "add provider config") };
6619
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "add provider config") };
6620
+ }
6621
+ }
6622
+ function detectProvidersFromOmoConfig() {
6623
+ const omoConfigPath = getOmoConfig();
6624
+ if (!existsSync4(omoConfigPath)) {
6625
+ return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false };
6626
+ }
6627
+ try {
6628
+ const content = readFileSync3(omoConfigPath, "utf-8");
6629
+ const omoConfig = parseJsonc(content);
6630
+ if (!omoConfig || typeof omoConfig !== "object") {
6631
+ return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false };
6632
+ }
6633
+ const configStr = JSON.stringify(omoConfig);
6634
+ const hasOpenAI = configStr.includes('"openai/');
6635
+ const hasOpencodeZen = configStr.includes('"opencode/');
6636
+ const hasZaiCodingPlan = configStr.includes('"zai-coding-plan/');
6637
+ return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan };
6638
+ } catch {
6639
+ return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false };
6410
6640
  }
6411
6641
  }
6412
6642
  function detectCurrentConfig() {
@@ -6414,15 +6644,17 @@ function detectCurrentConfig() {
6414
6644
  isInstalled: false,
6415
6645
  hasClaude: true,
6416
6646
  isMax20: true,
6417
- hasChatGPT: true,
6647
+ hasOpenAI: true,
6418
6648
  hasGemini: false,
6419
- hasCopilot: false
6649
+ hasCopilot: false,
6650
+ hasOpencodeZen: true,
6651
+ hasZaiCodingPlan: false
6420
6652
  };
6421
- const { format: format2, path: path2 } = detectConfigFormat();
6653
+ const { format: format2, path: path3 } = detectConfigFormat();
6422
6654
  if (format2 === "none") {
6423
6655
  return result;
6424
6656
  }
6425
- const parseResult = parseConfigWithError(path2);
6657
+ const parseResult = parseConfigWithError(path3);
6426
6658
  if (!parseResult.config) {
6427
6659
  return result;
6428
6660
  }
@@ -6433,44 +6665,16 @@ function detectCurrentConfig() {
6433
6665
  return result;
6434
6666
  }
6435
6667
  result.hasGemini = plugins.some((p2) => p2.startsWith("opencode-antigravity-auth"));
6436
- const omoConfigPath = getOmoConfig();
6437
- if (!existsSync3(omoConfigPath)) {
6438
- return result;
6439
- }
6440
- try {
6441
- const stat = statSync(omoConfigPath);
6442
- if (stat.size === 0) {
6443
- return result;
6444
- }
6445
- const content = readFileSync2(omoConfigPath, "utf-8");
6446
- if (isEmptyOrWhitespace(content)) {
6447
- return result;
6448
- }
6449
- const omoConfig = parseJsonc(content);
6450
- if (!omoConfig || typeof omoConfig !== "object") {
6451
- return result;
6452
- }
6453
- const agents = omoConfig.agents ?? {};
6454
- if (agents["Sisyphus"]?.model === "opencode/glm-4.7-free") {
6455
- result.hasClaude = false;
6456
- result.isMax20 = false;
6457
- } else if (agents["librarian"]?.model === "opencode/glm-4.7-free") {
6458
- result.hasClaude = true;
6459
- result.isMax20 = false;
6460
- }
6461
- if (agents["oracle"]?.model?.startsWith("anthropic/")) {
6462
- result.hasChatGPT = false;
6463
- } else if (agents["oracle"]?.model === "opencode/glm-4.7-free") {
6464
- result.hasChatGPT = false;
6465
- }
6466
- const hasAnyCopilotModel = Object.values(agents).some((agent) => agent?.model?.startsWith("github-copilot/"));
6467
- result.hasCopilot = hasAnyCopilotModel;
6468
- } catch {}
6668
+ const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan } = detectProvidersFromOmoConfig();
6669
+ result.hasOpenAI = hasOpenAI;
6670
+ result.hasOpencodeZen = hasOpencodeZen;
6671
+ result.hasZaiCodingPlan = hasZaiCodingPlan;
6469
6672
  return result;
6470
6673
  }
6471
6674
  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;
6472
6675
  var init_config_manager = __esm(() => {
6473
6676
  init_shared();
6677
+ init_model_fallback();
6474
6678
  OPENCODE_BINARIES = ["opencode", "opencode-desktop"];
6475
6679
  BUN_INSTALL_TIMEOUT_MS = BUN_INSTALL_TIMEOUT_SECONDS * 1000;
6476
6680
  PRIORITIZED_TAGS = ["latest", "beta", "next"];
@@ -6478,25 +6682,48 @@ var init_config_manager = __esm(() => {
6478
6682
  google: {
6479
6683
  name: "Google",
6480
6684
  models: {
6481
- "antigravity-gemini-3-pro-high": {
6482
- name: "Gemini 3 Pro High (Antigravity)",
6483
- thinking: true,
6484
- attachment: true,
6685
+ "antigravity-gemini-3-pro": {
6686
+ name: "Gemini 3 Pro (Antigravity)",
6485
6687
  limit: { context: 1048576, output: 65535 },
6486
- modalities: { input: ["text", "image", "pdf"], output: ["text"] }
6487
- },
6488
- "antigravity-gemini-3-pro-low": {
6489
- name: "Gemini 3 Pro Low (Antigravity)",
6490
- thinking: true,
6491
- attachment: true,
6492
- limit: { context: 1048576, output: 65535 },
6493
- modalities: { input: ["text", "image", "pdf"], output: ["text"] }
6688
+ modalities: { input: ["text", "image", "pdf"], output: ["text"] },
6689
+ variants: {
6690
+ low: { thinkingLevel: "low" },
6691
+ high: { thinkingLevel: "high" }
6692
+ }
6494
6693
  },
6495
6694
  "antigravity-gemini-3-flash": {
6496
6695
  name: "Gemini 3 Flash (Antigravity)",
6497
- attachment: true,
6498
6696
  limit: { context: 1048576, output: 65536 },
6697
+ modalities: { input: ["text", "image", "pdf"], output: ["text"] },
6698
+ variants: {
6699
+ minimal: { thinkingLevel: "minimal" },
6700
+ low: { thinkingLevel: "low" },
6701
+ medium: { thinkingLevel: "medium" },
6702
+ high: { thinkingLevel: "high" }
6703
+ }
6704
+ },
6705
+ "antigravity-claude-sonnet-4-5": {
6706
+ name: "Claude Sonnet 4.5 (Antigravity)",
6707
+ limit: { context: 200000, output: 64000 },
6499
6708
  modalities: { input: ["text", "image", "pdf"], output: ["text"] }
6709
+ },
6710
+ "antigravity-claude-sonnet-4-5-thinking": {
6711
+ name: "Claude Sonnet 4.5 Thinking (Antigravity)",
6712
+ limit: { context: 200000, output: 64000 },
6713
+ modalities: { input: ["text", "image", "pdf"], output: ["text"] },
6714
+ variants: {
6715
+ low: { thinkingConfig: { thinkingBudget: 8192 } },
6716
+ max: { thinkingConfig: { thinkingBudget: 32768 } }
6717
+ }
6718
+ },
6719
+ "antigravity-claude-opus-4-5-thinking": {
6720
+ name: "Claude Opus 4.5 Thinking (Antigravity)",
6721
+ limit: { context: 200000, output: 64000 },
6722
+ modalities: { input: ["text", "image", "pdf"], output: ["text"] },
6723
+ variants: {
6724
+ low: { thinkingConfig: { thinkingBudget: 8192 } },
6725
+ max: { thinkingConfig: { thinkingBudget: 32768 } }
6726
+ }
6500
6727
  }
6501
6728
  }
6502
6729
  }
@@ -6504,56 +6731,43 @@ var init_config_manager = __esm(() => {
6504
6731
  });
6505
6732
 
6506
6733
  // src/hooks/auto-update-checker/constants.ts
6507
- import * as path2 from "path";
6508
- import * as os2 from "os";
6509
- import * as fs2 from "fs";
6734
+ import * as path3 from "path";
6735
+ import * as os3 from "os";
6510
6736
  function getCacheDir() {
6511
6737
  if (process.platform === "win32") {
6512
- return path2.join(process.env.LOCALAPPDATA ?? os2.homedir(), "opencode");
6513
- }
6514
- return path2.join(os2.homedir(), ".cache", "opencode");
6515
- }
6516
- function getUserConfigDir() {
6517
- if (process.platform === "win32") {
6518
- const crossPlatformDir = path2.join(os2.homedir(), ".config");
6519
- const appdataDir = process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
6520
- const crossPlatformConfig = path2.join(crossPlatformDir, "opencode", "opencode.json");
6521
- const crossPlatformConfigJsonc = path2.join(crossPlatformDir, "opencode", "opencode.jsonc");
6522
- if (fs2.existsSync(crossPlatformConfig) || fs2.existsSync(crossPlatformConfigJsonc)) {
6523
- return crossPlatformDir;
6524
- }
6525
- return appdataDir;
6738
+ return path3.join(process.env.LOCALAPPDATA ?? os3.homedir(), "opencode");
6526
6739
  }
6527
- return process.env.XDG_CONFIG_HOME ?? path2.join(os2.homedir(), ".config");
6740
+ return path3.join(os3.homedir(), ".cache", "opencode");
6528
6741
  }
6529
6742
  function getWindowsAppdataDir() {
6530
6743
  if (process.platform !== "win32")
6531
6744
  return null;
6532
- return process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
6745
+ return process.env.APPDATA ?? path3.join(os3.homedir(), "AppData", "Roaming");
6533
6746
  }
6534
6747
  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;
6535
6748
  var init_constants = __esm(() => {
6749
+ init_shared();
6536
6750
  NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
6537
6751
  CACHE_DIR = getCacheDir();
6538
- VERSION_FILE = path2.join(CACHE_DIR, "version");
6539
- INSTALLED_PACKAGE_JSON = path2.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
6540
- USER_CONFIG_DIR = getUserConfigDir();
6541
- USER_OPENCODE_CONFIG = path2.join(USER_CONFIG_DIR, "opencode", "opencode.json");
6542
- USER_OPENCODE_CONFIG_JSONC = path2.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
6752
+ VERSION_FILE = path3.join(CACHE_DIR, "version");
6753
+ INSTALLED_PACKAGE_JSON = path3.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
6754
+ USER_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" });
6755
+ USER_OPENCODE_CONFIG = path3.join(USER_CONFIG_DIR, "opencode.json");
6756
+ USER_OPENCODE_CONFIG_JSONC = path3.join(USER_CONFIG_DIR, "opencode.jsonc");
6543
6757
  });
6544
6758
 
6545
6759
  // src/hooks/auto-update-checker/cache.ts
6546
- import * as fs3 from "fs";
6547
- import * as path3 from "path";
6760
+ import * as fs2 from "fs";
6761
+ import * as path4 from "path";
6548
6762
  function stripTrailingCommas(json2) {
6549
6763
  return json2.replace(/,(\s*[}\]])/g, "$1");
6550
6764
  }
6551
6765
  function removeFromBunLock(packageName) {
6552
- const lockPath = path3.join(CACHE_DIR, "bun.lock");
6553
- if (!fs3.existsSync(lockPath))
6766
+ const lockPath = path4.join(CACHE_DIR, "bun.lock");
6767
+ if (!fs2.existsSync(lockPath))
6554
6768
  return false;
6555
6769
  try {
6556
- const content = fs3.readFileSync(lockPath, "utf-8");
6770
+ const content = fs2.readFileSync(lockPath, "utf-8");
6557
6771
  const lock = JSON.parse(stripTrailingCommas(content));
6558
6772
  let modified = false;
6559
6773
  if (lock.workspaces?.[""]?.dependencies?.[packageName]) {
@@ -6565,7 +6779,7 @@ function removeFromBunLock(packageName) {
6565
6779
  modified = true;
6566
6780
  }
6567
6781
  if (modified) {
6568
- fs3.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
6782
+ fs2.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
6569
6783
  log(`[auto-update-checker] Removed from bun.lock: ${packageName}`);
6570
6784
  }
6571
6785
  return modified;
@@ -6575,22 +6789,22 @@ function removeFromBunLock(packageName) {
6575
6789
  }
6576
6790
  function invalidatePackage(packageName = PACKAGE_NAME2) {
6577
6791
  try {
6578
- const pkgDir = path3.join(CACHE_DIR, "node_modules", packageName);
6579
- const pkgJsonPath = path3.join(CACHE_DIR, "package.json");
6792
+ const pkgDir = path4.join(CACHE_DIR, "node_modules", packageName);
6793
+ const pkgJsonPath = path4.join(CACHE_DIR, "package.json");
6580
6794
  let packageRemoved = false;
6581
6795
  let dependencyRemoved = false;
6582
6796
  let lockRemoved = false;
6583
- if (fs3.existsSync(pkgDir)) {
6584
- fs3.rmSync(pkgDir, { recursive: true, force: true });
6797
+ if (fs2.existsSync(pkgDir)) {
6798
+ fs2.rmSync(pkgDir, { recursive: true, force: true });
6585
6799
  log(`[auto-update-checker] Package removed: ${pkgDir}`);
6586
6800
  packageRemoved = true;
6587
6801
  }
6588
- if (fs3.existsSync(pkgJsonPath)) {
6589
- const content = fs3.readFileSync(pkgJsonPath, "utf-8");
6802
+ if (fs2.existsSync(pkgJsonPath)) {
6803
+ const content = fs2.readFileSync(pkgJsonPath, "utf-8");
6590
6804
  const pkgJson = JSON.parse(content);
6591
6805
  if (pkgJson.dependencies?.[packageName]) {
6592
6806
  delete pkgJson.dependencies[packageName];
6593
- fs3.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
6807
+ fs2.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
6594
6808
  log(`[auto-update-checker] Dependency removed from package.json: ${packageName}`);
6595
6809
  dependencyRemoved = true;
6596
6810
  }
@@ -6682,6 +6896,7 @@ v${latestVersion} available. Restart OpenCode to apply.` : `OpenCode is now on S
6682
6896
  const localDevVersion = getLocalDevVersion(ctx.directory);
6683
6897
  const displayVersion = localDevVersion ?? cachedVersion;
6684
6898
  await showConfigErrorsIfAny(ctx);
6899
+ await showModelCacheWarningIfNeeded(ctx);
6685
6900
  if (localDevVersion) {
6686
6901
  if (showStartupToast) {
6687
6902
  showLocalDevToast(ctx, displayVersion, isSisyphusEnabled).catch(() => {});
@@ -6755,6 +6970,19 @@ async function runBunInstallSafe() {
6755
6970
  return false;
6756
6971
  }
6757
6972
  }
6973
+ async function showModelCacheWarningIfNeeded(ctx) {
6974
+ if (isModelCacheAvailable())
6975
+ return;
6976
+ await ctx.client.tui.showToast({
6977
+ body: {
6978
+ title: "Model Cache Not Found",
6979
+ message: "Run 'opencode models --refresh' or restart OpenCode to populate the models cache for optimal agent model selection.",
6980
+ variant: "warning",
6981
+ duration: 1e4
6982
+ }
6983
+ }).catch(() => {});
6984
+ log("[auto-update-checker] Model cache warning shown");
6985
+ }
6758
6986
  async function showConfigErrorsIfAny(ctx) {
6759
6987
  const errors = getConfigLoadErrors();
6760
6988
  if (errors.length === 0)
@@ -6832,16 +7060,17 @@ var init_auto_update_checker = __esm(() => {
6832
7060
  init_logger();
6833
7061
  init_config_errors();
6834
7062
  init_config_manager();
7063
+ init_model_availability();
6835
7064
  init_checker();
6836
7065
  init_cache();
6837
7066
  SISYPHUS_SPINNER = ["\xB7", "\u2022", "\u25CF", "\u25CB", "\u25CC", "\u25E6", " "];
6838
7067
  });
6839
7068
 
6840
7069
  // src/hooks/auto-update-checker/checker.ts
6841
- import * as fs4 from "fs";
6842
- import * as path4 from "path";
7070
+ import * as fs3 from "fs";
7071
+ import * as path5 from "path";
6843
7072
  import { fileURLToPath } from "url";
6844
- import * as os3 from "os";
7073
+ import * as os4 from "os";
6845
7074
  function isLocalDevMode(directory) {
6846
7075
  return getLocalDevPath(directory) !== null;
6847
7076
  }
@@ -6850,18 +7079,18 @@ function stripJsonComments(json2) {
6850
7079
  }
6851
7080
  function getConfigPaths(directory) {
6852
7081
  const paths = [
6853
- path4.join(directory, ".opencode", "opencode.json"),
6854
- path4.join(directory, ".opencode", "opencode.jsonc"),
7082
+ path5.join(directory, ".opencode", "opencode.json"),
7083
+ path5.join(directory, ".opencode", "opencode.jsonc"),
6855
7084
  USER_OPENCODE_CONFIG,
6856
7085
  USER_OPENCODE_CONFIG_JSONC
6857
7086
  ];
6858
7087
  if (process.platform === "win32") {
6859
- const crossPlatformDir = path4.join(os3.homedir(), ".config");
7088
+ const crossPlatformDir = path5.join(os4.homedir(), ".config");
6860
7089
  const appdataDir = getWindowsAppdataDir();
6861
7090
  if (appdataDir) {
6862
7091
  const alternateDir = USER_CONFIG_DIR === crossPlatformDir ? appdataDir : crossPlatformDir;
6863
- const alternateConfig = path4.join(alternateDir, "opencode", "opencode.json");
6864
- const alternateConfigJsonc = path4.join(alternateDir, "opencode", "opencode.jsonc");
7092
+ const alternateConfig = path5.join(alternateDir, "opencode", "opencode.json");
7093
+ const alternateConfigJsonc = path5.join(alternateDir, "opencode", "opencode.jsonc");
6865
7094
  if (!paths.includes(alternateConfig)) {
6866
7095
  paths.push(alternateConfig);
6867
7096
  }
@@ -6875,9 +7104,9 @@ function getConfigPaths(directory) {
6875
7104
  function getLocalDevPath(directory) {
6876
7105
  for (const configPath of getConfigPaths(directory)) {
6877
7106
  try {
6878
- if (!fs4.existsSync(configPath))
7107
+ if (!fs3.existsSync(configPath))
6879
7108
  continue;
6880
- const content = fs4.readFileSync(configPath, "utf-8");
7109
+ const content = fs3.readFileSync(configPath, "utf-8");
6881
7110
  const config = JSON.parse(stripJsonComments(content));
6882
7111
  const plugins = config.plugin ?? [];
6883
7112
  for (const entry of plugins) {
@@ -6897,19 +7126,19 @@ function getLocalDevPath(directory) {
6897
7126
  }
6898
7127
  function findPackageJsonUp(startPath) {
6899
7128
  try {
6900
- const stat = fs4.statSync(startPath);
6901
- let dir = stat.isDirectory() ? startPath : path4.dirname(startPath);
7129
+ const stat = fs3.statSync(startPath);
7130
+ let dir = stat.isDirectory() ? startPath : path5.dirname(startPath);
6902
7131
  for (let i2 = 0;i2 < 10; i2++) {
6903
- const pkgPath = path4.join(dir, "package.json");
6904
- if (fs4.existsSync(pkgPath)) {
7132
+ const pkgPath = path5.join(dir, "package.json");
7133
+ if (fs3.existsSync(pkgPath)) {
6905
7134
  try {
6906
- const content = fs4.readFileSync(pkgPath, "utf-8");
7135
+ const content = fs3.readFileSync(pkgPath, "utf-8");
6907
7136
  const pkg = JSON.parse(content);
6908
7137
  if (pkg.name === PACKAGE_NAME2)
6909
7138
  return pkgPath;
6910
7139
  } catch {}
6911
7140
  }
6912
- const parent = path4.dirname(dir);
7141
+ const parent = path5.dirname(dir);
6913
7142
  if (parent === dir)
6914
7143
  break;
6915
7144
  dir = parent;
@@ -6925,7 +7154,7 @@ function getLocalDevVersion(directory) {
6925
7154
  const pkgPath = findPackageJsonUp(localPath);
6926
7155
  if (!pkgPath)
6927
7156
  return null;
6928
- const content = fs4.readFileSync(pkgPath, "utf-8");
7157
+ const content = fs3.readFileSync(pkgPath, "utf-8");
6929
7158
  const pkg = JSON.parse(content);
6930
7159
  return pkg.version ?? null;
6931
7160
  } catch {
@@ -6935,9 +7164,9 @@ function getLocalDevVersion(directory) {
6935
7164
  function findPluginEntry(directory) {
6936
7165
  for (const configPath of getConfigPaths(directory)) {
6937
7166
  try {
6938
- if (!fs4.existsSync(configPath))
7167
+ if (!fs3.existsSync(configPath))
6939
7168
  continue;
6940
- const content = fs4.readFileSync(configPath, "utf-8");
7169
+ const content = fs3.readFileSync(configPath, "utf-8");
6941
7170
  const config = JSON.parse(stripJsonComments(content));
6942
7171
  const plugins = config.plugin ?? [];
6943
7172
  for (const entry of plugins) {
@@ -6958,18 +7187,18 @@ function findPluginEntry(directory) {
6958
7187
  }
6959
7188
  function getCachedVersion() {
6960
7189
  try {
6961
- if (fs4.existsSync(INSTALLED_PACKAGE_JSON)) {
6962
- const content = fs4.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
7190
+ if (fs3.existsSync(INSTALLED_PACKAGE_JSON)) {
7191
+ const content = fs3.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
6963
7192
  const pkg = JSON.parse(content);
6964
7193
  if (pkg.version)
6965
7194
  return pkg.version;
6966
7195
  }
6967
7196
  } catch {}
6968
7197
  try {
6969
- const currentDir = path4.dirname(fileURLToPath(import.meta.url));
7198
+ const currentDir = path5.dirname(fileURLToPath(import.meta.url));
6970
7199
  const pkgPath = findPackageJsonUp(currentDir);
6971
7200
  if (pkgPath) {
6972
- const content = fs4.readFileSync(pkgPath, "utf-8");
7201
+ const content = fs3.readFileSync(pkgPath, "utf-8");
6973
7202
  const pkg = JSON.parse(content);
6974
7203
  if (pkg.version)
6975
7204
  return pkg.version;
@@ -6981,7 +7210,7 @@ function getCachedVersion() {
6981
7210
  }
6982
7211
  function updatePinnedVersion(configPath, oldEntry, newVersion) {
6983
7212
  try {
6984
- const content = fs4.readFileSync(configPath, "utf-8");
7213
+ const content = fs3.readFileSync(configPath, "utf-8");
6985
7214
  const newEntry = `${PACKAGE_NAME2}@${newVersion}`;
6986
7215
  const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
6987
7216
  if (!pluginMatch || pluginMatch.index === undefined) {
@@ -7013,7 +7242,7 @@ function updatePinnedVersion(configPath, oldEntry, newVersion) {
7013
7242
  log(`[auto-update-checker] No changes made to ${configPath}`);
7014
7243
  return false;
7015
7244
  }
7016
- fs4.writeFileSync(configPath, updatedContent, "utf-8");
7245
+ fs3.writeFileSync(configPath, updatedContent, "utf-8");
7017
7246
  log(`[auto-update-checker] Updated ${configPath}: ${oldEntry} \u2192 ${newEntry}`);
7018
7247
  return true;
7019
7248
  } catch (err) {
@@ -7672,7 +7901,7 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
7672
7901
  // package.json
7673
7902
  var package_default = {
7674
7903
  name: "oh-my-opencode",
7675
- version: "3.0.0-beta.9",
7904
+ version: "3.0.1",
7676
7905
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
7677
7906
  main: "dist/index.js",
7678
7907
  types: "dist/index.d.ts",
@@ -7728,18 +7957,14 @@ var package_default = {
7728
7957
  "@clack/prompts": "^0.11.0",
7729
7958
  "@code-yeongyu/comment-checker": "^0.6.1",
7730
7959
  "@modelcontextprotocol/sdk": "^1.25.1",
7731
- "@openauthjs/openauth": "^0.4.3",
7732
7960
  "@opencode-ai/plugin": "^1.1.19",
7733
7961
  "@opencode-ai/sdk": "^1.1.19",
7734
7962
  commander: "^14.0.2",
7735
7963
  "detect-libc": "^2.0.0",
7736
- hono: "^4.10.4",
7737
7964
  "js-yaml": "^4.1.1",
7738
7965
  "jsonc-parser": "^3.3.1",
7739
- open: "^11.0.0",
7740
7966
  picocolors: "^1.1.1",
7741
7967
  picomatch: "^4.0.2",
7742
- "xdg-basedir": "^5.1.0",
7743
7968
  zod: "^4.1.8"
7744
7969
  },
7745
7970
  devDependencies: {
@@ -7749,13 +7974,13 @@ var package_default = {
7749
7974
  typescript: "^5.7.3"
7750
7975
  },
7751
7976
  optionalDependencies: {
7752
- "oh-my-opencode-darwin-arm64": "3.0.0-beta.9",
7753
- "oh-my-opencode-darwin-x64": "3.0.0-beta.9",
7754
- "oh-my-opencode-linux-arm64": "3.0.0-beta.9",
7755
- "oh-my-opencode-linux-arm64-musl": "3.0.0-beta.9",
7756
- "oh-my-opencode-linux-x64": "3.0.0-beta.9",
7757
- "oh-my-opencode-linux-x64-musl": "3.0.0-beta.9",
7758
- "oh-my-opencode-windows-x64": "3.0.0-beta.9"
7977
+ "oh-my-opencode-darwin-arm64": "3.0.1",
7978
+ "oh-my-opencode-darwin-x64": "3.0.1",
7979
+ "oh-my-opencode-linux-arm64": "3.0.1",
7980
+ "oh-my-opencode-linux-arm64-musl": "3.0.1",
7981
+ "oh-my-opencode-linux-x64": "3.0.1",
7982
+ "oh-my-opencode-linux-x64-musl": "3.0.1",
7983
+ "oh-my-opencode-windows-x64": "3.0.1"
7759
7984
  },
7760
7985
  trustedDependencies: [
7761
7986
  "@ast-grep/cli",
@@ -7767,13 +7992,13 @@ var package_default = {
7767
7992
  // src/cli/install.ts
7768
7993
  var VERSION = package_default.version;
7769
7994
  var SYMBOLS = {
7770
- check: import_picocolors2.default.green("\u2713"),
7771
- cross: import_picocolors2.default.red("\u2717"),
7772
- arrow: import_picocolors2.default.cyan("\u2192"),
7773
- bullet: import_picocolors2.default.dim("\u2022"),
7774
- info: import_picocolors2.default.blue("\u2139"),
7775
- warn: import_picocolors2.default.yellow("\u26A0"),
7776
- star: import_picocolors2.default.yellow("\u2605")
7995
+ check: import_picocolors2.default.green("[OK]"),
7996
+ cross: import_picocolors2.default.red("[X]"),
7997
+ arrow: import_picocolors2.default.cyan("->"),
7998
+ bullet: import_picocolors2.default.dim("*"),
7999
+ info: import_picocolors2.default.blue("[i]"),
8000
+ warn: import_picocolors2.default.yellow("[!]"),
8001
+ star: import_picocolors2.default.yellow("*")
7777
8002
  };
7778
8003
  function formatProvider(name, enabled, detail) {
7779
8004
  const status = enabled ? SYMBOLS.check : import_picocolors2.default.dim("\u25CB");
@@ -7787,22 +8012,18 @@ function formatConfigSummary(config) {
7787
8012
  lines.push("");
7788
8013
  const claudeDetail = config.hasClaude ? config.isMax20 ? "max20" : "standard" : undefined;
7789
8014
  lines.push(formatProvider("Claude", config.hasClaude, claudeDetail));
7790
- lines.push(formatProvider("ChatGPT", config.hasChatGPT));
8015
+ lines.push(formatProvider("OpenAI/ChatGPT", config.hasOpenAI, "GPT-5.2 for Oracle"));
7791
8016
  lines.push(formatProvider("Gemini", config.hasGemini));
7792
- lines.push(formatProvider("GitHub Copilot", config.hasCopilot, "fallback provider"));
8017
+ lines.push(formatProvider("GitHub Copilot", config.hasCopilot, "fallback"));
8018
+ lines.push(formatProvider("OpenCode Zen", config.hasOpencodeZen, "opencode/ models"));
8019
+ lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "Librarian/Multimodal"));
7793
8020
  lines.push("");
7794
8021
  lines.push(import_picocolors2.default.dim("\u2500".repeat(40)));
7795
8022
  lines.push("");
7796
- lines.push(import_picocolors2.default.bold(import_picocolors2.default.white("Agent Configuration")));
8023
+ lines.push(import_picocolors2.default.bold(import_picocolors2.default.white("Model Assignment")));
7797
8024
  lines.push("");
7798
- const sisyphusModel = config.hasClaude ? "claude-opus-4-5" : config.hasCopilot ? "github-copilot/claude-opus-4.5" : "glm-4.7-free";
7799
- const oracleModel = config.hasChatGPT ? "gpt-5.2" : config.hasCopilot ? "github-copilot/gpt-5.2" : config.hasClaude ? "claude-opus-4-5" : "glm-4.7-free";
7800
- const librarianModel = "glm-4.7-free";
7801
- const frontendModel = config.hasGemini ? "antigravity-gemini-3-pro-high" : config.hasClaude ? "claude-opus-4-5" : "glm-4.7-free";
7802
- lines.push(` ${SYMBOLS.bullet} Sisyphus ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(sisyphusModel)}`);
7803
- lines.push(` ${SYMBOLS.bullet} Oracle ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(oracleModel)}`);
7804
- lines.push(` ${SYMBOLS.bullet} Librarian ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(librarianModel)}`);
7805
- lines.push(` ${SYMBOLS.bullet} Frontend ${SYMBOLS.arrow} ${import_picocolors2.default.cyan(frontendModel)}`);
8025
+ lines.push(` ${SYMBOLS.info} Models auto-configured based on provider priority`);
8026
+ lines.push(` ${SYMBOLS.bullet} Priority: Native > Copilot > OpenCode Zen > Z.ai`);
7806
8027
  return lines.join(`
7807
8028
  `);
7808
8029
  }
@@ -7854,11 +8075,6 @@ function validateNonTuiArgs(args) {
7854
8075
  } else if (!["no", "yes", "max20"].includes(args.claude)) {
7855
8076
  errors.push(`Invalid --claude value: ${args.claude} (expected: no, yes, max20)`);
7856
8077
  }
7857
- if (args.chatgpt === undefined) {
7858
- errors.push("--chatgpt is required (values: no, yes)");
7859
- } else if (!["no", "yes"].includes(args.chatgpt)) {
7860
- errors.push(`Invalid --chatgpt value: ${args.chatgpt} (expected: no, yes)`);
7861
- }
7862
8078
  if (args.gemini === undefined) {
7863
8079
  errors.push("--gemini is required (values: no, yes)");
7864
8080
  } else if (!["no", "yes"].includes(args.gemini)) {
@@ -7869,15 +8085,26 @@ function validateNonTuiArgs(args) {
7869
8085
  } else if (!["no", "yes"].includes(args.copilot)) {
7870
8086
  errors.push(`Invalid --copilot value: ${args.copilot} (expected: no, yes)`);
7871
8087
  }
8088
+ if (args.openai !== undefined && !["no", "yes"].includes(args.openai)) {
8089
+ errors.push(`Invalid --openai value: ${args.openai} (expected: no, yes)`);
8090
+ }
8091
+ if (args.opencodeZen !== undefined && !["no", "yes"].includes(args.opencodeZen)) {
8092
+ errors.push(`Invalid --opencode-zen value: ${args.opencodeZen} (expected: no, yes)`);
8093
+ }
8094
+ if (args.zaiCodingPlan !== undefined && !["no", "yes"].includes(args.zaiCodingPlan)) {
8095
+ errors.push(`Invalid --zai-coding-plan value: ${args.zaiCodingPlan} (expected: no, yes)`);
8096
+ }
7872
8097
  return { valid: errors.length === 0, errors };
7873
8098
  }
7874
8099
  function argsToConfig(args) {
7875
8100
  return {
7876
8101
  hasClaude: args.claude !== "no",
7877
8102
  isMax20: args.claude === "max20",
7878
- hasChatGPT: args.chatgpt === "yes",
8103
+ hasOpenAI: args.openai === "yes",
7879
8104
  hasGemini: args.gemini === "yes",
7880
- hasCopilot: args.copilot === "yes"
8105
+ hasCopilot: args.copilot === "yes",
8106
+ hasOpencodeZen: args.opencodeZen === "yes",
8107
+ hasZaiCodingPlan: args.zaiCodingPlan === "yes"
7881
8108
  };
7882
8109
  }
7883
8110
  function detectedToInitialValues(detected) {
@@ -7887,9 +8114,11 @@ function detectedToInitialValues(detected) {
7887
8114
  }
7888
8115
  return {
7889
8116
  claude,
7890
- chatgpt: detected.hasChatGPT ? "yes" : "no",
8117
+ openai: detected.hasOpenAI ? "yes" : "no",
7891
8118
  gemini: detected.hasGemini ? "yes" : "no",
7892
- copilot: detected.hasCopilot ? "yes" : "no"
8119
+ copilot: detected.hasCopilot ? "yes" : "no",
8120
+ opencodeZen: detected.hasOpencodeZen ? "yes" : "no",
8121
+ zaiCodingPlan: detected.hasZaiCodingPlan ? "yes" : "no"
7893
8122
  };
7894
8123
  }
7895
8124
  async function runTuiMode(detected) {
@@ -7897,7 +8126,7 @@ async function runTuiMode(detected) {
7897
8126
  const claude = await ve({
7898
8127
  message: "Do you have a Claude Pro/Max subscription?",
7899
8128
  options: [
7900
- { value: "no", label: "No", hint: "Will use opencode/glm-4.7-free as fallback" },
8129
+ { value: "no", label: "No", hint: "Will use opencode/big-pickle as fallback" },
7901
8130
  { value: "yes", label: "Yes (standard)", hint: "Claude Opus 4.5 for orchestration" },
7902
8131
  { value: "max20", label: "Yes (max20 mode)", hint: "Full power with Claude Sonnet 4.5 for Librarian" }
7903
8132
  ],
@@ -7907,15 +8136,15 @@ async function runTuiMode(detected) {
7907
8136
  xe("Installation cancelled.");
7908
8137
  return null;
7909
8138
  }
7910
- const chatgpt = await ve({
7911
- message: "Do you have a ChatGPT Plus/Pro subscription?",
8139
+ const openai = await ve({
8140
+ message: "Do you have an OpenAI/ChatGPT Plus subscription?",
7912
8141
  options: [
7913
- { value: "no", label: "No", hint: "Oracle will use fallback model" },
7914
- { value: "yes", label: "Yes", hint: "GPT-5.2 for debugging and architecture" }
8142
+ { value: "no", label: "No", hint: "Oracle will use fallback models" },
8143
+ { value: "yes", label: "Yes", hint: "GPT-5.2 for Oracle (high-IQ debugging)" }
7915
8144
  ],
7916
- initialValue: initial.chatgpt
8145
+ initialValue: initial.openai
7917
8146
  });
7918
- if (pD(chatgpt)) {
8147
+ if (pD(openai)) {
7919
8148
  xe("Installation cancelled.");
7920
8149
  return null;
7921
8150
  }
@@ -7943,12 +8172,38 @@ async function runTuiMode(detected) {
7943
8172
  xe("Installation cancelled.");
7944
8173
  return null;
7945
8174
  }
8175
+ const opencodeZen = await ve({
8176
+ message: "Do you have access to OpenCode Zen (opencode/ models)?",
8177
+ options: [
8178
+ { value: "no", label: "No", hint: "Will use other configured providers" },
8179
+ { value: "yes", label: "Yes", hint: "opencode/claude-opus-4-5, opencode/gpt-5.2, etc." }
8180
+ ],
8181
+ initialValue: initial.opencodeZen
8182
+ });
8183
+ if (pD(opencodeZen)) {
8184
+ xe("Installation cancelled.");
8185
+ return null;
8186
+ }
8187
+ const zaiCodingPlan = await ve({
8188
+ message: "Do you have a Z.ai Coding Plan subscription?",
8189
+ options: [
8190
+ { value: "no", label: "No", hint: "Will use other configured providers" },
8191
+ { value: "yes", label: "Yes", hint: "Fallback for Librarian and Multimodal Looker" }
8192
+ ],
8193
+ initialValue: initial.zaiCodingPlan
8194
+ });
8195
+ if (pD(zaiCodingPlan)) {
8196
+ xe("Installation cancelled.");
8197
+ return null;
8198
+ }
7946
8199
  return {
7947
8200
  hasClaude: claude !== "no",
7948
8201
  isMax20: claude === "max20",
7949
- hasChatGPT: chatgpt === "yes",
8202
+ hasOpenAI: openai === "yes",
7950
8203
  hasGemini: gemini === "yes",
7951
- hasCopilot: copilot === "yes"
8204
+ hasCopilot: copilot === "yes",
8205
+ hasOpencodeZen: opencodeZen === "yes",
8206
+ hasZaiCodingPlan: zaiCodingPlan === "yes"
7952
8207
  };
7953
8208
  }
7954
8209
  async function runNonTuiInstall(args) {
@@ -7960,7 +8215,7 @@ async function runNonTuiInstall(args) {
7960
8215
  console.log(` ${SYMBOLS.bullet} ${err}`);
7961
8216
  }
7962
8217
  console.log();
7963
- printInfo("Usage: bunx oh-my-opencode install --no-tui --claude=<no|yes|max20> --chatgpt=<no|yes> --gemini=<no|yes> --copilot=<no|yes>");
8218
+ printInfo("Usage: bunx oh-my-opencode install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>");
7964
8219
  console.log();
7965
8220
  return 1;
7966
8221
  }
@@ -7971,16 +8226,16 @@ async function runNonTuiInstall(args) {
7971
8226
  let step = 1;
7972
8227
  printStep(step++, totalSteps, "Checking OpenCode installation...");
7973
8228
  const installed = await isOpenCodeInstalled();
8229
+ const version = await getOpenCodeVersion();
7974
8230
  if (!installed) {
7975
- printError("OpenCode is not installed on this system.");
8231
+ printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
7976
8232
  printInfo("Visit https://opencode.ai/docs for installation instructions");
7977
- return 1;
8233
+ } else {
8234
+ printSuccess(`OpenCode ${version ?? ""} detected`);
7978
8235
  }
7979
- const version = await getOpenCodeVersion();
7980
- printSuccess(`OpenCode ${version ?? ""} detected`);
7981
8236
  if (isUpdate) {
7982
8237
  const initial = detectedToInitialValues(detected);
7983
- printInfo(`Current config: Claude=${initial.claude}, ChatGPT=${initial.chatgpt}, Gemini=${initial.gemini}`);
8238
+ printInfo(`Current config: Claude=${initial.claude}, Gemini=${initial.gemini}`);
7984
8239
  }
7985
8240
  const config = argsToConfig(args);
7986
8241
  printStep(step++, totalSteps, "Adding oh-my-opencode plugin...");
@@ -8016,26 +8271,38 @@ async function runNonTuiInstall(args) {
8016
8271
  }
8017
8272
  printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors2.default.dim(omoResult.configPath)}`);
8018
8273
  printBox(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
8019
- if (!config.hasClaude && !config.hasChatGPT && !config.hasGemini && !config.hasCopilot) {
8020
- printWarning("No model providers configured. Using opencode/glm-4.7-free as fallback.");
8274
+ if (!config.hasClaude) {
8275
+ console.log();
8276
+ console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
8277
+ console.log();
8278
+ console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
8279
+ console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
8280
+ console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
8281
+ console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
8282
+ console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
8283
+ console.log();
8284
+ console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
8285
+ console.log();
8286
+ }
8287
+ if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
8288
+ printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
8021
8289
  }
8022
8290
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.bold(import_picocolors2.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
8023
8291
  console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
8024
8292
  console.log();
8025
8293
  printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
8026
8294
  ` + `All features work like magic\u2014parallel agents, background tasks,
8027
- ` + `deep exploration, and relentless execution until completion.`, "\uD83E\uDE84 The Magic Word");
8295
+ ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
8028
8296
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
8029
8297
  console.log(` ${import_picocolors2.default.dim("gh repo star code-yeongyu/oh-my-opencode")}`);
8030
8298
  console.log();
8031
8299
  console.log(import_picocolors2.default.dim("oMoMoMoMo... Enjoy!"));
8032
8300
  console.log();
8033
- if ((config.hasClaude || config.hasChatGPT || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8301
+ if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8034
8302
  printBox(`Run ${import_picocolors2.default.cyan("opencode auth login")} and select your provider:
8035
8303
  ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}
8036
- ` : "") + (config.hasChatGPT ? ` ${SYMBOLS.bullet} OpenAI ${import_picocolors2.default.gray("\u2192 ChatGPT Plus/Pro")}
8037
8304
  ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors2.default.gray("\u2192 OAuth with Antigravity")}
8038
- ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}` : ""), "\uD83D\uDD10 Authenticate Your Providers");
8305
+ ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}` : ""), "Authenticate Your Providers");
8039
8306
  }
8040
8307
  return 0;
8041
8308
  }
@@ -8048,20 +8315,19 @@ async function install(args) {
8048
8315
  Ie(import_picocolors2.default.bgMagenta(import_picocolors2.default.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")));
8049
8316
  if (isUpdate) {
8050
8317
  const initial = detectedToInitialValues(detected);
8051
- M2.info(`Existing configuration detected: Claude=${initial.claude}, ChatGPT=${initial.chatgpt}, Gemini=${initial.gemini}`);
8318
+ M2.info(`Existing configuration detected: Claude=${initial.claude}, Gemini=${initial.gemini}`);
8052
8319
  }
8053
8320
  const s = Y2();
8054
8321
  s.start("Checking OpenCode installation");
8055
8322
  const installed = await isOpenCodeInstalled();
8323
+ const version = await getOpenCodeVersion();
8056
8324
  if (!installed) {
8057
- s.stop("OpenCode is not installed");
8058
- M2.error("OpenCode is not installed on this system.");
8325
+ s.stop(`OpenCode binary not found ${import_picocolors2.default.yellow("[!]")}`);
8326
+ M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
8059
8327
  Me("Visit https://opencode.ai/docs for installation instructions", "Installation Guide");
8060
- Se(import_picocolors2.default.red("Please install OpenCode first."));
8061
- return 1;
8328
+ } else {
8329
+ s.stop(`OpenCode ${version ?? "installed"} ${import_picocolors2.default.green("[OK]")}`);
8062
8330
  }
8063
- const version = await getOpenCodeVersion();
8064
- s.stop(`OpenCode ${version ?? "installed"} ${import_picocolors2.default.green("\u2713")}`);
8065
8331
  const config = await runTuiMode(detected);
8066
8332
  if (!config)
8067
8333
  return 1;
@@ -8099,30 +8365,41 @@ async function install(args) {
8099
8365
  return 1;
8100
8366
  }
8101
8367
  s.stop(`Config written to ${import_picocolors2.default.cyan(omoResult.configPath)}`);
8102
- if (!config.hasClaude && !config.hasChatGPT && !config.hasGemini && !config.hasCopilot) {
8103
- M2.warn("No model providers configured. Using opencode/glm-4.7-free as fallback.");
8368
+ if (!config.hasClaude) {
8369
+ console.log();
8370
+ console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
8371
+ console.log();
8372
+ console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
8373
+ console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
8374
+ console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
8375
+ console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
8376
+ console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
8377
+ console.log();
8378
+ console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
8379
+ console.log();
8380
+ }
8381
+ if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
8382
+ M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
8104
8383
  }
8105
8384
  Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
8106
8385
  M2.success(import_picocolors2.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
8107
8386
  M2.message(`Run ${import_picocolors2.default.cyan("opencode")} to start!`);
8108
8387
  Me(`Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
8109
8388
  ` + `All features work like magic\u2014parallel agents, background tasks,
8110
- ` + `deep exploration, and relentless execution until completion.`, "\uD83E\uDE84 The Magic Word");
8389
+ ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
8111
8390
  M2.message(`${import_picocolors2.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
8112
8391
  M2.message(` ${import_picocolors2.default.dim("gh repo star code-yeongyu/oh-my-opencode")}`);
8113
8392
  Se(import_picocolors2.default.green("oMoMoMoMo... Enjoy!"));
8114
- if ((config.hasClaude || config.hasChatGPT || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8393
+ if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
8115
8394
  const providers = [];
8116
8395
  if (config.hasClaude)
8117
8396
  providers.push(`Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}`);
8118
- if (config.hasChatGPT)
8119
- providers.push(`OpenAI ${import_picocolors2.default.gray("\u2192 ChatGPT Plus/Pro")}`);
8120
8397
  if (config.hasGemini)
8121
8398
  providers.push(`Google ${import_picocolors2.default.gray("\u2192 OAuth with Antigravity")}`);
8122
8399
  if (config.hasCopilot)
8123
8400
  providers.push(`GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}`);
8124
8401
  console.log();
8125
- console.log(import_picocolors2.default.bold("\uD83D\uDD10 Authenticate Your Providers"));
8402
+ console.log(import_picocolors2.default.bold("Authenticate Your Providers"));
8126
8403
  console.log();
8127
8404
  console.log(` Run ${import_picocolors2.default.cyan("opencode auth login")} and select:`);
8128
8405
  for (const provider of providers) {
@@ -8366,7 +8643,7 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
8366
8643
 
8367
8644
  // node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
8368
8645
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
8369
- var defaultPathSerializer = ({ path: path2, url: _url }) => {
8646
+ var defaultPathSerializer = ({ path: path3, url: _url }) => {
8370
8647
  let url = _url;
8371
8648
  const matches = _url.match(PATH_PARAM_RE);
8372
8649
  if (matches) {
@@ -8385,7 +8662,7 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
8385
8662
  name = name.substring(1);
8386
8663
  style = "matrix";
8387
8664
  }
8388
- const value = path2[name];
8665
+ const value = path3[name];
8389
8666
  if (value === undefined || value === null) {
8390
8667
  continue;
8391
8668
  }
@@ -8416,11 +8693,11 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
8416
8693
  }
8417
8694
  return url;
8418
8695
  };
8419
- var getUrl = ({ baseUrl, path: path2, query, querySerializer, url: _url }) => {
8696
+ var getUrl = ({ baseUrl, path: path3, query, querySerializer, url: _url }) => {
8420
8697
  const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
8421
8698
  let url = (baseUrl ?? "") + pathUrl;
8422
- if (path2) {
8423
- url = defaultPathSerializer({ path: path2, url });
8699
+ if (path3) {
8700
+ url = defaultPathSerializer({ path: path3, url });
8424
8701
  }
8425
8702
  let search = query ? querySerializer(query) : "";
8426
8703
  if (search.startsWith("?")) {
@@ -9736,7 +10013,7 @@ function logEventVerbose(ctx, payload) {
9736
10013
  const toolName = toolProps?.name ?? "unknown";
9737
10014
  const input = toolProps?.input ?? {};
9738
10015
  const inputStr = JSON.stringify(input).slice(0, 150);
9739
- console.error(import_picocolors4.default.cyan(`${sessionTag} \u26A1 TOOL.EXECUTE: ${import_picocolors4.default.bold(toolName)}`));
10016
+ console.error(import_picocolors4.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors4.default.bold(toolName)}`));
9740
10017
  console.error(import_picocolors4.default.dim(` input: ${inputStr}${inputStr.length >= 150 ? "..." : ""}`));
9741
10018
  break;
9742
10019
  }
@@ -9744,13 +10021,13 @@ function logEventVerbose(ctx, payload) {
9744
10021
  const resultProps = props;
9745
10022
  const output = resultProps?.output ?? "";
9746
10023
  const preview = output.slice(0, 200).replace(/\n/g, "\\n");
9747
- console.error(import_picocolors4.default.green(`${sessionTag} \u2713 TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
10024
+ console.error(import_picocolors4.default.green(`${sessionTag} TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
9748
10025
  break;
9749
10026
  }
9750
10027
  case "session.error": {
9751
10028
  const errorProps = props;
9752
10029
  const errorMsg = serializeError(errorProps?.error);
9753
- console.error(import_picocolors4.default.red(`${sessionTag} \u274C SESSION.ERROR: ${errorMsg}`));
10030
+ console.error(import_picocolors4.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
9754
10031
  break;
9755
10032
  }
9756
10033
  default:
@@ -9844,7 +10121,7 @@ function handleToolExecute(ctx, payload, state) {
9844
10121
  }
9845
10122
  }
9846
10123
  process.stdout.write(`
9847
- ${import_picocolors4.default.cyan("\u26A1")} ${import_picocolors4.default.bold(toolName)}${inputPreview}
10124
+ ${import_picocolors4.default.cyan(">")} ${import_picocolors4.default.bold(toolName)}${inputPreview}
9848
10125
  `);
9849
10126
  }
9850
10127
  function handleToolResult(ctx, payload, state) {
@@ -9870,6 +10147,8 @@ function handleToolResult(ctx, payload, state) {
9870
10147
  // src/cli/run/runner.ts
9871
10148
  var POLL_INTERVAL_MS = 500;
9872
10149
  var DEFAULT_TIMEOUT_MS = 0;
10150
+ var SESSION_CREATE_MAX_RETRIES = 3;
10151
+ var SESSION_CREATE_RETRY_DELAY_MS = 1000;
9873
10152
  async function run(options) {
9874
10153
  const {
9875
10154
  message,
@@ -9903,12 +10182,39 @@ Interrupted. Shutting down...`));
9903
10182
  process.exit(130);
9904
10183
  });
9905
10184
  try {
9906
- const sessionRes = await client3.session.create({
9907
- body: { title: "oh-my-opencode run" }
9908
- });
9909
- const sessionID = sessionRes.data?.id;
10185
+ let sessionID;
10186
+ let lastError;
10187
+ for (let attempt = 1;attempt <= SESSION_CREATE_MAX_RETRIES; attempt++) {
10188
+ const sessionRes = await client3.session.create({
10189
+ body: { title: "oh-my-opencode run" }
10190
+ });
10191
+ if (sessionRes.error) {
10192
+ lastError = sessionRes.error;
10193
+ console.error(import_picocolors5.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
10194
+ console.error(import_picocolors5.default.dim(` Error: ${serializeError(sessionRes.error)}`));
10195
+ if (attempt < SESSION_CREATE_MAX_RETRIES) {
10196
+ const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
10197
+ console.log(import_picocolors5.default.dim(` Retrying in ${delay}ms...`));
10198
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
10199
+ continue;
10200
+ }
10201
+ }
10202
+ sessionID = sessionRes.data?.id;
10203
+ if (sessionID) {
10204
+ break;
10205
+ }
10206
+ lastError = new Error(`Unexpected response: ${JSON.stringify(sessionRes, null, 2)}`);
10207
+ console.error(import_picocolors5.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
10208
+ if (attempt < SESSION_CREATE_MAX_RETRIES) {
10209
+ const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
10210
+ console.log(import_picocolors5.default.dim(` Retrying in ${delay}ms...`));
10211
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
10212
+ }
10213
+ }
9910
10214
  if (!sessionID) {
9911
- console.error(import_picocolors5.default.red("Failed to create session"));
10215
+ console.error(import_picocolors5.default.red("Failed to create session after all retries"));
10216
+ console.error(import_picocolors5.default.dim(`Last error: ${serializeError(lastError)}`));
10217
+ cleanup();
9912
10218
  return 1;
9913
10219
  }
9914
10220
  console.log(import_picocolors5.default.dim(`Session: ${sessionID}`));
@@ -9978,13 +10284,13 @@ init_checker();
9978
10284
  // src/cli/get-local-version/formatter.ts
9979
10285
  var import_picocolors6 = __toESM(require_picocolors(), 1);
9980
10286
  var SYMBOLS2 = {
9981
- check: import_picocolors6.default.green("\u2713"),
9982
- cross: import_picocolors6.default.red("\u2717"),
9983
- arrow: import_picocolors6.default.cyan("\u2192"),
9984
- info: import_picocolors6.default.blue("\u2139"),
9985
- warn: import_picocolors6.default.yellow("\u26A0"),
9986
- pin: import_picocolors6.default.magenta("\uD83D\uDCCC"),
9987
- dev: import_picocolors6.default.cyan("\uD83D\uDD27")
10287
+ check: import_picocolors6.default.green("[OK]"),
10288
+ cross: import_picocolors6.default.red("[X]"),
10289
+ arrow: import_picocolors6.default.cyan("->"),
10290
+ info: import_picocolors6.default.blue("[i]"),
10291
+ warn: import_picocolors6.default.yellow("[!]"),
10292
+ pin: import_picocolors6.default.magenta("[PINNED]"),
10293
+ dev: import_picocolors6.default.cyan("[DEV]")
9988
10294
  };
9989
10295
  function formatVersionOutput(info) {
9990
10296
  const lines = [];
@@ -10143,6 +10449,7 @@ var CHECK_IDS = {
10143
10449
  OPENCODE_INSTALLATION: "opencode-installation",
10144
10450
  PLUGIN_REGISTRATION: "plugin-registration",
10145
10451
  CONFIG_VALIDATION: "config-validation",
10452
+ MODEL_RESOLUTION: "model-resolution",
10146
10453
  AUTH_ANTHROPIC: "auth-anthropic",
10147
10454
  AUTH_OPENAI: "auth-openai",
10148
10455
  AUTH_GOOGLE: "auth-google",
@@ -10159,6 +10466,7 @@ var CHECK_NAMES = {
10159
10466
  [CHECK_IDS.OPENCODE_INSTALLATION]: "OpenCode Installation",
10160
10467
  [CHECK_IDS.PLUGIN_REGISTRATION]: "Plugin Registration",
10161
10468
  [CHECK_IDS.CONFIG_VALIDATION]: "Configuration Validity",
10469
+ [CHECK_IDS.MODEL_RESOLUTION]: "Model Resolution",
10162
10470
  [CHECK_IDS.AUTH_ANTHROPIC]: "Anthropic (Claude) Auth",
10163
10471
  [CHECK_IDS.AUTH_OPENAI]: "OpenAI (ChatGPT) Auth",
10164
10472
  [CHECK_IDS.AUTH_GOOGLE]: "Google (Gemini) Auth",
@@ -10200,9 +10508,9 @@ function selectBinaryPath(paths, platform) {
10200
10508
  return null;
10201
10509
  if (platform !== "win32")
10202
10510
  return paths[0];
10203
- const normalized = paths.map((path5) => path5.toLowerCase());
10511
+ const normalized = paths.map((path6) => path6.toLowerCase());
10204
10512
  for (const ext of WINDOWS_EXECUTABLE_EXTS) {
10205
- const index = normalized.findIndex((path5) => path5.endsWith(ext));
10513
+ const index = normalized.findIndex((path6) => path6.endsWith(ext));
10206
10514
  if (index !== -1)
10207
10515
  return paths[index];
10208
10516
  }
@@ -10334,7 +10642,7 @@ function getOpenCodeCheckDefinition() {
10334
10642
  }
10335
10643
 
10336
10644
  // src/cli/doctor/checks/plugin.ts
10337
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
10645
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
10338
10646
  init_shared();
10339
10647
  function detectConfigPath() {
10340
10648
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
@@ -10353,6 +10661,9 @@ function findPluginEntry2(plugins) {
10353
10661
  const version = isPinned ? plugin.split("@")[1] : null;
10354
10662
  return { entry: plugin, isPinned, version };
10355
10663
  }
10664
+ if (plugin.startsWith("file://") && plugin.includes(PACKAGE_NAME3)) {
10665
+ return { entry: plugin, isPinned: false, version: "local-dev" };
10666
+ }
10356
10667
  }
10357
10668
  return null;
10358
10669
  }
@@ -10368,7 +10679,7 @@ function getPluginInfo() {
10368
10679
  };
10369
10680
  }
10370
10681
  try {
10371
- const content = readFileSync5(configInfo.path, "utf-8");
10682
+ const content = readFileSync6(configInfo.path, "utf-8");
10372
10683
  const config = parseJsonc(content);
10373
10684
  const plugins = config.plugin ?? [];
10374
10685
  const pluginEntry = findPluginEntry2(plugins);
@@ -10442,9 +10753,8 @@ function getPluginCheckDefinition() {
10442
10753
  }
10443
10754
 
10444
10755
  // src/cli/doctor/checks/config.ts
10445
- import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
10446
- import { homedir as homedir4 } from "os";
10447
- import { join as join6 } from "path";
10756
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
10757
+ import { join as join8 } from "path";
10448
10758
  init_shared();
10449
10759
 
10450
10760
  // node_modules/zod/v4/classic/external.js
@@ -11176,10 +11486,10 @@ function mergeDefs(...defs) {
11176
11486
  function cloneDef(schema2) {
11177
11487
  return mergeDefs(schema2._zod.def);
11178
11488
  }
11179
- function getElementAtPath(obj, path5) {
11180
- if (!path5)
11489
+ function getElementAtPath(obj, path6) {
11490
+ if (!path6)
11181
11491
  return obj;
11182
- return path5.reduce((acc, key) => acc?.[key], obj);
11492
+ return path6.reduce((acc, key) => acc?.[key], obj);
11183
11493
  }
11184
11494
  function promiseAllObject(promisesObj) {
11185
11495
  const keys = Object.keys(promisesObj);
@@ -11538,11 +11848,11 @@ function aborted(x2, startIndex = 0) {
11538
11848
  }
11539
11849
  return false;
11540
11850
  }
11541
- function prefixIssues(path5, issues) {
11851
+ function prefixIssues(path6, issues) {
11542
11852
  return issues.map((iss) => {
11543
11853
  var _a;
11544
11854
  (_a = iss).path ?? (_a.path = []);
11545
- iss.path.unshift(path5);
11855
+ iss.path.unshift(path6);
11546
11856
  return iss;
11547
11857
  });
11548
11858
  }
@@ -11710,7 +12020,7 @@ function treeifyError(error, _mapper) {
11710
12020
  return issue2.message;
11711
12021
  };
11712
12022
  const result = { errors: [] };
11713
- const processError = (error2, path5 = []) => {
12023
+ const processError = (error2, path6 = []) => {
11714
12024
  var _a, _b;
11715
12025
  for (const issue2 of error2.issues) {
11716
12026
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -11720,7 +12030,7 @@ function treeifyError(error, _mapper) {
11720
12030
  } else if (issue2.code === "invalid_element") {
11721
12031
  processError({ issues: issue2.issues }, issue2.path);
11722
12032
  } else {
11723
- const fullpath = [...path5, ...issue2.path];
12033
+ const fullpath = [...path6, ...issue2.path];
11724
12034
  if (fullpath.length === 0) {
11725
12035
  result.errors.push(mapper(issue2));
11726
12036
  continue;
@@ -11752,8 +12062,8 @@ function treeifyError(error, _mapper) {
11752
12062
  }
11753
12063
  function toDotPath(_path) {
11754
12064
  const segs = [];
11755
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11756
- for (const seg of path5) {
12065
+ const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12066
+ for (const seg of path6) {
11757
12067
  if (typeof seg === "number")
11758
12068
  segs.push(`[${seg}]`);
11759
12069
  else if (typeof seg === "symbol")
@@ -22780,16 +23090,15 @@ var AgentPermissionSchema = exports_external.object({
22780
23090
  external_directory: PermissionValue.optional()
22781
23091
  });
22782
23092
  var BuiltinAgentNameSchema = exports_external.enum([
22783
- "Sisyphus",
23093
+ "sisyphus",
23094
+ "prometheus",
22784
23095
  "oracle",
22785
23096
  "librarian",
22786
23097
  "explore",
22787
- "frontend-ui-ux-engineer",
22788
- "document-writer",
22789
23098
  "multimodal-looker",
22790
- "Metis (Plan Consultant)",
22791
- "Momus (Plan Reviewer)",
22792
- "orchestrator-sisyphus"
23099
+ "metis",
23100
+ "momus",
23101
+ "atlas"
22793
23102
  ]);
22794
23103
  var BuiltinSkillNameSchema = exports_external.enum([
22795
23104
  "playwright",
@@ -22799,19 +23108,17 @@ var BuiltinSkillNameSchema = exports_external.enum([
22799
23108
  var OverridableAgentNameSchema = exports_external.enum([
22800
23109
  "build",
22801
23110
  "plan",
22802
- "Sisyphus",
22803
- "Sisyphus-Junior",
23111
+ "sisyphus",
23112
+ "sisyphus-junior",
22804
23113
  "OpenCode-Builder",
22805
- "Prometheus (Planner)",
22806
- "Metis (Plan Consultant)",
22807
- "Momus (Plan Reviewer)",
23114
+ "prometheus",
23115
+ "metis",
23116
+ "momus",
22808
23117
  "oracle",
22809
23118
  "librarian",
22810
23119
  "explore",
22811
- "frontend-ui-ux-engineer",
22812
- "document-writer",
22813
23120
  "multimodal-looker",
22814
- "orchestrator-sisyphus"
23121
+ "atlas"
22815
23122
  ]);
22816
23123
  var HookNameSchema = exports_external.enum([
22817
23124
  "todo-continuation-enforcer",
@@ -22843,7 +23150,7 @@ var HookNameSchema = exports_external.enum([
22843
23150
  "delegate-task-retry",
22844
23151
  "prometheus-md-only",
22845
23152
  "start-work",
22846
- "sisyphus-orchestrator"
23153
+ "atlas"
22847
23154
  ]);
22848
23155
  var BuiltinCommandNameSchema = exports_external.enum([
22849
23156
  "init-deep",
@@ -22868,19 +23175,17 @@ var AgentOverrideConfigSchema = exports_external.object({
22868
23175
  var AgentOverridesSchema = exports_external.object({
22869
23176
  build: AgentOverrideConfigSchema.optional(),
22870
23177
  plan: AgentOverrideConfigSchema.optional(),
22871
- Sisyphus: AgentOverrideConfigSchema.optional(),
22872
- "Sisyphus-Junior": AgentOverrideConfigSchema.optional(),
23178
+ sisyphus: AgentOverrideConfigSchema.optional(),
23179
+ "sisyphus-junior": AgentOverrideConfigSchema.optional(),
22873
23180
  "OpenCode-Builder": AgentOverrideConfigSchema.optional(),
22874
- "Prometheus (Planner)": AgentOverrideConfigSchema.optional(),
22875
- "Metis (Plan Consultant)": AgentOverrideConfigSchema.optional(),
22876
- "Momus (Plan Reviewer)": AgentOverrideConfigSchema.optional(),
23181
+ prometheus: AgentOverrideConfigSchema.optional(),
23182
+ metis: AgentOverrideConfigSchema.optional(),
23183
+ momus: AgentOverrideConfigSchema.optional(),
22877
23184
  oracle: AgentOverrideConfigSchema.optional(),
22878
23185
  librarian: AgentOverrideConfigSchema.optional(),
22879
23186
  explore: AgentOverrideConfigSchema.optional(),
22880
- "frontend-ui-ux-engineer": AgentOverrideConfigSchema.optional(),
22881
- "document-writer": AgentOverrideConfigSchema.optional(),
22882
23187
  "multimodal-looker": AgentOverrideConfigSchema.optional(),
22883
- "orchestrator-sisyphus": AgentOverrideConfigSchema.optional()
23188
+ atlas: AgentOverrideConfigSchema.optional()
22884
23189
  });
22885
23190
  var ClaudeCodeConfigSchema = exports_external.object({
22886
23191
  mcp: exports_external.boolean().optional(),
@@ -22898,7 +23203,8 @@ var SisyphusAgentConfigSchema = exports_external.object({
22898
23203
  replace_plan: exports_external.boolean().optional()
22899
23204
  });
22900
23205
  var CategoryConfigSchema = exports_external.object({
22901
- model: exports_external.string(),
23206
+ description: exports_external.string().optional(),
23207
+ model: exports_external.string().optional(),
22902
23208
  variant: exports_external.string().optional(),
22903
23209
  temperature: exports_external.number().min(0).max(2).optional(),
22904
23210
  top_p: exports_external.number().min(0).max(1).optional(),
@@ -22907,19 +23213,20 @@ var CategoryConfigSchema = exports_external.object({
22907
23213
  type: exports_external.enum(["enabled", "disabled"]),
22908
23214
  budgetTokens: exports_external.number().optional()
22909
23215
  }).optional(),
22910
- reasoningEffort: exports_external.enum(["low", "medium", "high"]).optional(),
23216
+ reasoningEffort: exports_external.enum(["low", "medium", "high", "xhigh"]).optional(),
22911
23217
  textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
22912
23218
  tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
22913
- prompt_append: exports_external.string().optional()
23219
+ prompt_append: exports_external.string().optional(),
23220
+ is_unstable_agent: exports_external.boolean().optional()
22914
23221
  });
22915
23222
  var BuiltinCategoryNameSchema = exports_external.enum([
22916
23223
  "visual-engineering",
22917
23224
  "ultrabrain",
22918
23225
  "artistry",
22919
23226
  "quick",
22920
- "most-capable",
22921
- "writing",
22922
- "general"
23227
+ "unspecified-low",
23228
+ "unspecified-high",
23229
+ "writing"
22923
23230
  ]);
22924
23231
  var CategoriesConfigSchema = exports_external.record(exports_external.string(), CategoryConfigSchema);
22925
23232
  var CommentCheckerConfigSchema = exports_external.object({
@@ -23002,8 +23309,8 @@ var RalphLoopConfigSchema = exports_external.object({
23002
23309
  });
23003
23310
  var BackgroundTaskConfigSchema = exports_external.object({
23004
23311
  defaultConcurrency: exports_external.number().min(1).optional(),
23005
- providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional(),
23006
- modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional(),
23312
+ providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional(),
23313
+ modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional(),
23007
23314
  staleTimeoutMs: exports_external.number().min(60000).optional()
23008
23315
  });
23009
23316
  var NotificationConfigSchema = exports_external.object({
@@ -23034,9 +23341,9 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
23034
23341
  git_master: GitMasterConfigSchema.optional()
23035
23342
  });
23036
23343
  // src/cli/doctor/checks/config.ts
23037
- var USER_CONFIG_DIR2 = join6(homedir4(), ".config", "opencode");
23038
- var USER_CONFIG_BASE = join6(USER_CONFIG_DIR2, `${PACKAGE_NAME3}`);
23039
- var PROJECT_CONFIG_BASE = join6(process.cwd(), ".opencode", PACKAGE_NAME3);
23344
+ var USER_CONFIG_DIR2 = getOpenCodeConfigDir({ binary: "opencode" });
23345
+ var USER_CONFIG_BASE = join8(USER_CONFIG_DIR2, `${PACKAGE_NAME3}`);
23346
+ var PROJECT_CONFIG_BASE = join8(process.cwd(), ".opencode", PACKAGE_NAME3);
23040
23347
  function findConfigPath() {
23041
23348
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
23042
23349
  if (projectDetected.format !== "none") {
@@ -23050,7 +23357,7 @@ function findConfigPath() {
23050
23357
  }
23051
23358
  function validateConfig(configPath) {
23052
23359
  try {
23053
- const content = readFileSync6(configPath, "utf-8");
23360
+ const content = readFileSync7(configPath, "utf-8");
23054
23361
  const rawConfig = parseJsonc(content);
23055
23362
  const result = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
23056
23363
  if (!result.success) {
@@ -23132,25 +23439,195 @@ function getConfigCheckDefinition() {
23132
23439
  };
23133
23440
  }
23134
23441
 
23442
+ // src/cli/doctor/checks/model-resolution.ts
23443
+ import { readFileSync as readFileSync8, existsSync as existsSync9 } from "fs";
23444
+ init_shared();
23445
+ init_model_requirements();
23446
+ import { homedir as homedir6 } from "os";
23447
+ import { join as join9 } from "path";
23448
+ function getOpenCodeCacheDir2() {
23449
+ const xdgCache = process.env.XDG_CACHE_HOME;
23450
+ if (xdgCache)
23451
+ return join9(xdgCache, "opencode");
23452
+ return join9(homedir6(), ".cache", "opencode");
23453
+ }
23454
+ function loadAvailableModels() {
23455
+ const cacheFile = join9(getOpenCodeCacheDir2(), "models.json");
23456
+ if (!existsSync9(cacheFile)) {
23457
+ return { providers: [], modelCount: 0, cacheExists: false };
23458
+ }
23459
+ try {
23460
+ const content = readFileSync8(cacheFile, "utf-8");
23461
+ const data = JSON.parse(content);
23462
+ const providers = Object.keys(data);
23463
+ let modelCount = 0;
23464
+ for (const providerId of providers) {
23465
+ const models = data[providerId]?.models;
23466
+ if (models && typeof models === "object") {
23467
+ modelCount += Object.keys(models).length;
23468
+ }
23469
+ }
23470
+ return { providers, modelCount, cacheExists: true };
23471
+ } catch {
23472
+ return { providers: [], modelCount: 0, cacheExists: false };
23473
+ }
23474
+ }
23475
+ var PACKAGE_NAME4 = "oh-my-opencode";
23476
+ var USER_CONFIG_DIR3 = join9(homedir6(), ".config", "opencode");
23477
+ var USER_CONFIG_BASE2 = join9(USER_CONFIG_DIR3, PACKAGE_NAME4);
23478
+ var PROJECT_CONFIG_BASE2 = join9(process.cwd(), ".opencode", PACKAGE_NAME4);
23479
+ function loadConfig() {
23480
+ const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE2);
23481
+ if (projectDetected.format !== "none") {
23482
+ try {
23483
+ const content = readFileSync8(projectDetected.path, "utf-8");
23484
+ return parseJsonc(content);
23485
+ } catch {
23486
+ return null;
23487
+ }
23488
+ }
23489
+ const userDetected = detectConfigFile(USER_CONFIG_BASE2);
23490
+ if (userDetected.format !== "none") {
23491
+ try {
23492
+ const content = readFileSync8(userDetected.path, "utf-8");
23493
+ return parseJsonc(content);
23494
+ } catch {
23495
+ return null;
23496
+ }
23497
+ }
23498
+ return null;
23499
+ }
23500
+ function formatProviderChain(providers) {
23501
+ return providers.join(" \u2192 ");
23502
+ }
23503
+ function getEffectiveModel(requirement, userOverride) {
23504
+ if (userOverride) {
23505
+ return userOverride;
23506
+ }
23507
+ const firstEntry = requirement.fallbackChain[0];
23508
+ if (!firstEntry) {
23509
+ return "unknown";
23510
+ }
23511
+ return `${firstEntry.providers[0]}/${firstEntry.model}`;
23512
+ }
23513
+ function buildEffectiveResolution(requirement, userOverride) {
23514
+ if (userOverride) {
23515
+ return `User override: ${userOverride}`;
23516
+ }
23517
+ const firstEntry = requirement.fallbackChain[0];
23518
+ if (!firstEntry) {
23519
+ return "No fallback chain defined";
23520
+ }
23521
+ return `Provider fallback: ${formatProviderChain(firstEntry.providers)} \u2192 ${firstEntry.model}`;
23522
+ }
23523
+ function getModelResolutionInfoWithOverrides(config2) {
23524
+ const agents = Object.entries(AGENT_MODEL_REQUIREMENTS).map(([name, requirement]) => {
23525
+ const userOverride = config2.agents?.[name]?.model;
23526
+ return {
23527
+ name,
23528
+ requirement,
23529
+ userOverride,
23530
+ effectiveModel: getEffectiveModel(requirement, userOverride),
23531
+ effectiveResolution: buildEffectiveResolution(requirement, userOverride)
23532
+ };
23533
+ });
23534
+ const categories = Object.entries(CATEGORY_MODEL_REQUIREMENTS).map(([name, requirement]) => {
23535
+ const userOverride = config2.categories?.[name]?.model;
23536
+ return {
23537
+ name,
23538
+ requirement,
23539
+ userOverride,
23540
+ effectiveModel: getEffectiveModel(requirement, userOverride),
23541
+ effectiveResolution: buildEffectiveResolution(requirement, userOverride)
23542
+ };
23543
+ });
23544
+ return { agents, categories };
23545
+ }
23546
+ function formatModelWithVariant(model, variant) {
23547
+ return variant ? `${model} (${variant})` : model;
23548
+ }
23549
+ function getEffectiveVariant(requirement) {
23550
+ const firstEntry = requirement.fallbackChain[0];
23551
+ return firstEntry?.variant ?? requirement.variant;
23552
+ }
23553
+ function buildDetailsArray(info, available) {
23554
+ const details = [];
23555
+ details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
23556
+ details.push("");
23557
+ if (available.cacheExists) {
23558
+ details.push(` Providers: ${available.providers.length} (${available.providers.slice(0, 8).join(", ")}${available.providers.length > 8 ? "..." : ""})`);
23559
+ details.push(` Total models: ${available.modelCount}`);
23560
+ details.push(` Cache: ~/.cache/opencode/models.json`);
23561
+ details.push(` Refresh: opencode models --refresh`);
23562
+ } else {
23563
+ details.push(" \u26A0 Cache not found. Run 'opencode' to populate.");
23564
+ }
23565
+ details.push("");
23566
+ details.push("\u2550\u2550\u2550 Configured Models \u2550\u2550\u2550");
23567
+ details.push("");
23568
+ details.push("Agents:");
23569
+ for (const agent of info.agents) {
23570
+ const marker = agent.userOverride ? "\u25CF" : "\u25CB";
23571
+ const display = formatModelWithVariant(agent.effectiveModel, getEffectiveVariant(agent.requirement));
23572
+ details.push(` ${marker} ${agent.name}: ${display}`);
23573
+ }
23574
+ details.push("");
23575
+ details.push("Categories:");
23576
+ for (const category of info.categories) {
23577
+ const marker = category.userOverride ? "\u25CF" : "\u25CB";
23578
+ const display = formatModelWithVariant(category.effectiveModel, getEffectiveVariant(category.requirement));
23579
+ details.push(` ${marker} ${category.name}: ${display}`);
23580
+ }
23581
+ details.push("");
23582
+ details.push("\u25CF = user override, \u25CB = provider fallback");
23583
+ return details;
23584
+ }
23585
+ async function checkModelResolution() {
23586
+ const config2 = loadConfig() ?? {};
23587
+ const info = getModelResolutionInfoWithOverrides(config2);
23588
+ const available = loadAvailableModels();
23589
+ const agentCount = info.agents.length;
23590
+ const categoryCount = info.categories.length;
23591
+ const agentOverrides = info.agents.filter((a) => a.userOverride).length;
23592
+ const categoryOverrides = info.categories.filter((c) => c.userOverride).length;
23593
+ const totalOverrides = agentOverrides + categoryOverrides;
23594
+ const overrideNote = totalOverrides > 0 ? ` (${totalOverrides} override${totalOverrides > 1 ? "s" : ""})` : "";
23595
+ const cacheNote = available.cacheExists ? `, ${available.modelCount} available` : ", cache not found";
23596
+ return {
23597
+ name: CHECK_NAMES[CHECK_IDS.MODEL_RESOLUTION],
23598
+ status: available.cacheExists ? "pass" : "warn",
23599
+ message: `${agentCount} agents, ${categoryCount} categories${overrideNote}${cacheNote}`,
23600
+ details: buildDetailsArray(info, available)
23601
+ };
23602
+ }
23603
+ function getModelResolutionCheckDefinition() {
23604
+ return {
23605
+ id: CHECK_IDS.MODEL_RESOLUTION,
23606
+ name: CHECK_NAMES[CHECK_IDS.MODEL_RESOLUTION],
23607
+ category: "configuration",
23608
+ check: checkModelResolution,
23609
+ critical: false
23610
+ };
23611
+ }
23612
+
23135
23613
  // src/cli/doctor/checks/auth.ts
23136
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
23137
- import { homedir as homedir5 } from "os";
23138
- import { join as join7 } from "path";
23614
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
23615
+ import { join as join10 } from "path";
23139
23616
  init_shared();
23140
- var OPENCODE_CONFIG_DIR = join7(homedir5(), ".config", "opencode");
23141
- var OPENCODE_JSON = join7(OPENCODE_CONFIG_DIR, "opencode.json");
23142
- var OPENCODE_JSONC = join7(OPENCODE_CONFIG_DIR, "opencode.jsonc");
23617
+ var OPENCODE_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" });
23618
+ var OPENCODE_JSON = join10(OPENCODE_CONFIG_DIR, "opencode.json");
23619
+ var OPENCODE_JSONC = join10(OPENCODE_CONFIG_DIR, "opencode.jsonc");
23143
23620
  var AUTH_PLUGINS = {
23144
23621
  anthropic: { plugin: "builtin", name: "Anthropic (Claude)" },
23145
23622
  openai: { plugin: "opencode-openai-codex-auth", name: "OpenAI (ChatGPT)" },
23146
23623
  google: { plugin: "opencode-antigravity-auth", name: "Google (Gemini)" }
23147
23624
  };
23148
23625
  function getOpenCodeConfig() {
23149
- const configPath = existsSync9(OPENCODE_JSONC) ? OPENCODE_JSONC : OPENCODE_JSON;
23150
- if (!existsSync9(configPath))
23626
+ const configPath = existsSync10(OPENCODE_JSONC) ? OPENCODE_JSONC : OPENCODE_JSON;
23627
+ if (!existsSync10(configPath))
23151
23628
  return null;
23152
23629
  try {
23153
- const content = readFileSync7(configPath, "utf-8");
23630
+ const content = readFileSync9(configPath, "utf-8");
23154
23631
  return parseJsonc(content);
23155
23632
  } catch {
23156
23633
  return null;
@@ -23279,9 +23756,9 @@ async function checkAstGrepCli() {
23279
23756
  path: binary2.path
23280
23757
  };
23281
23758
  }
23282
- function checkAstGrepNapi() {
23759
+ async function checkAstGrepNapi() {
23283
23760
  try {
23284
- __require.resolve("@ast-grep/napi");
23761
+ await import("@ast-grep/napi");
23285
23762
  return {
23286
23763
  name: "AST-Grep NAPI",
23287
23764
  required: false,
@@ -23290,6 +23767,24 @@ function checkAstGrepNapi() {
23290
23767
  path: null
23291
23768
  };
23292
23769
  } catch {
23770
+ const { existsSync: existsSync11 } = await import("fs");
23771
+ const { join: join11 } = await import("path");
23772
+ const { homedir: homedir7 } = await import("os");
23773
+ const pathsToCheck = [
23774
+ join11(homedir7(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
23775
+ join11(process.cwd(), "node_modules", "@ast-grep", "napi")
23776
+ ];
23777
+ for (const napiPath of pathsToCheck) {
23778
+ if (existsSync11(napiPath)) {
23779
+ return {
23780
+ name: "AST-Grep NAPI",
23781
+ required: false,
23782
+ installed: true,
23783
+ version: null,
23784
+ path: napiPath
23785
+ };
23786
+ }
23787
+ }
23293
23788
  return {
23294
23789
  name: "AST-Grep NAPI",
23295
23790
  required: false,
@@ -23342,7 +23837,7 @@ async function checkDependencyAstGrepCli() {
23342
23837
  return dependencyToCheckResult(info, CHECK_NAMES[CHECK_IDS.DEP_AST_GREP_CLI]);
23343
23838
  }
23344
23839
  async function checkDependencyAstGrepNapi() {
23345
- const info = checkAstGrepNapi();
23840
+ const info = await checkAstGrepNapi();
23346
23841
  return dependencyToCheckResult(info, CHECK_NAMES[CHECK_IDS.DEP_AST_GREP_NAPI]);
23347
23842
  }
23348
23843
  async function checkDependencyCommentChecker() {
@@ -23509,15 +24004,15 @@ function getGhCliCheckDefinition() {
23509
24004
  }
23510
24005
 
23511
24006
  // src/tools/lsp/config.ts
23512
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
23513
- import { join as join8 } from "path";
23514
- import { homedir as homedir6 } from "os";
24007
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
24008
+ import { join as join11 } from "path";
24009
+ init_shared();
23515
24010
  function isServerInstalled(command) {
23516
24011
  if (command.length === 0)
23517
24012
  return false;
23518
24013
  const cmd = command[0];
23519
24014
  if (cmd.includes("/") || cmd.includes("\\")) {
23520
- if (existsSync10(cmd))
24015
+ if (existsSync11(cmd))
23521
24016
  return true;
23522
24017
  }
23523
24018
  const isWindows = process.platform === "win32";
@@ -23539,20 +24034,23 @@ function isServerInstalled(command) {
23539
24034
  const paths = pathEnv.split(pathSeparator);
23540
24035
  for (const p2 of paths) {
23541
24036
  for (const suffix of exts) {
23542
- if (existsSync10(join8(p2, cmd + suffix))) {
24037
+ if (existsSync11(join11(p2, cmd + suffix))) {
23543
24038
  return true;
23544
24039
  }
23545
24040
  }
23546
24041
  }
23547
24042
  const cwd = process.cwd();
24043
+ const configDir = getOpenCodeConfigDir({ binary: "opencode" });
24044
+ const dataDir = join11(getDataDir(), "opencode");
23548
24045
  const additionalBases = [
23549
- join8(cwd, "node_modules", ".bin"),
23550
- join8(homedir6(), ".config", "opencode", "bin"),
23551
- join8(homedir6(), ".config", "opencode", "node_modules", ".bin")
24046
+ join11(cwd, "node_modules", ".bin"),
24047
+ join11(configDir, "bin"),
24048
+ join11(configDir, "node_modules", ".bin"),
24049
+ join11(dataDir, "bin")
23552
24050
  ];
23553
24051
  for (const base of additionalBases) {
23554
24052
  for (const suffix of exts) {
23555
- if (existsSync10(join8(base, cmd + suffix))) {
24053
+ if (existsSync11(join11(base, cmd + suffix))) {
23556
24054
  return true;
23557
24055
  }
23558
24056
  }
@@ -23625,23 +24123,23 @@ function getLspCheckDefinition() {
23625
24123
  }
23626
24124
 
23627
24125
  // src/cli/doctor/checks/mcp.ts
23628
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
24126
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
23629
24127
  import { homedir as homedir7 } from "os";
23630
- import { join as join9 } from "path";
24128
+ import { join as join12 } from "path";
23631
24129
  init_shared();
23632
24130
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
23633
24131
  var MCP_CONFIG_PATHS = [
23634
- join9(homedir7(), ".claude", ".mcp.json"),
23635
- join9(process.cwd(), ".mcp.json"),
23636
- join9(process.cwd(), ".claude", ".mcp.json")
24132
+ join12(homedir7(), ".claude", ".mcp.json"),
24133
+ join12(process.cwd(), ".mcp.json"),
24134
+ join12(process.cwd(), ".claude", ".mcp.json")
23637
24135
  ];
23638
24136
  function loadUserMcpConfig() {
23639
24137
  const servers = {};
23640
24138
  for (const configPath of MCP_CONFIG_PATHS) {
23641
- if (!existsSync11(configPath))
24139
+ if (!existsSync12(configPath))
23642
24140
  continue;
23643
24141
  try {
23644
- const content = readFileSync9(configPath, "utf-8");
24142
+ const content = readFileSync11(configPath, "utf-8");
23645
24143
  const config2 = parseJsonc(content);
23646
24144
  if (config2.mcpServers) {
23647
24145
  Object.assign(servers, config2.mcpServers);
@@ -23848,6 +24346,7 @@ function getAllCheckDefinitions() {
23848
24346
  getOpenCodeCheckDefinition(),
23849
24347
  getPluginCheckDefinition(),
23850
24348
  getConfigCheckDefinition(),
24349
+ getModelResolutionCheckDefinition(),
23851
24350
  ...getAuthCheckDefinitions(),
23852
24351
  ...getDependencyCheckDefinitions(),
23853
24352
  getGhCliCheckDefinition(),
@@ -24039,23 +24538,28 @@ async function doctor(options = {}) {
24039
24538
  var VERSION2 = package_default.version;
24040
24539
  var program2 = new Command;
24041
24540
  program2.name("oh-my-opencode").description("The ultimate OpenCode plugin - multi-model orchestration, LSP tools, and more").version(VERSION2, "-v, --version", "Show version number");
24042
- 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", `
24541
+ 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", `
24043
24542
  Examples:
24044
24543
  $ bunx oh-my-opencode install
24045
- $ bunx oh-my-opencode install --no-tui --claude=max20 --chatgpt=yes --gemini=yes --copilot=no
24046
- $ bunx oh-my-opencode install --no-tui --claude=no --chatgpt=no --gemini=no --copilot=yes
24544
+ $ bunx oh-my-opencode install --no-tui --claude=max20 --openai=yes --gemini=yes --copilot=no
24545
+ $ bunx oh-my-opencode install --no-tui --claude=no --gemini=no --copilot=yes --opencode-zen=yes
24047
24546
 
24048
- Model Providers:
24049
- Claude Required for Sisyphus (main orchestrator) and Librarian agents
24050
- ChatGPT Powers the Oracle agent for debugging and architecture
24051
- Gemini Powers frontend, documentation, and multimodal agents
24547
+ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai):
24548
+ Claude Native anthropic/ models (Opus, Sonnet, Haiku)
24549
+ OpenAI Native openai/ models (GPT-5.2 for Oracle)
24550
+ Gemini Native google/ models (Gemini 3 Pro, Flash)
24551
+ Copilot github-copilot/ models (fallback)
24552
+ OpenCode Zen opencode/ models (opencode/claude-opus-4-5, etc.)
24553
+ Z.ai zai-coding-plan/glm-4.7 (Librarian priority)
24052
24554
  `).action(async (options) => {
24053
24555
  const args = {
24054
24556
  tui: options.tui !== false,
24055
24557
  claude: options.claude,
24056
- chatgpt: options.chatgpt,
24558
+ openai: options.openai,
24057
24559
  gemini: options.gemini,
24058
24560
  copilot: options.copilot,
24561
+ opencodeZen: options.opencodeZen,
24562
+ zaiCodingPlan: options.zaiCodingPlan,
24059
24563
  skipAuth: options.skipAuth ?? false
24060
24564
  };
24061
24565
  const exitCode = await install(args);