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