oh-my-opencode 2.14.0 → 3.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.ja.md +76 -17
  2. package/README.md +169 -37
  3. package/README.zh-cn.md +73 -17
  4. package/dist/agents/metis.d.ts +19 -0
  5. package/dist/agents/momus.d.ts +6 -0
  6. package/dist/agents/orchestrator-sisyphus.d.ts +20 -0
  7. package/dist/agents/plan-prompt.d.ts +8 -5
  8. package/dist/agents/prometheus-prompt.d.ts +27 -0
  9. package/dist/agents/sisyphus-junior.d.ts +3 -0
  10. package/dist/agents/types.d.ts +1 -1
  11. package/dist/agents/utils.d.ts +4 -1
  12. package/dist/auth/antigravity/accounts.d.ts +40 -0
  13. package/dist/auth/antigravity/accounts.test.d.ts +1 -0
  14. package/dist/auth/antigravity/browser.d.ts +27 -0
  15. package/dist/auth/antigravity/browser.test.d.ts +1 -0
  16. package/dist/auth/antigravity/cli.d.ts +2 -0
  17. package/dist/auth/antigravity/cli.test.d.ts +1 -0
  18. package/dist/auth/antigravity/constants.d.ts +63 -1
  19. package/dist/auth/antigravity/constants.test.d.ts +1 -0
  20. package/dist/auth/antigravity/fetch.d.ts +2 -1
  21. package/dist/auth/antigravity/integration.test.d.ts +10 -0
  22. package/dist/auth/antigravity/oauth.d.ts +6 -40
  23. package/dist/auth/antigravity/oauth.test.d.ts +1 -0
  24. package/dist/auth/antigravity/request.d.ts +12 -0
  25. package/dist/auth/antigravity/request.test.d.ts +1 -0
  26. package/dist/auth/antigravity/storage.d.ts +5 -0
  27. package/dist/auth/antigravity/storage.test.d.ts +1 -0
  28. package/dist/auth/antigravity/thinking.d.ts +45 -1
  29. package/dist/auth/antigravity/thinking.test.d.ts +10 -0
  30. package/dist/auth/antigravity/token.test.d.ts +1 -0
  31. package/dist/auth/antigravity/types.d.ts +29 -5
  32. package/dist/cli/commands/auth.d.ts +2 -0
  33. package/dist/cli/index.js +342 -117
  34. package/dist/config/schema.d.ts +473 -6
  35. package/dist/features/background-agent/manager.d.ts +13 -1
  36. package/dist/features/background-agent/types.d.ts +26 -1
  37. package/dist/features/boulder-state/constants.d.ts +10 -0
  38. package/dist/features/boulder-state/index.d.ts +3 -0
  39. package/dist/features/boulder-state/storage.d.ts +28 -0
  40. package/dist/features/boulder-state/storage.test.d.ts +1 -0
  41. package/dist/features/boulder-state/types.d.ts +24 -0
  42. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  43. package/dist/features/builtin-commands/templates/refactor.d.ts +1 -1
  44. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -0
  45. package/dist/features/builtin-commands/types.d.ts +1 -1
  46. package/dist/features/hook-message-injector/injector.d.ts +2 -2
  47. package/dist/features/hook-message-injector/types.d.ts +3 -2
  48. package/dist/features/opencode-skill-loader/index.d.ts +1 -0
  49. package/dist/features/opencode-skill-loader/skill-content.d.ts +5 -0
  50. package/dist/features/opencode-skill-loader/skill-content.test.d.ts +1 -0
  51. package/dist/features/task-toast-manager/index.d.ts +2 -0
  52. package/dist/features/task-toast-manager/manager.d.ts +56 -0
  53. package/dist/features/task-toast-manager/manager.test.d.ts +1 -0
  54. package/dist/features/task-toast-manager/types.d.ts +16 -0
  55. package/dist/google-auth.js +2167 -161
  56. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  57. package/dist/hooks/auto-update-checker/index.d.ts +3 -0
  58. package/dist/hooks/auto-update-checker/index.test.d.ts +1 -0
  59. package/dist/hooks/claude-code-hooks/index.d.ts +2 -1
  60. package/dist/hooks/claude-code-hooks/types.d.ts +1 -0
  61. package/dist/hooks/index.d.ts +4 -0
  62. package/dist/hooks/prometheus-md-only/constants.d.ts +6 -0
  63. package/dist/hooks/prometheus-md-only/index.d.ts +12 -0
  64. package/dist/hooks/prometheus-md-only/index.test.d.ts +1 -0
  65. package/dist/hooks/sisyphus-orchestrator/index.d.ts +35 -0
  66. package/dist/hooks/sisyphus-orchestrator/index.test.d.ts +1 -0
  67. package/dist/hooks/start-work/index.d.ts +16 -0
  68. package/dist/hooks/start-work/index.test.d.ts +1 -0
  69. package/dist/hooks/task-resume-info/index.d.ts +11 -0
  70. package/dist/hooks/todo-continuation-enforcer.d.ts +1 -0
  71. package/dist/index.js +15227 -6676
  72. package/dist/mcp/index.d.ts +4 -2
  73. package/dist/mcp/websearch.d.ts +3 -0
  74. package/dist/shared/external-plugin-detector.d.ts +18 -0
  75. package/dist/shared/external-plugin-detector.test.d.ts +1 -0
  76. package/dist/shared/index.d.ts +1 -0
  77. package/dist/shared/migration.d.ts +6 -0
  78. package/dist/tools/background-task/index.d.ts +1 -1
  79. package/dist/tools/call-omo-agent/constants.d.ts +1 -1
  80. package/dist/tools/index.d.ts +1 -0
  81. package/dist/tools/sisyphus-task/constants.d.ts +12 -0
  82. package/dist/tools/sisyphus-task/index.d.ts +3 -0
  83. package/dist/tools/sisyphus-task/tools.d.ts +16 -0
  84. package/dist/tools/sisyphus-task/tools.test.d.ts +1 -0
  85. package/dist/tools/sisyphus-task/types.d.ts +9 -0
  86. package/package.json +3 -2
package/dist/cli/index.js CHANGED
@@ -2657,8 +2657,8 @@ var require_napi = __commonJS((exports, module) => {
2657
2657
  var require_package = __commonJS((exports, module) => {
2658
2658
  module.exports = {
2659
2659
  name: "oh-my-opencode",
2660
- version: "2.13.2",
2661
- description: "OpenCode plugin - custom agents (oracle, librarian) and enhanced features",
2660
+ version: "2.14.0",
2661
+ description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
2662
2662
  main: "dist/index.js",
2663
2663
  types: "dist/index.d.ts",
2664
2664
  type: "module",
@@ -2719,6 +2719,7 @@ var require_package = __commonJS((exports, module) => {
2719
2719
  hono: "^4.10.4",
2720
2720
  "js-yaml": "^4.1.1",
2721
2721
  "jsonc-parser": "^3.3.1",
2722
+ open: "^11.0.0",
2722
2723
  picocolors: "^1.1.1",
2723
2724
  picomatch: "^4.0.2",
2724
2725
  "xdg-basedir": "^5.1.0",
@@ -6007,6 +6008,12 @@ function log(message, data) {
6007
6008
  var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
6008
6009
  // src/shared/dynamic-truncator.ts
6009
6010
  var ANTHROPIC_ACTUAL_LIMIT = process.env.ANTHROPIC_1M_CONTEXT === "true" || process.env.VERTEX_ANTHROPIC_1M_CONTEXT === "true" ? 1e6 : 200000;
6011
+ // src/shared/data-path.ts
6012
+ import * as path2 from "path";
6013
+ import * as os2 from "os";
6014
+ function getDataDir() {
6015
+ return process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
6016
+ }
6010
6017
  // src/shared/jsonc-parser.ts
6011
6018
  import { existsSync, readFileSync } from "fs";
6012
6019
 
@@ -6877,8 +6884,8 @@ function detectConfigFile(basePath) {
6877
6884
  }
6878
6885
  // src/shared/opencode-config-dir.ts
6879
6886
  import { existsSync as existsSync2 } from "fs";
6880
- import { homedir } from "os";
6881
- import { join as join2 } from "path";
6887
+ import { homedir as homedir2 } from "os";
6888
+ import { join as join3 } from "path";
6882
6889
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop";
6883
6890
  var TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
6884
6891
  function isDevBuild(version) {
@@ -6890,35 +6897,35 @@ function getTauriConfigDir(identifier) {
6890
6897
  const platform = process.platform;
6891
6898
  switch (platform) {
6892
6899
  case "darwin":
6893
- return join2(homedir(), "Library", "Application Support", identifier);
6900
+ return join3(homedir2(), "Library", "Application Support", identifier);
6894
6901
  case "win32": {
6895
- const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
6896
- return join2(appData, identifier);
6902
+ const appData = process.env.APPDATA || join3(homedir2(), "AppData", "Roaming");
6903
+ return join3(appData, identifier);
6897
6904
  }
6898
6905
  case "linux":
6899
6906
  default: {
6900
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
6901
- return join2(xdgConfig, identifier);
6907
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
6908
+ return join3(xdgConfig, identifier);
6902
6909
  }
6903
6910
  }
6904
6911
  }
6905
6912
  function getCliConfigDir() {
6906
6913
  if (process.platform === "win32") {
6907
- const crossPlatformDir = join2(homedir(), ".config", "opencode");
6908
- const crossPlatformConfig = join2(crossPlatformDir, "opencode.json");
6914
+ const crossPlatformDir = join3(homedir2(), ".config", "opencode");
6915
+ const crossPlatformConfig = join3(crossPlatformDir, "opencode.json");
6909
6916
  if (existsSync2(crossPlatformConfig)) {
6910
6917
  return crossPlatformDir;
6911
6918
  }
6912
- const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
6913
- const appdataDir = join2(appData, "opencode");
6914
- const appdataConfig = join2(appdataDir, "opencode.json");
6919
+ const appData = process.env.APPDATA || join3(homedir2(), "AppData", "Roaming");
6920
+ const appdataDir = join3(appData, "opencode");
6921
+ const appdataConfig = join3(appdataDir, "opencode.json");
6915
6922
  if (existsSync2(appdataConfig)) {
6916
6923
  return appdataDir;
6917
6924
  }
6918
6925
  return crossPlatformDir;
6919
6926
  }
6920
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
6921
- return join2(xdgConfig, "opencode");
6927
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
6928
+ return join3(xdgConfig, "opencode");
6922
6929
  }
6923
6930
  function getOpenCodeConfigDir(options) {
6924
6931
  const { binary: binary2, version, checkExisting = true } = options;
@@ -6929,8 +6936,8 @@ function getOpenCodeConfigDir(options) {
6929
6936
  const tauriDir = getTauriConfigDir(identifier);
6930
6937
  if (checkExisting) {
6931
6938
  const legacyDir = getCliConfigDir();
6932
- const legacyConfig = join2(legacyDir, "opencode.json");
6933
- const legacyConfigC = join2(legacyDir, "opencode.jsonc");
6939
+ const legacyConfig = join3(legacyDir, "opencode.json");
6940
+ const legacyConfigC = join3(legacyDir, "opencode.jsonc");
6934
6941
  if (existsSync2(legacyConfig) || existsSync2(legacyConfigC)) {
6935
6942
  return legacyDir;
6936
6943
  }
@@ -6941,10 +6948,10 @@ function getOpenCodeConfigPaths(options) {
6941
6948
  const configDir = getOpenCodeConfigDir(options);
6942
6949
  return {
6943
6950
  configDir,
6944
- configJson: join2(configDir, "opencode.json"),
6945
- configJsonc: join2(configDir, "opencode.jsonc"),
6946
- packageJson: join2(configDir, "package.json"),
6947
- omoConfig: join2(configDir, "oh-my-opencode.json")
6951
+ configJson: join3(configDir, "opencode.json"),
6952
+ configJsonc: join3(configDir, "opencode.jsonc"),
6953
+ packageJson: join3(configDir, "package.json"),
6954
+ omoConfig: join3(configDir, "oh-my-opencode.json")
6948
6955
  };
6949
6956
  }
6950
6957
  // src/shared/opencode-version.ts
@@ -7029,26 +7036,26 @@ function detectConfigFormat() {
7029
7036
  function isEmptyOrWhitespace(content) {
7030
7037
  return content.trim().length === 0;
7031
7038
  }
7032
- function parseConfigWithError(path2) {
7039
+ function parseConfigWithError(path3) {
7033
7040
  try {
7034
- const stat = statSync(path2);
7041
+ const stat = statSync(path3);
7035
7042
  if (stat.size === 0) {
7036
- return { config: null, error: `Config file is empty: ${path2}. Delete it or add valid JSON content.` };
7043
+ return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
7037
7044
  }
7038
- const content = readFileSync2(path2, "utf-8");
7045
+ const content = readFileSync2(path3, "utf-8");
7039
7046
  if (isEmptyOrWhitespace(content)) {
7040
- return { config: null, error: `Config file contains only whitespace: ${path2}. Delete it or add valid JSON content.` };
7047
+ return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
7041
7048
  }
7042
7049
  const config = parseJsonc(content);
7043
7050
  if (config === null || config === undefined) {
7044
- return { config: null, error: `Config file parsed to null/undefined: ${path2}. Ensure it contains valid JSON.` };
7051
+ return { config: null, error: `Config file parsed to null/undefined: ${path3}. Ensure it contains valid JSON.` };
7045
7052
  }
7046
7053
  if (typeof config !== "object" || Array.isArray(config)) {
7047
- return { config: null, error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path2}` };
7054
+ return { config: null, error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path3}` };
7048
7055
  }
7049
7056
  return { config };
7050
7057
  } catch (err) {
7051
- return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path2}`) };
7058
+ return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path3}`) };
7052
7059
  }
7053
7060
  }
7054
7061
  function ensureConfigDir() {
@@ -7063,27 +7070,27 @@ function addPluginToOpenCodeConfig() {
7063
7070
  } catch (err) {
7064
7071
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
7065
7072
  }
7066
- const { format: format2, path: path2 } = detectConfigFormat();
7073
+ const { format: format2, path: path3 } = detectConfigFormat();
7067
7074
  const pluginName = "oh-my-opencode";
7068
7075
  try {
7069
7076
  if (format2 === "none") {
7070
7077
  const config2 = { plugin: [pluginName] };
7071
- writeFileSync(path2, JSON.stringify(config2, null, 2) + `
7078
+ writeFileSync(path3, JSON.stringify(config2, null, 2) + `
7072
7079
  `);
7073
- return { success: true, configPath: path2 };
7080
+ return { success: true, configPath: path3 };
7074
7081
  }
7075
- const parseResult = parseConfigWithError(path2);
7082
+ const parseResult = parseConfigWithError(path3);
7076
7083
  if (!parseResult.config) {
7077
- return { success: false, configPath: path2, error: parseResult.error ?? "Failed to parse config file" };
7084
+ return { success: false, configPath: path3, error: parseResult.error ?? "Failed to parse config file" };
7078
7085
  }
7079
7086
  const config = parseResult.config;
7080
7087
  const plugins = config.plugin ?? [];
7081
7088
  if (plugins.some((p2) => p2.startsWith(pluginName))) {
7082
- return { success: true, configPath: path2 };
7089
+ return { success: true, configPath: path3 };
7083
7090
  }
7084
7091
  config.plugin = [...plugins, pluginName];
7085
7092
  if (format2 === "jsonc") {
7086
- const content = readFileSync2(path2, "utf-8");
7093
+ const content = readFileSync2(path3, "utf-8");
7087
7094
  const pluginArrayRegex = /"plugin"\s*:\s*\[([\s\S]*?)\]/;
7088
7095
  const match = content.match(pluginArrayRegex);
7089
7096
  if (match) {
@@ -7093,19 +7100,19 @@ function addPluginToOpenCodeConfig() {
7093
7100
  const newContent = content.replace(pluginArrayRegex, `"plugin": [
7094
7101
  ${newArrayContent}
7095
7102
  ]`);
7096
- writeFileSync(path2, newContent);
7103
+ writeFileSync(path3, newContent);
7097
7104
  } else {
7098
7105
  const newContent = content.replace(/^(\s*\{)/, `$1
7099
7106
  "plugin": ["${pluginName}"],`);
7100
- writeFileSync(path2, newContent);
7107
+ writeFileSync(path3, newContent);
7101
7108
  }
7102
7109
  } else {
7103
- writeFileSync(path2, JSON.stringify(config, null, 2) + `
7110
+ writeFileSync(path3, JSON.stringify(config, null, 2) + `
7104
7111
  `);
7105
7112
  }
7106
- return { success: true, configPath: path2 };
7113
+ return { success: true, configPath: path3 };
7107
7114
  } catch (err) {
7108
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "update opencode config") };
7115
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "update opencode config") };
7109
7116
  }
7110
7117
  }
7111
7118
  function deepMerge(target, source) {
@@ -7158,6 +7165,13 @@ function generateOmoConfig(installConfig) {
7158
7165
  if (Object.keys(agents).length > 0) {
7159
7166
  config.agents = agents;
7160
7167
  }
7168
+ if (installConfig.hasGemini) {
7169
+ config.categories = {
7170
+ "visual-engineering": { model: "google/gemini-3-pro-high" },
7171
+ artistry: { model: "google/gemini-3-pro-high" },
7172
+ writing: { model: "google/gemini-3-flash-high" }
7173
+ };
7174
+ }
7161
7175
  return config;
7162
7176
  }
7163
7177
  function writeOmoConfig(installConfig) {
@@ -7239,11 +7253,11 @@ async function addAuthPlugins(config) {
7239
7253
  } catch (err) {
7240
7254
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
7241
7255
  }
7242
- const { format: format2, path: path2 } = detectConfigFormat();
7256
+ const { format: format2, path: path3 } = detectConfigFormat();
7243
7257
  try {
7244
7258
  let existingConfig = null;
7245
7259
  if (format2 !== "none") {
7246
- const parseResult = parseConfigWithError(path2);
7260
+ const parseResult = parseConfigWithError(path3);
7247
7261
  if (parseResult.error && !parseResult.config) {
7248
7262
  existingConfig = {};
7249
7263
  } else {
@@ -7264,11 +7278,11 @@ async function addAuthPlugins(config) {
7264
7278
  }
7265
7279
  }
7266
7280
  const newConfig = { ...existingConfig ?? {}, plugin: plugins };
7267
- writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
7281
+ writeFileSync(path3, JSON.stringify(newConfig, null, 2) + `
7268
7282
  `);
7269
- return { success: true, configPath: path2 };
7283
+ return { success: true, configPath: path3 };
7270
7284
  } catch (err) {
7271
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "add auth plugins to config") };
7285
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "add auth plugins to config") };
7272
7286
  }
7273
7287
  }
7274
7288
  var ANTIGRAVITY_PROVIDER_CONFIG = {
@@ -7352,11 +7366,11 @@ function addProviderConfig(config) {
7352
7366
  } catch (err) {
7353
7367
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
7354
7368
  }
7355
- const { format: format2, path: path2 } = detectConfigFormat();
7369
+ const { format: format2, path: path3 } = detectConfigFormat();
7356
7370
  try {
7357
7371
  let existingConfig = null;
7358
7372
  if (format2 !== "none") {
7359
- const parseResult = parseConfigWithError(path2);
7373
+ const parseResult = parseConfigWithError(path3);
7360
7374
  if (parseResult.error && !parseResult.config) {
7361
7375
  existingConfig = {};
7362
7376
  } else {
@@ -7374,11 +7388,11 @@ function addProviderConfig(config) {
7374
7388
  if (Object.keys(providers).length > 0) {
7375
7389
  newConfig.provider = providers;
7376
7390
  }
7377
- writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
7391
+ writeFileSync(path3, JSON.stringify(newConfig, null, 2) + `
7378
7392
  `);
7379
- return { success: true, configPath: path2 };
7393
+ return { success: true, configPath: path3 };
7380
7394
  } catch (err) {
7381
- return { success: false, configPath: path2, error: formatErrorWithSuggestion(err, "add provider config") };
7395
+ return { success: false, configPath: path3, error: formatErrorWithSuggestion(err, "add provider config") };
7382
7396
  }
7383
7397
  }
7384
7398
  function detectCurrentConfig() {
@@ -7389,11 +7403,11 @@ function detectCurrentConfig() {
7389
7403
  hasChatGPT: true,
7390
7404
  hasGemini: false
7391
7405
  };
7392
- const { format: format2, path: path2 } = detectConfigFormat();
7406
+ const { format: format2, path: path3 } = detectConfigFormat();
7393
7407
  if (format2 === "none") {
7394
7408
  return result;
7395
7409
  }
7396
- const parseResult = parseConfigWithError(path2);
7410
+ const parseResult = parseConfigWithError(path3);
7397
7411
  if (!parseResult.config) {
7398
7412
  return result;
7399
7413
  }
@@ -8024,7 +8038,7 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
8024
8038
 
8025
8039
  // node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
8026
8040
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
8027
- var defaultPathSerializer = ({ path: path2, url: _url }) => {
8041
+ var defaultPathSerializer = ({ path: path3, url: _url }) => {
8028
8042
  let url = _url;
8029
8043
  const matches = _url.match(PATH_PARAM_RE);
8030
8044
  if (matches) {
@@ -8043,7 +8057,7 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
8043
8057
  name = name.substring(1);
8044
8058
  style = "matrix";
8045
8059
  }
8046
- const value = path2[name];
8060
+ const value = path3[name];
8047
8061
  if (value === undefined || value === null) {
8048
8062
  continue;
8049
8063
  }
@@ -8074,11 +8088,11 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
8074
8088
  }
8075
8089
  return url;
8076
8090
  };
8077
- var getUrl = ({ baseUrl, path: path2, query, querySerializer, url: _url }) => {
8091
+ var getUrl = ({ baseUrl, path: path3, query, querySerializer, url: _url }) => {
8078
8092
  const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
8079
8093
  let url = (baseUrl ?? "") + pathUrl;
8080
- if (path2) {
8081
- url = defaultPathSerializer({ path: path2, url });
8094
+ if (path3) {
8095
+ url = defaultPathSerializer({ path: path3, url });
8082
8096
  }
8083
8097
  let search = query ? querySerializer(query) : "";
8084
8098
  if (search.startsWith("?")) {
@@ -9590,49 +9604,49 @@ All tasks completed.`));
9590
9604
  }
9591
9605
  // src/hooks/auto-update-checker/checker.ts
9592
9606
  import * as fs3 from "fs";
9593
- import * as path3 from "path";
9607
+ import * as path4 from "path";
9594
9608
  import { fileURLToPath } from "url";
9595
9609
 
9596
9610
  // src/hooks/auto-update-checker/constants.ts
9597
- import * as path2 from "path";
9598
- import * as os2 from "os";
9611
+ import * as path3 from "path";
9612
+ import * as os3 from "os";
9599
9613
  import * as fs2 from "fs";
9600
9614
  var PACKAGE_NAME = "oh-my-opencode";
9601
9615
  var NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
9602
9616
  var NPM_FETCH_TIMEOUT = 5000;
9603
9617
  function getCacheDir() {
9604
9618
  if (process.platform === "win32") {
9605
- return path2.join(process.env.LOCALAPPDATA ?? os2.homedir(), "opencode");
9619
+ return path3.join(process.env.LOCALAPPDATA ?? os3.homedir(), "opencode");
9606
9620
  }
9607
- return path2.join(os2.homedir(), ".cache", "opencode");
9621
+ return path3.join(os3.homedir(), ".cache", "opencode");
9608
9622
  }
9609
9623
  var CACHE_DIR = getCacheDir();
9610
- var VERSION_FILE = path2.join(CACHE_DIR, "version");
9611
- var INSTALLED_PACKAGE_JSON = path2.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
9624
+ var VERSION_FILE = path3.join(CACHE_DIR, "version");
9625
+ var INSTALLED_PACKAGE_JSON = path3.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
9612
9626
  function getUserConfigDir() {
9613
9627
  if (process.platform === "win32") {
9614
- const crossPlatformDir = path2.join(os2.homedir(), ".config");
9615
- const appdataDir = process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
9616
- const crossPlatformConfig = path2.join(crossPlatformDir, "opencode", "opencode.json");
9617
- const crossPlatformConfigJsonc = path2.join(crossPlatformDir, "opencode", "opencode.jsonc");
9628
+ const crossPlatformDir = path3.join(os3.homedir(), ".config");
9629
+ const appdataDir = process.env.APPDATA ?? path3.join(os3.homedir(), "AppData", "Roaming");
9630
+ const crossPlatformConfig = path3.join(crossPlatformDir, "opencode", "opencode.json");
9631
+ const crossPlatformConfigJsonc = path3.join(crossPlatformDir, "opencode", "opencode.jsonc");
9618
9632
  if (fs2.existsSync(crossPlatformConfig) || fs2.existsSync(crossPlatformConfigJsonc)) {
9619
9633
  return crossPlatformDir;
9620
9634
  }
9621
9635
  return appdataDir;
9622
9636
  }
9623
- return process.env.XDG_CONFIG_HOME ?? path2.join(os2.homedir(), ".config");
9637
+ return process.env.XDG_CONFIG_HOME ?? path3.join(os3.homedir(), ".config");
9624
9638
  }
9625
9639
  function getWindowsAppdataDir() {
9626
9640
  if (process.platform !== "win32")
9627
9641
  return null;
9628
- return process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
9642
+ return process.env.APPDATA ?? path3.join(os3.homedir(), "AppData", "Roaming");
9629
9643
  }
9630
9644
  var USER_CONFIG_DIR = getUserConfigDir();
9631
- var USER_OPENCODE_CONFIG = path2.join(USER_CONFIG_DIR, "opencode", "opencode.json");
9632
- var USER_OPENCODE_CONFIG_JSONC = path2.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
9645
+ var USER_OPENCODE_CONFIG = path3.join(USER_CONFIG_DIR, "opencode", "opencode.json");
9646
+ var USER_OPENCODE_CONFIG_JSONC = path3.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
9633
9647
 
9634
9648
  // src/hooks/auto-update-checker/checker.ts
9635
- import * as os3 from "os";
9649
+ import * as os4 from "os";
9636
9650
  function isLocalDevMode(directory) {
9637
9651
  return getLocalDevPath(directory) !== null;
9638
9652
  }
@@ -9641,18 +9655,18 @@ function stripJsonComments(json2) {
9641
9655
  }
9642
9656
  function getConfigPaths(directory) {
9643
9657
  const paths = [
9644
- path3.join(directory, ".opencode", "opencode.json"),
9645
- path3.join(directory, ".opencode", "opencode.jsonc"),
9658
+ path4.join(directory, ".opencode", "opencode.json"),
9659
+ path4.join(directory, ".opencode", "opencode.jsonc"),
9646
9660
  USER_OPENCODE_CONFIG,
9647
9661
  USER_OPENCODE_CONFIG_JSONC
9648
9662
  ];
9649
9663
  if (process.platform === "win32") {
9650
- const crossPlatformDir = path3.join(os3.homedir(), ".config");
9664
+ const crossPlatformDir = path4.join(os4.homedir(), ".config");
9651
9665
  const appdataDir = getWindowsAppdataDir();
9652
9666
  if (appdataDir) {
9653
9667
  const alternateDir = USER_CONFIG_DIR === crossPlatformDir ? appdataDir : crossPlatformDir;
9654
- const alternateConfig = path3.join(alternateDir, "opencode", "opencode.json");
9655
- const alternateConfigJsonc = path3.join(alternateDir, "opencode", "opencode.jsonc");
9668
+ const alternateConfig = path4.join(alternateDir, "opencode", "opencode.json");
9669
+ const alternateConfigJsonc = path4.join(alternateDir, "opencode", "opencode.jsonc");
9656
9670
  if (!paths.includes(alternateConfig)) {
9657
9671
  paths.push(alternateConfig);
9658
9672
  }
@@ -9689,9 +9703,9 @@ function getLocalDevPath(directory) {
9689
9703
  function findPackageJsonUp(startPath) {
9690
9704
  try {
9691
9705
  const stat = fs3.statSync(startPath);
9692
- let dir = stat.isDirectory() ? startPath : path3.dirname(startPath);
9706
+ let dir = stat.isDirectory() ? startPath : path4.dirname(startPath);
9693
9707
  for (let i2 = 0;i2 < 10; i2++) {
9694
- const pkgPath = path3.join(dir, "package.json");
9708
+ const pkgPath = path4.join(dir, "package.json");
9695
9709
  if (fs3.existsSync(pkgPath)) {
9696
9710
  try {
9697
9711
  const content = fs3.readFileSync(pkgPath, "utf-8");
@@ -9700,7 +9714,7 @@ function findPackageJsonUp(startPath) {
9700
9714
  return pkgPath;
9701
9715
  } catch {}
9702
9716
  }
9703
- const parent = path3.dirname(dir);
9717
+ const parent = path4.dirname(dir);
9704
9718
  if (parent === dir)
9705
9719
  break;
9706
9720
  dir = parent;
@@ -9742,7 +9756,7 @@ function getCachedVersion() {
9742
9756
  }
9743
9757
  } catch {}
9744
9758
  try {
9745
- const currentDir = path3.dirname(fileURLToPath(import.meta.url));
9759
+ const currentDir = path4.dirname(fileURLToPath(import.meta.url));
9746
9760
  const pkgPath = findPackageJsonUp(currentDir);
9747
9761
  if (pkgPath) {
9748
9762
  const content = fs3.readFileSync(pkgPath, "utf-8");
@@ -10199,8 +10213,8 @@ function getPluginCheckDefinition() {
10199
10213
 
10200
10214
  // src/cli/doctor/checks/config.ts
10201
10215
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
10202
- import { homedir as homedir4 } from "os";
10203
- import { join as join5 } from "path";
10216
+ import { homedir as homedir5 } from "os";
10217
+ import { join as join6 } from "path";
10204
10218
 
10205
10219
  // node_modules/zod/v4/classic/external.js
10206
10220
  var exports_external = {};
@@ -10931,10 +10945,10 @@ function mergeDefs(...defs) {
10931
10945
  function cloneDef(schema2) {
10932
10946
  return mergeDefs(schema2._zod.def);
10933
10947
  }
10934
- function getElementAtPath(obj, path4) {
10935
- if (!path4)
10948
+ function getElementAtPath(obj, path5) {
10949
+ if (!path5)
10936
10950
  return obj;
10937
- return path4.reduce((acc, key) => acc?.[key], obj);
10951
+ return path5.reduce((acc, key) => acc?.[key], obj);
10938
10952
  }
10939
10953
  function promiseAllObject(promisesObj) {
10940
10954
  const keys = Object.keys(promisesObj);
@@ -11293,11 +11307,11 @@ function aborted(x2, startIndex = 0) {
11293
11307
  }
11294
11308
  return false;
11295
11309
  }
11296
- function prefixIssues(path4, issues) {
11310
+ function prefixIssues(path5, issues) {
11297
11311
  return issues.map((iss) => {
11298
11312
  var _a;
11299
11313
  (_a = iss).path ?? (_a.path = []);
11300
- iss.path.unshift(path4);
11314
+ iss.path.unshift(path5);
11301
11315
  return iss;
11302
11316
  });
11303
11317
  }
@@ -11465,7 +11479,7 @@ function treeifyError(error, _mapper) {
11465
11479
  return issue2.message;
11466
11480
  };
11467
11481
  const result = { errors: [] };
11468
- const processError = (error2, path4 = []) => {
11482
+ const processError = (error2, path5 = []) => {
11469
11483
  var _a, _b;
11470
11484
  for (const issue2 of error2.issues) {
11471
11485
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -11475,7 +11489,7 @@ function treeifyError(error, _mapper) {
11475
11489
  } else if (issue2.code === "invalid_element") {
11476
11490
  processError({ issues: issue2.issues }, issue2.path);
11477
11491
  } else {
11478
- const fullpath = [...path4, ...issue2.path];
11492
+ const fullpath = [...path5, ...issue2.path];
11479
11493
  if (fullpath.length === 0) {
11480
11494
  result.errors.push(mapper(issue2));
11481
11495
  continue;
@@ -11507,8 +11521,8 @@ function treeifyError(error, _mapper) {
11507
11521
  }
11508
11522
  function toDotPath(_path) {
11509
11523
  const segs = [];
11510
- const path4 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11511
- for (const seg of path4) {
11524
+ const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11525
+ for (const seg of path5) {
11512
11526
  if (typeof seg === "number")
11513
11527
  segs.push(`[${seg}]`);
11514
11528
  else if (typeof seg === "symbol")
@@ -22541,23 +22555,31 @@ var BuiltinAgentNameSchema = exports_external.enum([
22541
22555
  "explore",
22542
22556
  "frontend-ui-ux-engineer",
22543
22557
  "document-writer",
22544
- "multimodal-looker"
22558
+ "multimodal-looker",
22559
+ "Metis (Plan Consultant)",
22560
+ "Momus (Plan Reviewer)",
22561
+ "orchestrator-sisyphus"
22545
22562
  ]);
22546
22563
  var BuiltinSkillNameSchema = exports_external.enum([
22547
- "playwright"
22564
+ "playwright",
22565
+ "frontend-ui-ux",
22566
+ "git-master"
22548
22567
  ]);
22549
22568
  var OverridableAgentNameSchema = exports_external.enum([
22550
22569
  "build",
22551
22570
  "plan",
22552
22571
  "Sisyphus",
22553
22572
  "OpenCode-Builder",
22554
- "Planner-Sisyphus",
22573
+ "Prometheus (Planner)",
22574
+ "Metis (Plan Consultant)",
22575
+ "Momus (Plan Reviewer)",
22555
22576
  "oracle",
22556
22577
  "librarian",
22557
22578
  "explore",
22558
22579
  "frontend-ui-ux-engineer",
22559
22580
  "document-writer",
22560
- "multimodal-looker"
22581
+ "multimodal-looker",
22582
+ "orchestrator-sisyphus"
22561
22583
  ]);
22562
22584
  var HookNameSchema = exports_external.enum([
22563
22585
  "todo-continuation-enforcer",
@@ -22587,13 +22609,19 @@ var HookNameSchema = exports_external.enum([
22587
22609
  "compaction-context-injector",
22588
22610
  "claude-code-hooks",
22589
22611
  "auto-slash-command",
22590
- "edit-error-recovery"
22612
+ "edit-error-recovery",
22613
+ "prometheus-md-only",
22614
+ "start-work",
22615
+ "sisyphus-orchestrator"
22591
22616
  ]);
22592
22617
  var BuiltinCommandNameSchema = exports_external.enum([
22593
- "init-deep"
22618
+ "init-deep",
22619
+ "start-work"
22594
22620
  ]);
22595
22621
  var AgentOverrideConfigSchema = exports_external.object({
22596
22622
  model: exports_external.string().optional(),
22623
+ category: exports_external.string().optional(),
22624
+ skills: exports_external.array(exports_external.string()).optional(),
22597
22625
  temperature: exports_external.number().min(0).max(2).optional(),
22598
22626
  top_p: exports_external.number().min(0).max(1).optional(),
22599
22627
  prompt: exports_external.string().optional(),
@@ -22610,13 +22638,16 @@ var AgentOverridesSchema = exports_external.object({
22610
22638
  plan: AgentOverrideConfigSchema.optional(),
22611
22639
  Sisyphus: AgentOverrideConfigSchema.optional(),
22612
22640
  "OpenCode-Builder": AgentOverrideConfigSchema.optional(),
22613
- "Planner-Sisyphus": AgentOverrideConfigSchema.optional(),
22641
+ "Prometheus (Planner)": AgentOverrideConfigSchema.optional(),
22642
+ "Metis (Plan Consultant)": AgentOverrideConfigSchema.optional(),
22643
+ "Momus (Plan Reviewer)": AgentOverrideConfigSchema.optional(),
22614
22644
  oracle: AgentOverrideConfigSchema.optional(),
22615
22645
  librarian: AgentOverrideConfigSchema.optional(),
22616
22646
  explore: AgentOverrideConfigSchema.optional(),
22617
22647
  "frontend-ui-ux-engineer": AgentOverrideConfigSchema.optional(),
22618
22648
  "document-writer": AgentOverrideConfigSchema.optional(),
22619
- "multimodal-looker": AgentOverrideConfigSchema.optional()
22649
+ "multimodal-looker": AgentOverrideConfigSchema.optional(),
22650
+ "orchestrator-sisyphus": AgentOverrideConfigSchema.optional()
22620
22651
  });
22621
22652
  var ClaudeCodeConfigSchema = exports_external.object({
22622
22653
  mcp: exports_external.boolean().optional(),
@@ -22633,6 +22664,30 @@ var SisyphusAgentConfigSchema = exports_external.object({
22633
22664
  planner_enabled: exports_external.boolean().optional(),
22634
22665
  replace_plan: exports_external.boolean().optional()
22635
22666
  });
22667
+ var CategoryConfigSchema = exports_external.object({
22668
+ model: exports_external.string(),
22669
+ temperature: exports_external.number().min(0).max(2).optional(),
22670
+ top_p: exports_external.number().min(0).max(1).optional(),
22671
+ maxTokens: exports_external.number().optional(),
22672
+ thinking: exports_external.object({
22673
+ type: exports_external.enum(["enabled", "disabled"]),
22674
+ budgetTokens: exports_external.number().optional()
22675
+ }).optional(),
22676
+ reasoningEffort: exports_external.enum(["low", "medium", "high"]).optional(),
22677
+ textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
22678
+ tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
22679
+ prompt_append: exports_external.string().optional()
22680
+ });
22681
+ var BuiltinCategoryNameSchema = exports_external.enum([
22682
+ "visual-engineering",
22683
+ "ultrabrain",
22684
+ "artistry",
22685
+ "quick",
22686
+ "most-capable",
22687
+ "writing",
22688
+ "general"
22689
+ ]);
22690
+ var CategoriesConfigSchema = exports_external.record(exports_external.string(), CategoryConfigSchema);
22636
22691
  var CommentCheckerConfigSchema = exports_external.object({
22637
22692
  custom_prompt: exports_external.string().optional()
22638
22693
  });
@@ -22720,6 +22775,13 @@ var BackgroundTaskConfigSchema = exports_external.object({
22720
22775
  providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional(),
22721
22776
  modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional()
22722
22777
  });
22778
+ var NotificationConfigSchema = exports_external.object({
22779
+ force_enable: exports_external.boolean().optional()
22780
+ });
22781
+ var GitMasterConfigSchema = exports_external.object({
22782
+ commit_footer: exports_external.boolean().default(true),
22783
+ include_co_authored_by: exports_external.boolean().default(true)
22784
+ });
22723
22785
  var OhMyOpenCodeConfigSchema = exports_external.object({
22724
22786
  $schema: exports_external.string().optional(),
22725
22787
  disabled_mcps: exports_external.array(AnyMcpNameSchema).optional(),
@@ -22728,6 +22790,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
22728
22790
  disabled_hooks: exports_external.array(HookNameSchema).optional(),
22729
22791
  disabled_commands: exports_external.array(BuiltinCommandNameSchema).optional(),
22730
22792
  agents: AgentOverridesSchema.optional(),
22793
+ categories: CategoriesConfigSchema.optional(),
22731
22794
  claude_code: ClaudeCodeConfigSchema.optional(),
22732
22795
  google_auth: exports_external.boolean().optional(),
22733
22796
  sisyphus_agent: SisyphusAgentConfigSchema.optional(),
@@ -22736,12 +22799,14 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
22736
22799
  auto_update: exports_external.boolean().optional(),
22737
22800
  skills: SkillsConfigSchema.optional(),
22738
22801
  ralph_loop: RalphLoopConfigSchema.optional(),
22739
- background_task: BackgroundTaskConfigSchema.optional()
22802
+ background_task: BackgroundTaskConfigSchema.optional(),
22803
+ notification: NotificationConfigSchema.optional(),
22804
+ git_master: GitMasterConfigSchema.optional()
22740
22805
  });
22741
22806
  // src/cli/doctor/checks/config.ts
22742
- var USER_CONFIG_DIR2 = join5(homedir4(), ".config", "opencode");
22743
- var USER_CONFIG_BASE = join5(USER_CONFIG_DIR2, `${PACKAGE_NAME2}`);
22744
- var PROJECT_CONFIG_BASE = join5(process.cwd(), ".opencode", PACKAGE_NAME2);
22807
+ var USER_CONFIG_DIR2 = join6(homedir5(), ".config", "opencode");
22808
+ var USER_CONFIG_BASE = join6(USER_CONFIG_DIR2, `${PACKAGE_NAME2}`);
22809
+ var PROJECT_CONFIG_BASE = join6(process.cwd(), ".opencode", PACKAGE_NAME2);
22745
22810
  function findConfigPath() {
22746
22811
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
22747
22812
  if (projectDetected.format !== "none") {
@@ -22839,11 +22904,11 @@ function getConfigCheckDefinition() {
22839
22904
 
22840
22905
  // src/cli/doctor/checks/auth.ts
22841
22906
  import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
22842
- import { homedir as homedir5 } from "os";
22843
- import { join as join6 } from "path";
22844
- var OPENCODE_CONFIG_DIR = join6(homedir5(), ".config", "opencode");
22845
- var OPENCODE_JSON = join6(OPENCODE_CONFIG_DIR, "opencode.json");
22846
- var OPENCODE_JSONC = join6(OPENCODE_CONFIG_DIR, "opencode.jsonc");
22907
+ import { homedir as homedir6 } from "os";
22908
+ import { join as join7 } from "path";
22909
+ var OPENCODE_CONFIG_DIR = join7(homedir6(), ".config", "opencode");
22910
+ var OPENCODE_JSON = join7(OPENCODE_CONFIG_DIR, "opencode.json");
22911
+ var OPENCODE_JSONC = join7(OPENCODE_CONFIG_DIR, "opencode.jsonc");
22847
22912
  var AUTH_PLUGINS = {
22848
22913
  anthropic: { plugin: "builtin", name: "Anthropic (Claude)" },
22849
22914
  openai: { plugin: "opencode-openai-codex-auth", name: "OpenAI (ChatGPT)" },
@@ -23284,13 +23349,13 @@ function getLspCheckDefinition() {
23284
23349
 
23285
23350
  // src/cli/doctor/checks/mcp.ts
23286
23351
  import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
23287
- import { homedir as homedir6 } from "os";
23288
- import { join as join7 } from "path";
23352
+ import { homedir as homedir7 } from "os";
23353
+ import { join as join8 } from "path";
23289
23354
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
23290
23355
  var MCP_CONFIG_PATHS = [
23291
- join7(homedir6(), ".claude", ".mcp.json"),
23292
- join7(process.cwd(), ".mcp.json"),
23293
- join7(process.cwd(), ".claude", ".mcp.json")
23356
+ join8(homedir7(), ".claude", ".mcp.json"),
23357
+ join8(process.cwd(), ".mcp.json"),
23358
+ join8(process.cwd(), ".claude", ".mcp.json")
23294
23359
  ];
23295
23360
  function loadUserMcpConfig() {
23296
23361
  const servers = {};
@@ -23689,6 +23754,140 @@ async function doctor(options = {}) {
23689
23754
  return result.exitCode;
23690
23755
  }
23691
23756
 
23757
+ // src/auth/antigravity/storage.ts
23758
+ import { promises as fs4 } from "fs";
23759
+ import { join as join9, dirname as dirname2 } from "path";
23760
+ function getDataDir2() {
23761
+ return join9(getDataDir(), "opencode");
23762
+ }
23763
+ function getStoragePath() {
23764
+ return join9(getDataDir2(), "oh-my-opencode-accounts.json");
23765
+ }
23766
+ async function loadAccounts(path5) {
23767
+ const storagePath = path5 ?? getStoragePath();
23768
+ try {
23769
+ const content = await fs4.readFile(storagePath, "utf-8");
23770
+ const data = JSON.parse(content);
23771
+ if (!isValidAccountStorage(data)) {
23772
+ return null;
23773
+ }
23774
+ return data;
23775
+ } catch (error45) {
23776
+ const errorCode = error45.code;
23777
+ if (errorCode === "ENOENT") {
23778
+ return null;
23779
+ }
23780
+ if (error45 instanceof SyntaxError) {
23781
+ return null;
23782
+ }
23783
+ throw error45;
23784
+ }
23785
+ }
23786
+ async function saveAccounts(storage, path5) {
23787
+ const storagePath = path5 ?? getStoragePath();
23788
+ await fs4.mkdir(dirname2(storagePath), { recursive: true });
23789
+ const content = JSON.stringify(storage, null, 2);
23790
+ const tempPath = `${storagePath}.tmp.${process.pid}.${Date.now()}`;
23791
+ await fs4.writeFile(tempPath, content, { encoding: "utf-8", mode: 384 });
23792
+ try {
23793
+ await fs4.rename(tempPath, storagePath);
23794
+ } catch (error45) {
23795
+ await fs4.unlink(tempPath).catch(() => {});
23796
+ throw error45;
23797
+ }
23798
+ }
23799
+ function isValidAccountStorage(data) {
23800
+ if (typeof data !== "object" || data === null) {
23801
+ return false;
23802
+ }
23803
+ const obj = data;
23804
+ if (typeof obj.version !== "number") {
23805
+ return false;
23806
+ }
23807
+ if (!Array.isArray(obj.accounts)) {
23808
+ return false;
23809
+ }
23810
+ if (typeof obj.activeIndex !== "number") {
23811
+ return false;
23812
+ }
23813
+ return true;
23814
+ }
23815
+
23816
+ // src/cli/commands/auth.ts
23817
+ async function listAccounts() {
23818
+ const accounts = await loadAccounts();
23819
+ if (!accounts || accounts.accounts.length === 0) {
23820
+ console.log("No accounts found.");
23821
+ console.log("Run 'opencode auth login' and select Google (Antigravity) to add accounts.");
23822
+ return 0;
23823
+ }
23824
+ console.log(`
23825
+ Google Antigravity Accounts (${accounts.accounts.length}/10):
23826
+ `);
23827
+ for (let i2 = 0;i2 < accounts.accounts.length; i2++) {
23828
+ const acc = accounts.accounts[i2];
23829
+ const isActive = i2 === accounts.activeIndex;
23830
+ const activeMarker = isActive ? "* " : " ";
23831
+ console.log(`${activeMarker}[${i2}] ${acc.email || "Unknown"}`);
23832
+ console.log(` Tier: ${acc.tier || "free"}`);
23833
+ const rateLimits = acc.rateLimits || {};
23834
+ const now = Date.now();
23835
+ const limited = [];
23836
+ if (rateLimits.claude && rateLimits.claude > now) {
23837
+ const mins = Math.ceil((rateLimits.claude - now) / 60000);
23838
+ limited.push(`claude (${mins}m)`);
23839
+ }
23840
+ if (rateLimits["gemini-flash"] && rateLimits["gemini-flash"] > now) {
23841
+ const mins = Math.ceil((rateLimits["gemini-flash"] - now) / 60000);
23842
+ limited.push(`gemini-flash (${mins}m)`);
23843
+ }
23844
+ if (rateLimits["gemini-pro"] && rateLimits["gemini-pro"] > now) {
23845
+ const mins = Math.ceil((rateLimits["gemini-pro"] - now) / 60000);
23846
+ limited.push(`gemini-pro (${mins}m)`);
23847
+ }
23848
+ if (limited.length > 0) {
23849
+ console.log(` Rate limited: ${limited.join(", ")}`);
23850
+ }
23851
+ console.log();
23852
+ }
23853
+ return 0;
23854
+ }
23855
+ async function removeAccount(indexOrEmail) {
23856
+ const accounts = await loadAccounts();
23857
+ if (!accounts || accounts.accounts.length === 0) {
23858
+ console.error("No accounts found.");
23859
+ return 1;
23860
+ }
23861
+ let index;
23862
+ const parsedIndex = Number(indexOrEmail);
23863
+ if (Number.isInteger(parsedIndex) && String(parsedIndex) === indexOrEmail) {
23864
+ index = parsedIndex;
23865
+ } else {
23866
+ index = accounts.accounts.findIndex((acc) => acc.email === indexOrEmail);
23867
+ if (index === -1) {
23868
+ console.error(`Account not found: ${indexOrEmail}`);
23869
+ return 1;
23870
+ }
23871
+ }
23872
+ if (index < 0 || index >= accounts.accounts.length) {
23873
+ console.error(`Invalid index: ${index}. Valid range: 0-${accounts.accounts.length - 1}`);
23874
+ return 1;
23875
+ }
23876
+ const removed = accounts.accounts[index];
23877
+ accounts.accounts.splice(index, 1);
23878
+ if (accounts.accounts.length === 0) {
23879
+ accounts.activeIndex = -1;
23880
+ } else if (accounts.activeIndex >= accounts.accounts.length) {
23881
+ accounts.activeIndex = accounts.accounts.length - 1;
23882
+ } else if (accounts.activeIndex > index) {
23883
+ accounts.activeIndex--;
23884
+ }
23885
+ await saveAccounts(accounts);
23886
+ console.log(`Removed account: ${removed.email || "Unknown"} (index ${index})`);
23887
+ console.log(`Remaining accounts: ${accounts.accounts.length}`);
23888
+ return 0;
23889
+ }
23890
+
23692
23891
  // src/cli/index.ts
23693
23892
  var packageJson = await Promise.resolve().then(() => __toESM(require_package(), 1));
23694
23893
  var VERSION = packageJson.version;
@@ -23776,6 +23975,32 @@ Categories:
23776
23975
  const exitCode = await doctor(doctorOptions);
23777
23976
  process.exit(exitCode);
23778
23977
  });
23978
+ var authCommand = program2.command("auth").description("Manage Google Antigravity accounts");
23979
+ authCommand.command("list").description("List all Google Antigravity accounts").addHelpText("after", `
23980
+ Examples:
23981
+ $ bunx oh-my-opencode auth list
23982
+
23983
+ Shows:
23984
+ - Account index and email
23985
+ - Account tier (free/paid)
23986
+ - Active account (marked with *)
23987
+ - Rate limit status per model family
23988
+ `).action(async () => {
23989
+ const exitCode = await listAccounts();
23990
+ process.exit(exitCode);
23991
+ });
23992
+ authCommand.command("remove <index-or-email>").description("Remove an account by index or email").addHelpText("after", `
23993
+ Examples:
23994
+ $ bunx oh-my-opencode auth remove 0
23995
+ $ bunx oh-my-opencode auth remove user@example.com
23996
+
23997
+ Note:
23998
+ - Use 'auth list' to see account indices
23999
+ - Removing the active account will switch to the next available account
24000
+ `).action(async (indexOrEmail) => {
24001
+ const exitCode = await removeAccount(indexOrEmail);
24002
+ process.exit(exitCode);
24003
+ });
23779
24004
  program2.command("version").description("Show version information").action(() => {
23780
24005
  console.log(`oh-my-opencode v${VERSION}`);
23781
24006
  });