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

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 (71) hide show
  1. package/README.ja.md +6 -13
  2. package/README.md +20 -25
  3. package/README.zh-cn.md +18 -20
  4. package/bin/oh-my-opencode.js +80 -0
  5. package/bin/platform.js +38 -0
  6. package/bin/platform.test.ts +148 -0
  7. package/dist/agents/orchestrator-sisyphus.d.ts +2 -2
  8. package/dist/agents/prometheus-prompt.d.ts +1 -1
  9. package/dist/agents/sisyphus-junior.d.ts +1 -1
  10. package/dist/agents/utils.d.ts +3 -3
  11. package/dist/cli/config-manager.d.ts +9 -1
  12. package/dist/cli/doctor/checks/opencode.d.ts +5 -1
  13. package/dist/cli/index.js +292 -156
  14. package/dist/config/schema.d.ts +205 -211
  15. package/dist/features/background-agent/concurrency.d.ts +17 -0
  16. package/dist/features/background-agent/manager.d.ts +29 -5
  17. package/dist/features/background-agent/types.d.ts +3 -1
  18. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  19. package/dist/features/builtin-commands/templates/refactor.d.ts +1 -1
  20. package/dist/features/claude-code-session-state/state.d.ts +2 -1
  21. package/dist/features/context-injector/index.d.ts +1 -1
  22. package/dist/features/hook-message-injector/index.d.ts +1 -1
  23. package/dist/features/opencode-skill-loader/skill-content.d.ts +11 -0
  24. package/dist/features/skill-mcp-manager/manager.d.ts +10 -0
  25. package/dist/features/task-toast-manager/index.d.ts +1 -1
  26. package/dist/features/task-toast-manager/manager.d.ts +2 -1
  27. package/dist/features/task-toast-manager/types.d.ts +5 -0
  28. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  29. package/dist/hooks/anthropic-context-window-limit-recovery/executor.d.ts +1 -1
  30. package/dist/hooks/anthropic-context-window-limit-recovery/index.d.ts +1 -2
  31. package/dist/hooks/anthropic-context-window-limit-recovery/types.d.ts +0 -5
  32. package/dist/hooks/comment-checker/cli.d.ts +0 -1
  33. package/dist/hooks/comment-checker/cli.test.d.ts +1 -0
  34. package/dist/hooks/compaction-context-injector/index.d.ts +7 -1
  35. package/dist/hooks/delegate-task-retry/index.d.ts +24 -0
  36. package/dist/hooks/delegate-task-retry/index.test.d.ts +1 -0
  37. package/dist/hooks/index.d.ts +1 -2
  38. package/dist/hooks/prometheus-md-only/constants.d.ts +1 -1
  39. package/dist/index.js +3688 -2120
  40. package/dist/shared/agent-tool-restrictions.d.ts +7 -0
  41. package/dist/shared/index.d.ts +4 -0
  42. package/dist/shared/opencode-version.d.ts +6 -3
  43. package/dist/shared/permission-compat.d.ts +22 -9
  44. package/dist/shared/session-cursor.d.ts +13 -0
  45. package/dist/shared/session-cursor.test.d.ts +1 -0
  46. package/dist/shared/shell-env.d.ts +41 -0
  47. package/dist/shared/shell-env.test.d.ts +1 -0
  48. package/dist/shared/system-directive.d.ts +31 -0
  49. package/dist/tools/{sisyphus-task → delegate-task}/constants.d.ts +1 -1
  50. package/dist/tools/{sisyphus-task → delegate-task}/index.d.ts +1 -1
  51. package/dist/tools/{sisyphus-task → delegate-task}/tools.d.ts +2 -2
  52. package/dist/tools/delegate-task/tools.test.d.ts +1 -0
  53. package/dist/tools/{sisyphus-task → delegate-task}/types.d.ts +2 -2
  54. package/dist/tools/index.d.ts +1 -1
  55. package/dist/tools/interactive-bash/constants.d.ts +1 -1
  56. package/dist/tools/look-at/tools.d.ts +7 -0
  57. package/dist/tools/look-at/tools.test.d.ts +1 -0
  58. package/dist/tools/lsp/client.d.ts +0 -3
  59. package/dist/tools/lsp/config.test.d.ts +1 -0
  60. package/dist/tools/lsp/index.d.ts +1 -1
  61. package/dist/tools/lsp/tools.d.ts +0 -1
  62. package/dist/tools/lsp/types.d.ts +0 -33
  63. package/dist/tools/lsp/utils.d.ts +1 -4
  64. package/dist/tools/skill/types.d.ts +3 -0
  65. package/package.json +18 -3
  66. package/postinstall.mjs +43 -0
  67. package/dist/hooks/empty-message-sanitizer/index.d.ts +0 -12
  68. package/dist/hooks/preemptive-compaction/constants.d.ts +0 -3
  69. package/dist/hooks/preemptive-compaction/index.d.ts +0 -24
  70. package/dist/hooks/preemptive-compaction/types.d.ts +0 -17
  71. /package/dist/{tools/sisyphus-task/tools.test.d.ts → features/claude-code-session-state/state.test.d.ts} +0 -0
package/dist/cli/index.js CHANGED
@@ -5929,12 +5929,6 @@ var NOT_CACHED;
5929
5929
  var init_opencode_version = __esm(() => {
5930
5930
  NOT_CACHED = Symbol("NOT_CACHED");
5931
5931
  });
5932
-
5933
- // src/shared/permission-compat.ts
5934
- var init_permission_compat = __esm(() => {
5935
- init_opencode_version();
5936
- });
5937
-
5938
5932
  // src/shared/external-plugin-detector.ts
5939
5933
  var init_external_plugin_detector = __esm(() => {
5940
5934
  init_logger();
@@ -5943,6 +5937,17 @@ var init_external_plugin_detector = __esm(() => {
5943
5937
 
5944
5938
  // src/shared/zip-extractor.ts
5945
5939
  var init_zip_extractor = () => {};
5940
+ // src/shared/session-cursor.ts
5941
+ var sessionCursors;
5942
+ var init_session_cursor = __esm(() => {
5943
+ sessionCursors = new Map;
5944
+ });
5945
+ // src/shared/system-directive.ts
5946
+ var init_system_directive = () => {};
5947
+
5948
+ // src/shared/agent-tool-restrictions.ts
5949
+ var init_agent_tool_restrictions = () => {};
5950
+
5946
5951
  // src/shared/index.ts
5947
5952
  var init_shared = __esm(() => {
5948
5953
  init_frontmatter();
@@ -5962,9 +5967,11 @@ var init_shared = __esm(() => {
5962
5967
  init_migration();
5963
5968
  init_opencode_config_dir();
5964
5969
  init_opencode_version();
5965
- init_permission_compat();
5966
5970
  init_external_plugin_detector();
5967
5971
  init_zip_extractor();
5972
+ init_session_cursor();
5973
+ init_system_directive();
5974
+ init_agent_tool_restrictions();
5968
5975
  });
5969
5976
 
5970
5977
  // src/cli/config-manager.ts
@@ -6030,6 +6037,31 @@ async function fetchLatestVersion(packageName) {
6030
6037
  return null;
6031
6038
  }
6032
6039
  }
6040
+ async function fetchNpmDistTags(packageName) {
6041
+ try {
6042
+ const res = await fetch(`https://registry.npmjs.org/-/package/${packageName}/dist-tags`, {
6043
+ signal: AbortSignal.timeout(NPM_FETCH_TIMEOUT_MS)
6044
+ });
6045
+ if (!res.ok)
6046
+ return null;
6047
+ const data = await res.json();
6048
+ return data;
6049
+ } catch {
6050
+ return null;
6051
+ }
6052
+ }
6053
+ async function getPluginNameWithVersion(currentVersion) {
6054
+ const distTags = await fetchNpmDistTags(PACKAGE_NAME);
6055
+ if (distTags) {
6056
+ const allTags = new Set([...PRIORITIZED_TAGS, ...Object.keys(distTags)]);
6057
+ for (const tag of allTags) {
6058
+ if (distTags[tag] === currentVersion) {
6059
+ return `${PACKAGE_NAME}@${tag}`;
6060
+ }
6061
+ }
6062
+ }
6063
+ return `${PACKAGE_NAME}@${currentVersion}`;
6064
+ }
6033
6065
  function detectConfigFormat() {
6034
6066
  const configJsonc = getConfigJsonc();
6035
6067
  const configJson = getConfigJson();
@@ -6072,17 +6104,17 @@ function ensureConfigDir() {
6072
6104
  mkdirSync(configDir, { recursive: true });
6073
6105
  }
6074
6106
  }
6075
- function addPluginToOpenCodeConfig() {
6107
+ async function addPluginToOpenCodeConfig(currentVersion) {
6076
6108
  try {
6077
6109
  ensureConfigDir();
6078
6110
  } catch (err) {
6079
6111
  return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
6080
6112
  }
6081
6113
  const { format: format2, path: path2 } = detectConfigFormat();
6082
- const pluginName = "oh-my-opencode";
6114
+ const pluginEntry = await getPluginNameWithVersion(currentVersion);
6083
6115
  try {
6084
6116
  if (format2 === "none") {
6085
- const config2 = { plugin: [pluginName] };
6117
+ const config2 = { plugin: [pluginEntry] };
6086
6118
  writeFileSync(path2, JSON.stringify(config2, null, 2) + `
6087
6119
  `);
6088
6120
  return { success: true, configPath: path2 };
@@ -6093,25 +6125,30 @@ function addPluginToOpenCodeConfig() {
6093
6125
  }
6094
6126
  const config = parseResult.config;
6095
6127
  const plugins = config.plugin ?? [];
6096
- if (plugins.some((p2) => p2.startsWith(pluginName))) {
6097
- return { success: true, configPath: path2 };
6128
+ const existingIndex = plugins.findIndex((p2) => p2 === PACKAGE_NAME || p2.startsWith(`${PACKAGE_NAME}@`));
6129
+ if (existingIndex !== -1) {
6130
+ if (plugins[existingIndex] === pluginEntry) {
6131
+ return { success: true, configPath: path2 };
6132
+ }
6133
+ plugins[existingIndex] = pluginEntry;
6134
+ } else {
6135
+ plugins.push(pluginEntry);
6098
6136
  }
6099
- config.plugin = [...plugins, pluginName];
6137
+ config.plugin = plugins;
6100
6138
  if (format2 === "jsonc") {
6101
6139
  const content = readFileSync2(path2, "utf-8");
6102
6140
  const pluginArrayRegex = /"plugin"\s*:\s*\[([\s\S]*?)\]/;
6103
6141
  const match = content.match(pluginArrayRegex);
6104
6142
  if (match) {
6105
- const arrayContent = match[1].trim();
6106
- const newArrayContent = arrayContent ? `${arrayContent},
6107
- "${pluginName}"` : `"${pluginName}"`;
6143
+ const formattedPlugins = plugins.map((p2) => `"${p2}"`).join(`,
6144
+ `);
6108
6145
  const newContent = content.replace(pluginArrayRegex, `"plugin": [
6109
- ${newArrayContent}
6146
+ ${formattedPlugins}
6110
6147
  ]`);
6111
6148
  writeFileSync(path2, newContent);
6112
6149
  } else {
6113
6150
  const newContent = content.replace(/^(\s*\{)/, `$1
6114
- "plugin": ["${pluginName}"],`);
6151
+ "plugin": ["${pluginEntry}"],`);
6115
6152
  writeFileSync(path2, newContent);
6116
6153
  }
6117
6154
  } else {
@@ -6431,11 +6468,12 @@ function detectCurrentConfig() {
6431
6468
  } catch {}
6432
6469
  return result;
6433
6470
  }
6434
- var OPENCODE_BINARIES, configContext = null, BUN_INSTALL_TIMEOUT_SECONDS = 60, BUN_INSTALL_TIMEOUT_MS, ANTIGRAVITY_PROVIDER_CONFIG;
6471
+ 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;
6435
6472
  var init_config_manager = __esm(() => {
6436
6473
  init_shared();
6437
6474
  OPENCODE_BINARIES = ["opencode", "opencode-desktop"];
6438
6475
  BUN_INSTALL_TIMEOUT_MS = BUN_INSTALL_TIMEOUT_SECONDS * 1000;
6476
+ PRIORITIZED_TAGS = ["latest", "beta", "next"];
6439
6477
  ANTIGRAVITY_PROVIDER_CONFIG = {
6440
6478
  google: {
6441
6479
  name: "Google",
@@ -6493,12 +6531,12 @@ function getWindowsAppdataDir() {
6493
6531
  return null;
6494
6532
  return process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
6495
6533
  }
6496
- var PACKAGE_NAME = "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
+ 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;
6497
6535
  var init_constants = __esm(() => {
6498
- NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
6536
+ NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
6499
6537
  CACHE_DIR = getCacheDir();
6500
6538
  VERSION_FILE = path2.join(CACHE_DIR, "version");
6501
- INSTALLED_PACKAGE_JSON = path2.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
6539
+ INSTALLED_PACKAGE_JSON = path2.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
6502
6540
  USER_CONFIG_DIR = getUserConfigDir();
6503
6541
  USER_OPENCODE_CONFIG = path2.join(USER_CONFIG_DIR, "opencode", "opencode.json");
6504
6542
  USER_OPENCODE_CONFIG_JSONC = path2.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
@@ -6535,7 +6573,7 @@ function removeFromBunLock(packageName) {
6535
6573
  return false;
6536
6574
  }
6537
6575
  }
6538
- function invalidatePackage(packageName = PACKAGE_NAME) {
6576
+ function invalidatePackage(packageName = PACKAGE_NAME2) {
6539
6577
  try {
6540
6578
  const pkgDir = path3.join(CACHE_DIR, "node_modules", packageName);
6541
6579
  const pkgJsonPath = path3.join(CACHE_DIR, "package.json");
@@ -6696,9 +6734,9 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
6696
6734
  log("[auto-update-checker] Failed to update pinned version in config");
6697
6735
  return;
6698
6736
  }
6699
- log(`[auto-update-checker] Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME}@${latestVersion}`);
6737
+ log(`[auto-update-checker] Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME2}@${latestVersion}`);
6700
6738
  }
6701
- invalidatePackage(PACKAGE_NAME);
6739
+ invalidatePackage(PACKAGE_NAME2);
6702
6740
  const installSuccess = await runBunInstallSafe();
6703
6741
  if (installSuccess) {
6704
6742
  await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
@@ -6843,7 +6881,7 @@ function getLocalDevPath(directory) {
6843
6881
  const config = JSON.parse(stripJsonComments(content));
6844
6882
  const plugins = config.plugin ?? [];
6845
6883
  for (const entry of plugins) {
6846
- if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
6884
+ if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME2)) {
6847
6885
  try {
6848
6886
  return fileURLToPath(entry);
6849
6887
  } catch {
@@ -6867,7 +6905,7 @@ function findPackageJsonUp(startPath) {
6867
6905
  try {
6868
6906
  const content = fs4.readFileSync(pkgPath, "utf-8");
6869
6907
  const pkg = JSON.parse(content);
6870
- if (pkg.name === PACKAGE_NAME)
6908
+ if (pkg.name === PACKAGE_NAME2)
6871
6909
  return pkgPath;
6872
6910
  } catch {}
6873
6911
  }
@@ -6903,11 +6941,11 @@ function findPluginEntry(directory) {
6903
6941
  const config = JSON.parse(stripJsonComments(content));
6904
6942
  const plugins = config.plugin ?? [];
6905
6943
  for (const entry of plugins) {
6906
- if (entry === PACKAGE_NAME) {
6944
+ if (entry === PACKAGE_NAME2) {
6907
6945
  return { entry, isPinned: false, pinnedVersion: null, configPath };
6908
6946
  }
6909
- if (entry.startsWith(`${PACKAGE_NAME}@`)) {
6910
- const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
6947
+ if (entry.startsWith(`${PACKAGE_NAME2}@`)) {
6948
+ const pinnedVersion = entry.slice(PACKAGE_NAME2.length + 1);
6911
6949
  const isPinned = pinnedVersion !== "latest";
6912
6950
  return { entry, isPinned, pinnedVersion: isPinned ? pinnedVersion : null, configPath };
6913
6951
  }
@@ -6944,7 +6982,7 @@ function getCachedVersion() {
6944
6982
  function updatePinnedVersion(configPath, oldEntry, newVersion) {
6945
6983
  try {
6946
6984
  const content = fs4.readFileSync(configPath, "utf-8");
6947
- const newEntry = `${PACKAGE_NAME}@${newVersion}`;
6985
+ const newEntry = `${PACKAGE_NAME2}@${newVersion}`;
6948
6986
  const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
6949
6987
  if (!pluginMatch || pluginMatch.index === undefined) {
6950
6988
  log(`[auto-update-checker] No "plugin" array found in ${configPath}`);
@@ -7032,88 +7070,6 @@ var init_checker = __esm(() => {
7032
7070
  init_logger();
7033
7071
  });
7034
7072
 
7035
- // package.json
7036
- var require_package = __commonJS((exports, module) => {
7037
- module.exports = {
7038
- name: "oh-my-opencode",
7039
- version: "3.0.0-beta.7",
7040
- description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
7041
- main: "dist/index.js",
7042
- types: "dist/index.d.ts",
7043
- type: "module",
7044
- bin: {
7045
- "oh-my-opencode": "./dist/cli/index.js"
7046
- },
7047
- files: [
7048
- "dist"
7049
- ],
7050
- exports: {
7051
- ".": {
7052
- types: "./dist/index.d.ts",
7053
- import: "./dist/index.js"
7054
- },
7055
- "./schema.json": "./dist/oh-my-opencode.schema.json"
7056
- },
7057
- scripts: {
7058
- build: "bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
7059
- "build:schema": "bun run script/build-schema.ts",
7060
- clean: "rm -rf dist",
7061
- prepublishOnly: "bun run clean && bun run build",
7062
- typecheck: "tsc --noEmit",
7063
- test: "bun test"
7064
- },
7065
- keywords: [
7066
- "opencode",
7067
- "plugin",
7068
- "oracle",
7069
- "librarian",
7070
- "agents",
7071
- "ai",
7072
- "llm"
7073
- ],
7074
- author: "YeonGyu-Kim",
7075
- license: "SUL-1.0",
7076
- repository: {
7077
- type: "git",
7078
- url: "git+https://github.com/code-yeongyu/oh-my-opencode.git"
7079
- },
7080
- bugs: {
7081
- url: "https://github.com/code-yeongyu/oh-my-opencode/issues"
7082
- },
7083
- homepage: "https://github.com/code-yeongyu/oh-my-opencode#readme",
7084
- dependencies: {
7085
- "@ast-grep/cli": "^0.40.0",
7086
- "@ast-grep/napi": "^0.40.0",
7087
- "@clack/prompts": "^0.11.0",
7088
- "@code-yeongyu/comment-checker": "^0.6.1",
7089
- "@modelcontextprotocol/sdk": "^1.25.1",
7090
- "@openauthjs/openauth": "^0.4.3",
7091
- "@opencode-ai/plugin": "^1.1.19",
7092
- "@opencode-ai/sdk": "^1.1.19",
7093
- commander: "^14.0.2",
7094
- hono: "^4.10.4",
7095
- "js-yaml": "^4.1.1",
7096
- "jsonc-parser": "^3.3.1",
7097
- open: "^11.0.0",
7098
- picocolors: "^1.1.1",
7099
- picomatch: "^4.0.2",
7100
- "xdg-basedir": "^5.1.0",
7101
- zod: "^4.1.8"
7102
- },
7103
- devDependencies: {
7104
- "@types/js-yaml": "^4.0.9",
7105
- "@types/picomatch": "^3.0.2",
7106
- "bun-types": "latest",
7107
- typescript: "^5.7.3"
7108
- },
7109
- trustedDependencies: [
7110
- "@ast-grep/cli",
7111
- "@ast-grep/napi",
7112
- "@code-yeongyu/comment-checker"
7113
- ]
7114
- };
7115
- });
7116
-
7117
7073
  // node_modules/commander/esm.mjs
7118
7074
  var import__ = __toESM(require_commander(), 1);
7119
7075
  var {
@@ -7713,6 +7669,103 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
7713
7669
  // src/cli/install.ts
7714
7670
  init_config_manager();
7715
7671
  var import_picocolors2 = __toESM(require_picocolors(), 1);
7672
+ // package.json
7673
+ var package_default = {
7674
+ name: "oh-my-opencode",
7675
+ version: "3.0.0-beta.9",
7676
+ description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
7677
+ main: "dist/index.js",
7678
+ types: "dist/index.d.ts",
7679
+ type: "module",
7680
+ bin: {
7681
+ "oh-my-opencode": "./bin/oh-my-opencode.js"
7682
+ },
7683
+ files: [
7684
+ "dist",
7685
+ "bin",
7686
+ "postinstall.mjs"
7687
+ ],
7688
+ exports: {
7689
+ ".": {
7690
+ types: "./dist/index.d.ts",
7691
+ import: "./dist/index.js"
7692
+ },
7693
+ "./schema.json": "./dist/oh-my-opencode.schema.json"
7694
+ },
7695
+ scripts: {
7696
+ build: "bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
7697
+ "build:all": "bun run build && bun run build:binaries",
7698
+ "build:binaries": "bun run script/build-binaries.ts",
7699
+ "build:schema": "bun run script/build-schema.ts",
7700
+ clean: "rm -rf dist",
7701
+ postinstall: "node postinstall.mjs",
7702
+ prepublishOnly: "bun run clean && bun run build",
7703
+ typecheck: "tsc --noEmit",
7704
+ test: "bun test"
7705
+ },
7706
+ keywords: [
7707
+ "opencode",
7708
+ "plugin",
7709
+ "oracle",
7710
+ "librarian",
7711
+ "agents",
7712
+ "ai",
7713
+ "llm"
7714
+ ],
7715
+ author: "YeonGyu-Kim",
7716
+ license: "SUL-1.0",
7717
+ repository: {
7718
+ type: "git",
7719
+ url: "git+https://github.com/code-yeongyu/oh-my-opencode.git"
7720
+ },
7721
+ bugs: {
7722
+ url: "https://github.com/code-yeongyu/oh-my-opencode/issues"
7723
+ },
7724
+ homepage: "https://github.com/code-yeongyu/oh-my-opencode#readme",
7725
+ dependencies: {
7726
+ "@ast-grep/cli": "^0.40.0",
7727
+ "@ast-grep/napi": "^0.40.0",
7728
+ "@clack/prompts": "^0.11.0",
7729
+ "@code-yeongyu/comment-checker": "^0.6.1",
7730
+ "@modelcontextprotocol/sdk": "^1.25.1",
7731
+ "@openauthjs/openauth": "^0.4.3",
7732
+ "@opencode-ai/plugin": "^1.1.19",
7733
+ "@opencode-ai/sdk": "^1.1.19",
7734
+ commander: "^14.0.2",
7735
+ "detect-libc": "^2.0.0",
7736
+ hono: "^4.10.4",
7737
+ "js-yaml": "^4.1.1",
7738
+ "jsonc-parser": "^3.3.1",
7739
+ open: "^11.0.0",
7740
+ picocolors: "^1.1.1",
7741
+ picomatch: "^4.0.2",
7742
+ "xdg-basedir": "^5.1.0",
7743
+ zod: "^4.1.8"
7744
+ },
7745
+ devDependencies: {
7746
+ "@types/js-yaml": "^4.0.9",
7747
+ "@types/picomatch": "^3.0.2",
7748
+ "bun-types": "latest",
7749
+ typescript: "^5.7.3"
7750
+ },
7751
+ optionalDependencies: {
7752
+ "oh-my-opencode-darwin-arm64": "3.0.0-beta.9",
7753
+ "oh-my-opencode-darwin-x64": "3.0.0-beta.9",
7754
+ "oh-my-opencode-linux-arm64": "3.0.0-beta.9",
7755
+ "oh-my-opencode-linux-arm64-musl": "3.0.0-beta.9",
7756
+ "oh-my-opencode-linux-x64": "3.0.0-beta.9",
7757
+ "oh-my-opencode-linux-x64-musl": "3.0.0-beta.9",
7758
+ "oh-my-opencode-windows-x64": "3.0.0-beta.9"
7759
+ },
7760
+ trustedDependencies: [
7761
+ "@ast-grep/cli",
7762
+ "@ast-grep/napi",
7763
+ "@code-yeongyu/comment-checker"
7764
+ ]
7765
+ };
7766
+
7767
+ // src/cli/install.ts
7768
+ var VERSION = package_default.version;
7716
7769
  var SYMBOLS = {
7717
7770
  check: import_picocolors2.default.green("\u2713"),
7718
7771
  cross: import_picocolors2.default.red("\u2717"),
@@ -7931,7 +7984,7 @@ async function runNonTuiInstall(args) {
7931
7984
  }
7932
7985
  const config = argsToConfig(args);
7933
7986
  printStep(step++, totalSteps, "Adding oh-my-opencode plugin...");
7934
- const pluginResult = addPluginToOpenCodeConfig();
7987
+ const pluginResult = await addPluginToOpenCodeConfig(VERSION);
7935
7988
  if (!pluginResult.success) {
7936
7989
  printError(`Failed: ${pluginResult.error}`);
7937
7990
  return 1;
@@ -8013,7 +8066,7 @@ async function install(args) {
8013
8066
  if (!config)
8014
8067
  return 1;
8015
8068
  s.start("Adding oh-my-opencode to OpenCode config");
8016
- const pluginResult = addPluginToOpenCodeConfig();
8069
+ const pluginResult = await addPluginToOpenCodeConfig(VERSION);
8017
8070
  if (!pluginResult.success) {
8018
8071
  s.stop(`Failed to add plugin: ${pluginResult.error}`);
8019
8072
  Se(import_picocolors2.default.red("Installation failed."));
@@ -10131,18 +10184,57 @@ var EXIT_CODES = {
10131
10184
  FAILURE: 1
10132
10185
  };
10133
10186
  var MIN_OPENCODE_VERSION = "1.0.150";
10134
- var PACKAGE_NAME2 = "oh-my-opencode";
10187
+ var PACKAGE_NAME3 = "oh-my-opencode";
10135
10188
  var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
10136
10189
 
10137
10190
  // src/cli/doctor/checks/opencode.ts
10191
+ var WINDOWS_EXECUTABLE_EXTS = [".exe", ".cmd", ".bat", ".ps1"];
10192
+ function getBinaryLookupCommand(platform) {
10193
+ return platform === "win32" ? "where" : "which";
10194
+ }
10195
+ function parseBinaryPaths(output) {
10196
+ return output.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
10197
+ }
10198
+ function selectBinaryPath(paths, platform) {
10199
+ if (paths.length === 0)
10200
+ return null;
10201
+ if (platform !== "win32")
10202
+ return paths[0];
10203
+ const normalized = paths.map((path5) => path5.toLowerCase());
10204
+ for (const ext of WINDOWS_EXECUTABLE_EXTS) {
10205
+ const index = normalized.findIndex((path5) => path5.endsWith(ext));
10206
+ if (index !== -1)
10207
+ return paths[index];
10208
+ }
10209
+ return paths[0];
10210
+ }
10211
+ function buildVersionCommand(binaryPath, platform) {
10212
+ if (platform === "win32" && binaryPath.toLowerCase().endsWith(".ps1")) {
10213
+ return [
10214
+ "powershell",
10215
+ "-NoProfile",
10216
+ "-ExecutionPolicy",
10217
+ "Bypass",
10218
+ "-File",
10219
+ binaryPath,
10220
+ "--version"
10221
+ ];
10222
+ }
10223
+ return [binaryPath, "--version"];
10224
+ }
10138
10225
  async function findOpenCodeBinary() {
10139
10226
  for (const binary2 of OPENCODE_BINARIES2) {
10140
10227
  try {
10141
- const proc = Bun.spawn(["which", binary2], { stdout: "pipe", stderr: "pipe" });
10228
+ const lookupCommand = getBinaryLookupCommand(process.platform);
10229
+ const proc = Bun.spawn([lookupCommand, binary2], { stdout: "pipe", stderr: "pipe" });
10142
10230
  const output = await new Response(proc.stdout).text();
10143
10231
  await proc.exited;
10144
10232
  if (proc.exitCode === 0) {
10145
- return { binary: binary2, path: output.trim() };
10233
+ const paths = parseBinaryPaths(output);
10234
+ const selectedPath = selectBinaryPath(paths, process.platform);
10235
+ if (selectedPath) {
10236
+ return { binary: binary2, path: selectedPath };
10237
+ }
10146
10238
  }
10147
10239
  } catch {
10148
10240
  continue;
@@ -10150,9 +10242,10 @@ async function findOpenCodeBinary() {
10150
10242
  }
10151
10243
  return null;
10152
10244
  }
10153
- async function getOpenCodeVersion2(binary2) {
10245
+ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
10154
10246
  try {
10155
- const proc = Bun.spawn([binary2, "--version"], { stdout: "pipe", stderr: "pipe" });
10247
+ const command = buildVersionCommand(binaryPath, platform);
10248
+ const proc = Bun.spawn(command, { stdout: "pipe", stderr: "pipe" });
10156
10249
  const output = await new Response(proc.stdout).text();
10157
10250
  await proc.exited;
10158
10251
  if (proc.exitCode === 0) {
@@ -10190,7 +10283,7 @@ async function getOpenCodeInfo() {
10190
10283
  binary: null
10191
10284
  };
10192
10285
  }
10193
- const version = await getOpenCodeVersion2(binaryInfo.binary);
10286
+ const version = await getOpenCodeVersion2(binaryInfo.path ?? binaryInfo.binary);
10194
10287
  return {
10195
10288
  installed: true,
10196
10289
  version,
@@ -10255,7 +10348,7 @@ function detectConfigPath() {
10255
10348
  }
10256
10349
  function findPluginEntry2(plugins) {
10257
10350
  for (const plugin of plugins) {
10258
- if (plugin === PACKAGE_NAME2 || plugin.startsWith(`${PACKAGE_NAME2}@`)) {
10351
+ if (plugin === PACKAGE_NAME3 || plugin.startsWith(`${PACKAGE_NAME3}@`)) {
10259
10352
  const isPinned = plugin.includes("@");
10260
10353
  const version = isPinned ? plugin.split("@")[1] : null;
10261
10354
  return { entry: plugin, isPinned, version };
@@ -22741,14 +22834,13 @@ var HookNameSchema = exports_external.enum([
22741
22834
  "agent-usage-reminder",
22742
22835
  "non-interactive-env",
22743
22836
  "interactive-bash-session",
22744
- "empty-message-sanitizer",
22745
22837
  "thinking-block-validator",
22746
22838
  "ralph-loop",
22747
- "preemptive-compaction",
22748
22839
  "compaction-context-injector",
22749
22840
  "claude-code-hooks",
22750
22841
  "auto-slash-command",
22751
22842
  "edit-error-recovery",
22843
+ "delegate-task-retry",
22752
22844
  "prometheus-md-only",
22753
22845
  "start-work",
22754
22846
  "sisyphus-orchestrator"
@@ -22866,11 +22958,8 @@ var DynamicContextPruningConfigSchema = exports_external.object({
22866
22958
  var ExperimentalConfigSchema = exports_external.object({
22867
22959
  aggressive_truncation: exports_external.boolean().optional(),
22868
22960
  auto_resume: exports_external.boolean().optional(),
22869
- preemptive_compaction: exports_external.boolean().optional(),
22870
- preemptive_compaction_threshold: exports_external.number().min(0.5).max(0.95).optional(),
22871
22961
  truncate_all_tool_outputs: exports_external.boolean().optional(),
22872
- dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(),
22873
- dcp_for_compaction: exports_external.boolean().optional()
22962
+ dynamic_context_pruning: DynamicContextPruningConfigSchema.optional()
22874
22963
  });
22875
22964
  var SkillSourceSchema = exports_external.union([
22876
22965
  exports_external.string(),
@@ -22914,7 +23003,8 @@ var RalphLoopConfigSchema = exports_external.object({
22914
23003
  var BackgroundTaskConfigSchema = exports_external.object({
22915
23004
  defaultConcurrency: exports_external.number().min(1).optional(),
22916
23005
  providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional(),
22917
- modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional()
23006
+ modelConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(1)).optional(),
23007
+ staleTimeoutMs: exports_external.number().min(60000).optional()
22918
23008
  });
22919
23009
  var NotificationConfigSchema = exports_external.object({
22920
23010
  force_enable: exports_external.boolean().optional()
@@ -22945,8 +23035,8 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
22945
23035
  });
22946
23036
  // src/cli/doctor/checks/config.ts
22947
23037
  var USER_CONFIG_DIR2 = join6(homedir4(), ".config", "opencode");
22948
- var USER_CONFIG_BASE = join6(USER_CONFIG_DIR2, `${PACKAGE_NAME2}`);
22949
- var PROJECT_CONFIG_BASE = join6(process.cwd(), ".opencode", PACKAGE_NAME2);
23038
+ var USER_CONFIG_BASE = join6(USER_CONFIG_DIR2, `${PACKAGE_NAME3}`);
23039
+ var PROJECT_CONFIG_BASE = join6(process.cwd(), ".opencode", PACKAGE_NAME3);
22950
23040
  function findConfigPath() {
22951
23041
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
22952
23042
  if (projectDetected.format !== "none") {
@@ -23418,6 +23508,61 @@ function getGhCliCheckDefinition() {
23418
23508
  };
23419
23509
  }
23420
23510
 
23511
+ // src/tools/lsp/config.ts
23512
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
23513
+ import { join as join8 } from "path";
23514
+ import { homedir as homedir6 } from "os";
23515
+ function isServerInstalled(command) {
23516
+ if (command.length === 0)
23517
+ return false;
23518
+ const cmd = command[0];
23519
+ if (cmd.includes("/") || cmd.includes("\\")) {
23520
+ if (existsSync10(cmd))
23521
+ return true;
23522
+ }
23523
+ const isWindows = process.platform === "win32";
23524
+ let exts = [""];
23525
+ if (isWindows) {
23526
+ const pathExt = process.env.PATHEXT || "";
23527
+ if (pathExt) {
23528
+ const systemExts = pathExt.split(";").filter(Boolean);
23529
+ exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
23530
+ } else {
23531
+ exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
23532
+ }
23533
+ }
23534
+ let pathEnv = process.env.PATH || "";
23535
+ if (isWindows && !pathEnv) {
23536
+ pathEnv = process.env.Path || "";
23537
+ }
23538
+ const pathSeparator = isWindows ? ";" : ":";
23539
+ const paths = pathEnv.split(pathSeparator);
23540
+ for (const p2 of paths) {
23541
+ for (const suffix of exts) {
23542
+ if (existsSync10(join8(p2, cmd + suffix))) {
23543
+ return true;
23544
+ }
23545
+ }
23546
+ }
23547
+ const cwd = process.cwd();
23548
+ const additionalBases = [
23549
+ join8(cwd, "node_modules", ".bin"),
23550
+ join8(homedir6(), ".config", "opencode", "bin"),
23551
+ join8(homedir6(), ".config", "opencode", "node_modules", ".bin")
23552
+ ];
23553
+ for (const base of additionalBases) {
23554
+ for (const suffix of exts) {
23555
+ if (existsSync10(join8(base, cmd + suffix))) {
23556
+ return true;
23557
+ }
23558
+ }
23559
+ }
23560
+ if (cmd === "bun" || cmd === "node") {
23561
+ return true;
23562
+ }
23563
+ return false;
23564
+ }
23565
+
23421
23566
  // src/cli/doctor/checks/lsp.ts
23422
23567
  var DEFAULT_LSP_SERVERS = [
23423
23568
  { id: "typescript-language-server", binary: "typescript-language-server", extensions: [".ts", ".tsx", ".js", ".jsx"] },
@@ -23425,19 +23570,10 @@ var DEFAULT_LSP_SERVERS = [
23425
23570
  { id: "rust-analyzer", binary: "rust-analyzer", extensions: [".rs"] },
23426
23571
  { id: "gopls", binary: "gopls", extensions: [".go"] }
23427
23572
  ];
23428
- async function checkBinaryExists3(binary2) {
23429
- try {
23430
- const proc = Bun.spawn(["which", binary2], { stdout: "pipe", stderr: "pipe" });
23431
- await proc.exited;
23432
- return proc.exitCode === 0;
23433
- } catch {
23434
- return false;
23435
- }
23436
- }
23437
23573
  async function getLspServersInfo() {
23438
23574
  const servers = [];
23439
23575
  for (const server2 of DEFAULT_LSP_SERVERS) {
23440
- const installed = await checkBinaryExists3(server2.binary);
23576
+ const installed = isServerInstalled([server2.binary]);
23441
23577
  servers.push({
23442
23578
  id: server2.id,
23443
23579
  installed,
@@ -23489,23 +23625,23 @@ function getLspCheckDefinition() {
23489
23625
  }
23490
23626
 
23491
23627
  // src/cli/doctor/checks/mcp.ts
23492
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
23493
- import { homedir as homedir6 } from "os";
23494
- import { join as join8 } from "path";
23628
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
23629
+ import { homedir as homedir7 } from "os";
23630
+ import { join as join9 } from "path";
23495
23631
  init_shared();
23496
23632
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
23497
23633
  var MCP_CONFIG_PATHS = [
23498
- join8(homedir6(), ".claude", ".mcp.json"),
23499
- join8(process.cwd(), ".mcp.json"),
23500
- join8(process.cwd(), ".claude", ".mcp.json")
23634
+ join9(homedir7(), ".claude", ".mcp.json"),
23635
+ join9(process.cwd(), ".mcp.json"),
23636
+ join9(process.cwd(), ".claude", ".mcp.json")
23501
23637
  ];
23502
23638
  function loadUserMcpConfig() {
23503
23639
  const servers = {};
23504
23640
  for (const configPath of MCP_CONFIG_PATHS) {
23505
- if (!existsSync10(configPath))
23641
+ if (!existsSync11(configPath))
23506
23642
  continue;
23507
23643
  try {
23508
- const content = readFileSync8(configPath, "utf-8");
23644
+ const content = readFileSync9(configPath, "utf-8");
23509
23645
  const config2 = parseJsonc(content);
23510
23646
  if (config2.mcpServers) {
23511
23647
  Object.assign(servers, config2.mcpServers);
@@ -23900,15 +24036,14 @@ async function doctor(options = {}) {
23900
24036
  }
23901
24037
 
23902
24038
  // src/cli/index.ts
23903
- var packageJson = await Promise.resolve().then(() => __toESM(require_package(), 1));
23904
- var VERSION = packageJson.version;
24039
+ var VERSION2 = package_default.version;
23905
24040
  var program2 = new Command;
23906
- program2.name("oh-my-opencode").description("The ultimate OpenCode plugin - multi-model orchestration, LSP tools, and more").version(VERSION, "-v, --version", "Show version number");
23907
- program2.command("install").description("Install and configure oh-my-opencode with interactive setup").option("--no-tui", "Run in non-interactive mode (requires all options)").option("--claude <value>", "Claude subscription: no, yes, max20").option("--chatgpt <value>", "ChatGPT subscription: no, yes").option("--gemini <value>", "Gemini integration: no, yes").option("--skip-auth", "Skip authentication setup hints").addHelpText("after", `
24041
+ program2.name("oh-my-opencode").description("The ultimate OpenCode plugin - multi-model orchestration, LSP tools, and more").version(VERSION2, "-v, --version", "Show version number");
24042
+ program2.command("install").description("Install and configure oh-my-opencode with interactive setup").option("--no-tui", "Run in non-interactive mode (requires all options)").option("--claude <value>", "Claude subscription: no, yes, max20").option("--chatgpt <value>", "ChatGPT subscription: no, yes").option("--gemini <value>", "Gemini integration: no, yes").option("--copilot <value>", "GitHub Copilot subscription: no, yes").option("--skip-auth", "Skip authentication setup hints").addHelpText("after", `
23908
24043
  Examples:
23909
24044
  $ bunx oh-my-opencode install
23910
- $ bunx oh-my-opencode install --no-tui --claude=max20 --chatgpt=yes --gemini=yes
23911
- $ bunx oh-my-opencode install --no-tui --claude=no --chatgpt=no --gemini=no
24045
+ $ bunx oh-my-opencode install --no-tui --claude=max20 --chatgpt=yes --gemini=yes --copilot=no
24046
+ $ bunx oh-my-opencode install --no-tui --claude=no --chatgpt=no --gemini=no --copilot=yes
23912
24047
 
23913
24048
  Model Providers:
23914
24049
  Claude Required for Sisyphus (main orchestrator) and Librarian agents
@@ -23920,6 +24055,7 @@ Model Providers:
23920
24055
  claude: options.claude,
23921
24056
  chatgpt: options.chatgpt,
23922
24057
  gemini: options.gemini,
24058
+ copilot: options.copilot,
23923
24059
  skipAuth: options.skipAuth ?? false
23924
24060
  };
23925
24061
  const exitCode = await install(args);
@@ -23987,6 +24123,6 @@ Categories:
23987
24123
  process.exit(exitCode);
23988
24124
  });
23989
24125
  program2.command("version").description("Show version information").action(() => {
23990
- console.log(`oh-my-opencode v${VERSION}`);
24126
+ console.log(`oh-my-opencode v${VERSION2}`);
23991
24127
  });
23992
24128
  program2.parse();