opencode-dux 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +452 -0
  3. package/dist/agents/descriptions.d.ts +6 -0
  4. package/dist/agents/designer.d.ts +2 -0
  5. package/dist/agents/explorer.d.ts +2 -0
  6. package/dist/agents/fixer.d.ts +2 -0
  7. package/dist/agents/index.d.ts +22 -0
  8. package/dist/agents/interpreter.d.ts +2 -0
  9. package/dist/agents/librarian.d.ts +2 -0
  10. package/dist/agents/oracle.d.ts +2 -0
  11. package/dist/agents/orchestrator.d.ts +27 -0
  12. package/dist/agents/overrides.d.ts +18 -0
  13. package/dist/agents/prompt-blocks.d.ts +97 -0
  14. package/dist/agents/steward.d.ts +3 -0
  15. package/dist/cli/config-io.d.ts +24 -0
  16. package/dist/cli/config-manager.d.ts +4 -0
  17. package/dist/cli/index.d.ts +2 -0
  18. package/dist/cli/index.js +1006 -0
  19. package/dist/cli/install.d.ts +2 -0
  20. package/dist/cli/mcps.d.ts +13 -0
  21. package/dist/cli/model-key-normalization.d.ts +1 -0
  22. package/dist/cli/paths.d.ts +35 -0
  23. package/dist/cli/providers.d.ts +137 -0
  24. package/dist/cli/skills.d.ts +22 -0
  25. package/dist/cli/system.d.ts +5 -0
  26. package/dist/cli/types.d.ts +38 -0
  27. package/dist/config/constants.d.ts +12 -0
  28. package/dist/config/index.d.ts +4 -0
  29. package/dist/config/loader.d.ts +40 -0
  30. package/dist/config/runtime-preset.d.ts +12 -0
  31. package/dist/config/schema.d.ts +281 -0
  32. package/dist/config/utils.d.ts +10 -0
  33. package/dist/discovery/local/types.d.ts +79 -0
  34. package/dist/discovery/local.d.ts +73 -0
  35. package/dist/discovery/mcp-servers.d.ts +88 -0
  36. package/dist/discovery/skills.d.ts +94 -0
  37. package/dist/hooks/apply-patch/codec.d.ts +7 -0
  38. package/dist/hooks/apply-patch/errors.d.ts +25 -0
  39. package/dist/hooks/apply-patch/execution-context.d.ts +27 -0
  40. package/dist/hooks/apply-patch/index.d.ts +15 -0
  41. package/dist/hooks/apply-patch/matching.d.ts +26 -0
  42. package/dist/hooks/apply-patch/operations.d.ts +3 -0
  43. package/dist/hooks/apply-patch/patch.d.ts +2 -0
  44. package/dist/hooks/apply-patch/prepared-changes.d.ts +17 -0
  45. package/dist/hooks/apply-patch/resolution.d.ts +19 -0
  46. package/dist/hooks/apply-patch/rewrite.d.ts +7 -0
  47. package/dist/hooks/apply-patch/test-helpers.d.ts +6 -0
  48. package/dist/hooks/apply-patch/types.d.ts +80 -0
  49. package/dist/hooks/auto-update-checker/cache.d.ts +11 -0
  50. package/dist/hooks/auto-update-checker/checker.d.ts +32 -0
  51. package/dist/hooks/auto-update-checker/constants.d.ts +11 -0
  52. package/dist/hooks/auto-update-checker/index.d.ts +18 -0
  53. package/dist/hooks/auto-update-checker/types.d.ts +22 -0
  54. package/dist/hooks/chat-headers.d.ts +16 -0
  55. package/dist/hooks/context-pressure-reminder/index.d.ts +33 -0
  56. package/dist/hooks/delegate-task-retry/guidance.d.ts +2 -0
  57. package/dist/hooks/delegate-task-retry/hook.d.ts +8 -0
  58. package/dist/hooks/delegate-task-retry/index.d.ts +4 -0
  59. package/dist/hooks/delegate-task-retry/patterns.d.ts +11 -0
  60. package/dist/hooks/filter-available-skills/index.d.ts +32 -0
  61. package/dist/hooks/foreground-fallback/index.d.ts +72 -0
  62. package/dist/hooks/image-hook.d.ts +5 -0
  63. package/dist/hooks/index.d.ts +14 -0
  64. package/dist/hooks/json-error-recovery/hook.d.ts +18 -0
  65. package/dist/hooks/json-error-recovery/index.d.ts +1 -0
  66. package/dist/hooks/phase-reminder/index.d.ts +26 -0
  67. package/dist/hooks/post-file-tool-nudge/index.d.ts +19 -0
  68. package/dist/hooks/task-session-manager/index.d.ts +52 -0
  69. package/dist/hooks/todo-continuation/index.d.ts +53 -0
  70. package/dist/hooks/todo-continuation/todo-hygiene.d.ts +35 -0
  71. package/dist/index.d.ts +5 -0
  72. package/dist/index.js +31782 -0
  73. package/dist/mcp/context7.d.ts +6 -0
  74. package/dist/mcp/grep-app.d.ts +6 -0
  75. package/dist/mcp/index.d.ts +13 -0
  76. package/dist/mcp/types.d.ts +12 -0
  77. package/dist/mcp/websearch.d.ts +9 -0
  78. package/dist/skills/registry.d.ts +29 -0
  79. package/dist/subscriptions/accounts-store.d.ts +57 -0
  80. package/dist/subscriptions/index.d.ts +13 -0
  81. package/dist/subscriptions/neuralwatt-scraper.d.ts +14 -0
  82. package/dist/subscriptions/opencode-go-scraper.d.ts +27 -0
  83. package/dist/subscriptions/types.d.ts +115 -0
  84. package/dist/subscriptions/usage-service.d.ts +74 -0
  85. package/dist/tools/ast-grep/cli.d.ts +15 -0
  86. package/dist/tools/ast-grep/constants.d.ts +25 -0
  87. package/dist/tools/ast-grep/downloader.d.ts +5 -0
  88. package/dist/tools/ast-grep/index.d.ts +10 -0
  89. package/dist/tools/ast-grep/tools.d.ts +3 -0
  90. package/dist/tools/ast-grep/types.d.ts +30 -0
  91. package/dist/tools/ast-grep/utils.d.ts +4 -0
  92. package/dist/tools/delegate.d.ts +14 -0
  93. package/dist/tools/index.d.ts +5 -0
  94. package/dist/tools/preset-manager.d.ts +27 -0
  95. package/dist/tools/smartfetch/binary.d.ts +3 -0
  96. package/dist/tools/smartfetch/cache.d.ts +6 -0
  97. package/dist/tools/smartfetch/constants.d.ts +12 -0
  98. package/dist/tools/smartfetch/index.d.ts +3 -0
  99. package/dist/tools/smartfetch/network.d.ts +38 -0
  100. package/dist/tools/smartfetch/secondary-model.d.ts +28 -0
  101. package/dist/tools/smartfetch/tool.d.ts +3 -0
  102. package/dist/tools/smartfetch/types.d.ts +122 -0
  103. package/dist/tools/smartfetch/utils.d.ts +18 -0
  104. package/dist/tui-state.d.ts +168 -0
  105. package/dist/tui.d.ts +37 -0
  106. package/dist/tui.js +1896 -0
  107. package/dist/utils/agent-variant.d.ts +63 -0
  108. package/dist/utils/compat.d.ts +30 -0
  109. package/dist/utils/env.d.ts +1 -0
  110. package/dist/utils/index.d.ts +9 -0
  111. package/dist/utils/internal-initiator.d.ts +6 -0
  112. package/dist/utils/logger.d.ts +8 -0
  113. package/dist/utils/polling.d.ts +21 -0
  114. package/dist/utils/session-manager.d.ts +55 -0
  115. package/dist/utils/session.d.ts +90 -0
  116. package/dist/utils/subagent-depth.d.ts +35 -0
  117. package/dist/utils/system-collapse.d.ts +6 -0
  118. package/dist/utils/task.d.ts +4 -0
  119. package/dist/utils/zip-extractor.d.ts +1 -0
  120. package/index.ts +1 -0
  121. package/opencode-dux.schema.json +634 -0
  122. package/package.json +103 -0
  123. package/src/agents/descriptions.ts +55 -0
  124. package/src/agents/designer.test.ts +86 -0
  125. package/src/agents/designer.ts +154 -0
  126. package/src/agents/display-name.test.ts +186 -0
  127. package/src/agents/explorer.test.ts +79 -0
  128. package/src/agents/explorer.ts +144 -0
  129. package/src/agents/fixer.test.ts +79 -0
  130. package/src/agents/fixer.ts +145 -0
  131. package/src/agents/index.test.ts +472 -0
  132. package/src/agents/index.ts +248 -0
  133. package/src/agents/interpreter.ts +136 -0
  134. package/src/agents/librarian.test.ts +80 -0
  135. package/src/agents/librarian.ts +145 -0
  136. package/src/agents/oracle.test.ts +89 -0
  137. package/src/agents/oracle.ts +184 -0
  138. package/src/agents/orchestrator.test.ts +116 -0
  139. package/src/agents/orchestrator.ts +574 -0
  140. package/src/agents/overrides.ts +95 -0
  141. package/src/agents/prompt-blocks.test.ts +114 -0
  142. package/src/agents/prompt-blocks.ts +640 -0
  143. package/src/agents/steward.ts +146 -0
  144. package/src/cli/config-io.test.ts +536 -0
  145. package/src/cli/config-io.ts +473 -0
  146. package/src/cli/config-manager.test.ts +141 -0
  147. package/src/cli/config-manager.ts +4 -0
  148. package/src/cli/index.ts +88 -0
  149. package/src/cli/install.ts +282 -0
  150. package/src/cli/mcps.test.ts +62 -0
  151. package/src/cli/mcps.ts +39 -0
  152. package/src/cli/model-key-normalization.test.ts +21 -0
  153. package/src/cli/model-key-normalization.ts +60 -0
  154. package/src/cli/paths.test.ts +167 -0
  155. package/src/cli/paths.ts +144 -0
  156. package/src/cli/providers.test.ts +118 -0
  157. package/src/cli/providers.ts +141 -0
  158. package/src/cli/skills.test.ts +111 -0
  159. package/src/cli/skills.ts +103 -0
  160. package/src/cli/system.test.ts +91 -0
  161. package/src/cli/system.ts +180 -0
  162. package/src/cli/types.ts +43 -0
  163. package/src/config/constants.ts +58 -0
  164. package/src/config/index.ts +4 -0
  165. package/src/config/loader.test.ts +1194 -0
  166. package/src/config/loader.ts +269 -0
  167. package/src/config/model-resolution.test.ts +176 -0
  168. package/src/config/runtime-preset.test.ts +61 -0
  169. package/src/config/runtime-preset.ts +37 -0
  170. package/src/config/schema.ts +248 -0
  171. package/src/config/utils.test.ts +41 -0
  172. package/src/config/utils.ts +23 -0
  173. package/src/discovery/local/types.ts +85 -0
  174. package/src/discovery/local.ts +322 -0
  175. package/src/discovery/mcp-servers.ts +804 -0
  176. package/src/discovery/skills.ts +959 -0
  177. package/src/hooks/apply-patch/codec.test.ts +184 -0
  178. package/src/hooks/apply-patch/codec.ts +352 -0
  179. package/src/hooks/apply-patch/errors.ts +117 -0
  180. package/src/hooks/apply-patch/execution-context.ts +432 -0
  181. package/src/hooks/apply-patch/hook.test.ts +768 -0
  182. package/src/hooks/apply-patch/index.ts +126 -0
  183. package/src/hooks/apply-patch/matching.test.ts +215 -0
  184. package/src/hooks/apply-patch/matching.ts +586 -0
  185. package/src/hooks/apply-patch/operations.test.ts +1535 -0
  186. package/src/hooks/apply-patch/operations.ts +3 -0
  187. package/src/hooks/apply-patch/patch.ts +9 -0
  188. package/src/hooks/apply-patch/prepared-changes.ts +400 -0
  189. package/src/hooks/apply-patch/resolution.test.ts +420 -0
  190. package/src/hooks/apply-patch/resolution.ts +437 -0
  191. package/src/hooks/apply-patch/rewrite.ts +496 -0
  192. package/src/hooks/apply-patch/test-helpers.ts +52 -0
  193. package/src/hooks/apply-patch/types.ts +111 -0
  194. package/src/hooks/auto-update-checker/cache.test.ts +179 -0
  195. package/src/hooks/auto-update-checker/cache.ts +188 -0
  196. package/src/hooks/auto-update-checker/checker.test.ts +159 -0
  197. package/src/hooks/auto-update-checker/checker.ts +308 -0
  198. package/src/hooks/auto-update-checker/constants.ts +33 -0
  199. package/src/hooks/auto-update-checker/index.test.ts +282 -0
  200. package/src/hooks/auto-update-checker/index.ts +225 -0
  201. package/src/hooks/auto-update-checker/types.ts +26 -0
  202. package/src/hooks/chat-headers.test.ts +236 -0
  203. package/src/hooks/chat-headers.ts +97 -0
  204. package/src/hooks/context-pressure-reminder/index.test.ts +179 -0
  205. package/src/hooks/context-pressure-reminder/index.ts +137 -0
  206. package/src/hooks/delegate-task-retry/guidance.ts +41 -0
  207. package/src/hooks/delegate-task-retry/hook.ts +23 -0
  208. package/src/hooks/delegate-task-retry/index.test.ts +38 -0
  209. package/src/hooks/delegate-task-retry/index.ts +7 -0
  210. package/src/hooks/delegate-task-retry/patterns.ts +79 -0
  211. package/src/hooks/filter-available-skills/index.test.ts +297 -0
  212. package/src/hooks/filter-available-skills/index.ts +160 -0
  213. package/src/hooks/foreground-fallback/index.test.ts +624 -0
  214. package/src/hooks/foreground-fallback/index.ts +374 -0
  215. package/src/hooks/image-hook.ts +6 -0
  216. package/src/hooks/index.ts +17 -0
  217. package/src/hooks/json-error-recovery/hook.ts +73 -0
  218. package/src/hooks/json-error-recovery/index.test.ts +111 -0
  219. package/src/hooks/json-error-recovery/index.ts +6 -0
  220. package/src/hooks/phase-reminder/index.test.ts +74 -0
  221. package/src/hooks/phase-reminder/index.ts +85 -0
  222. package/src/hooks/post-file-tool-nudge/index.test.ts +94 -0
  223. package/src/hooks/post-file-tool-nudge/index.ts +63 -0
  224. package/src/hooks/task-session-manager/index.test.ts +833 -0
  225. package/src/hooks/task-session-manager/index.ts +434 -0
  226. package/src/hooks/todo-continuation/index.test.ts +3026 -0
  227. package/src/hooks/todo-continuation/index.ts +878 -0
  228. package/src/hooks/todo-continuation/todo-hygiene.test.ts +204 -0
  229. package/src/hooks/todo-continuation/todo-hygiene.ts +207 -0
  230. package/src/index.ts +1672 -0
  231. package/src/mcp/context7.ts +14 -0
  232. package/src/mcp/grep-app.ts +11 -0
  233. package/src/mcp/index.test.ts +96 -0
  234. package/src/mcp/index.ts +66 -0
  235. package/src/mcp/types.ts +16 -0
  236. package/src/mcp/websearch.ts +47 -0
  237. package/src/skills/codemap/README.md +60 -0
  238. package/src/skills/codemap/SKILL.md +174 -0
  239. package/src/skills/codemap/scripts/codemap.mjs +483 -0
  240. package/src/skills/codemap/scripts/codemap.test.ts +129 -0
  241. package/src/skills/registry.ts +218 -0
  242. package/src/skills/simplify/README.md +19 -0
  243. package/src/skills/simplify/SKILL.md +138 -0
  244. package/src/subscriptions/accounts-store.test.ts +236 -0
  245. package/src/subscriptions/accounts-store.ts +184 -0
  246. package/src/subscriptions/index.ts +30 -0
  247. package/src/subscriptions/neuralwatt-scraper.ts +108 -0
  248. package/src/subscriptions/opencode-go-scraper.ts +301 -0
  249. package/src/subscriptions/types.ts +145 -0
  250. package/src/subscriptions/usage-service.test.ts +202 -0
  251. package/src/subscriptions/usage-service.ts +651 -0
  252. package/src/tools/ast-grep/cli.ts +257 -0
  253. package/src/tools/ast-grep/constants.ts +214 -0
  254. package/src/tools/ast-grep/downloader.ts +131 -0
  255. package/src/tools/ast-grep/index.ts +24 -0
  256. package/src/tools/ast-grep/tools.ts +117 -0
  257. package/src/tools/ast-grep/types.ts +51 -0
  258. package/src/tools/ast-grep/utils.ts +126 -0
  259. package/src/tools/delegate-handoff.test.ts +18 -0
  260. package/src/tools/delegate.ts +508 -0
  261. package/src/tools/index.ts +8 -0
  262. package/src/tools/preset-manager.test.ts +795 -0
  263. package/src/tools/preset-manager.ts +332 -0
  264. package/src/tools/smartfetch/binary.ts +58 -0
  265. package/src/tools/smartfetch/cache.test.ts +34 -0
  266. package/src/tools/smartfetch/cache.ts +112 -0
  267. package/src/tools/smartfetch/constants.ts +29 -0
  268. package/src/tools/smartfetch/index.ts +8 -0
  269. package/src/tools/smartfetch/network.test.ts +178 -0
  270. package/src/tools/smartfetch/network.ts +614 -0
  271. package/src/tools/smartfetch/secondary-model.test.ts +85 -0
  272. package/src/tools/smartfetch/secondary-model.ts +276 -0
  273. package/src/tools/smartfetch/tool.test.ts +60 -0
  274. package/src/tools/smartfetch/tool.ts +832 -0
  275. package/src/tools/smartfetch/types.ts +135 -0
  276. package/src/tools/smartfetch/utils.test.ts +24 -0
  277. package/src/tools/smartfetch/utils.ts +456 -0
  278. package/src/tui-state.test.ts +867 -0
  279. package/src/tui-state.ts +1255 -0
  280. package/src/tui.test.ts +336 -0
  281. package/src/tui.ts +1539 -0
  282. package/src/utils/agent-variant.test.ts +244 -0
  283. package/src/utils/agent-variant.ts +187 -0
  284. package/src/utils/compat.ts +91 -0
  285. package/src/utils/env.ts +12 -0
  286. package/src/utils/index.ts +9 -0
  287. package/src/utils/internal-initiator.ts +28 -0
  288. package/src/utils/logger.test.ts +220 -0
  289. package/src/utils/logger.ts +136 -0
  290. package/src/utils/polling.test.ts +191 -0
  291. package/src/utils/polling.ts +67 -0
  292. package/src/utils/session-manager.test.ts +173 -0
  293. package/src/utils/session-manager.ts +356 -0
  294. package/src/utils/session.test.ts +110 -0
  295. package/src/utils/session.ts +389 -0
  296. package/src/utils/subagent-depth.test.ts +170 -0
  297. package/src/utils/subagent-depth.ts +75 -0
  298. package/src/utils/system-collapse.test.ts +86 -0
  299. package/src/utils/system-collapse.ts +24 -0
  300. package/src/utils/task.test.ts +24 -0
  301. package/src/utils/task.ts +20 -0
  302. package/src/utils/zip-extractor.ts +102 -0
@@ -0,0 +1,91 @@
1
+ /// <reference types="bun-types" />
2
+
3
+ import { describe, expect, mock, test } from 'bun:test';
4
+ import {
5
+ chmodSync,
6
+ mkdirSync,
7
+ mkdtempSync,
8
+ rmSync,
9
+ writeFileSync,
10
+ } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join } from 'node:path';
13
+ import {
14
+ fetchLatestVersion,
15
+ getOpenCodeVersion,
16
+ isOpenCodeInstalled,
17
+ } from './system';
18
+
19
+ describe('system', () => {
20
+ test('isOpenCodeInstalled detects opencode in ~/.opencode/bin', async () => {
21
+ const dir = mkdtempSync(join(tmpdir(), 'opencode-system-test-'));
22
+ const originalPath = process.env.PATH;
23
+ const originalHome = process.env.HOME;
24
+
25
+ try {
26
+ const opencodePath = join(dir, '.opencode', 'bin', 'opencode');
27
+ mkdirSync(join(dir, '.opencode', 'bin'), { recursive: true });
28
+ writeFileSync(opencodePath, '#!/bin/sh\necho 1.2.3\n');
29
+ chmodSync(opencodePath, 0o755);
30
+ process.env.HOME = dir;
31
+ process.env.PATH = '/usr/bin:/bin:/usr/sbin:/sbin';
32
+
33
+ const system = await import(`./system?test=home-detect-${Date.now()}`);
34
+ expect(await system.isOpenCodeInstalled()).toBe(true);
35
+ } finally {
36
+ process.env.PATH = originalPath;
37
+ process.env.HOME = originalHome;
38
+ rmSync(dir, { recursive: true, force: true });
39
+ }
40
+ });
41
+
42
+ test('isOpenCodeInstalled returns boolean', async () => {
43
+ // We don't necessarily want to depend on the host system
44
+ // but for a basic test we can just check it returns a boolean
45
+ const result = await isOpenCodeInstalled();
46
+ expect(typeof result).toBe('boolean');
47
+ });
48
+
49
+ test('fetchLatestVersion returns version string or null', async () => {
50
+ // Mock global fetch
51
+ const originalFetch = globalThis.fetch;
52
+ globalThis.fetch = mock(async () => {
53
+ return {
54
+ ok: true,
55
+ json: async () => ({ version: '1.2.3' }),
56
+ };
57
+ }) as any;
58
+
59
+ try {
60
+ const version = await fetchLatestVersion('any-package');
61
+ expect(version).toBe('1.2.3');
62
+ } finally {
63
+ globalThis.fetch = originalFetch;
64
+ }
65
+ });
66
+
67
+ test('fetchLatestVersion returns null on error', async () => {
68
+ const originalFetch = globalThis.fetch;
69
+ try {
70
+ globalThis.fetch = mock(async () => {
71
+ return {
72
+ ok: false,
73
+ };
74
+ }) as any;
75
+
76
+ const version = await fetchLatestVersion('any-package');
77
+ expect(version).toBeNull();
78
+ } finally {
79
+ globalThis.fetch = originalFetch;
80
+ }
81
+ });
82
+
83
+ test('getOpenCodeVersion returns string or null', async () => {
84
+ const version = await getOpenCodeVersion();
85
+ if (version !== null) {
86
+ expect(typeof version).toBe('string');
87
+ } else {
88
+ expect(version).toBeNull();
89
+ }
90
+ });
91
+ });
@@ -0,0 +1,180 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { statSync } from 'node:fs';
3
+ import { crossSpawn } from '../utils/compat';
4
+
5
+ let cachedOpenCodePath: string | null = null;
6
+
7
+ function resolvePathCommand(command: string): string | null {
8
+ try {
9
+ const resolver = process.platform === 'win32' ? 'where' : 'which';
10
+ const result = spawnSync(resolver, [command], {
11
+ encoding: 'utf-8',
12
+ stdio: ['ignore', 'pipe', 'ignore'],
13
+ });
14
+
15
+ if (result.status !== 0) {
16
+ return null;
17
+ }
18
+
19
+ const resolved = result.stdout
20
+ .split(/\r?\n/)
21
+ .map((line) => line.trim())
22
+ .find(Boolean);
23
+
24
+ return resolved ?? null;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+
30
+ function canExecute(command: string, args: string[]): boolean {
31
+ try {
32
+ const result = spawnSync(command, args, {
33
+ stdio: 'ignore',
34
+ });
35
+ return result.status === 0;
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ function getOpenCodePaths(): string[] {
42
+ const home = process.env.HOME || process.env.USERPROFILE || '';
43
+
44
+ return [
45
+ // PATH (try this first)
46
+ 'opencode',
47
+ // User local installations (Linux & macOS)
48
+ `${home}/.local/bin/opencode`,
49
+ `${home}/.opencode/bin/opencode`,
50
+ `${home}/bin/opencode`,
51
+ // System-wide installations
52
+ '/usr/local/bin/opencode',
53
+ '/opt/opencode/bin/opencode',
54
+ '/usr/bin/opencode',
55
+ '/bin/opencode',
56
+ // macOS specific
57
+ '/Applications/OpenCode.app/Contents/MacOS/opencode',
58
+ `${home}/Applications/OpenCode.app/Contents/MacOS/opencode`,
59
+ // Homebrew (macOS & Linux)
60
+ '/opt/homebrew/bin/opencode',
61
+ '/home/linuxbrew/.linuxbrew/bin/opencode',
62
+ `${home}/homebrew/bin/opencode`,
63
+ // macOS user Library
64
+ `${home}/Library/Application Support/opencode/bin/opencode`,
65
+ // Snap (Linux)
66
+ '/snap/bin/opencode',
67
+ '/var/snap/opencode/current/bin/opencode',
68
+ // Flatpak (Linux)
69
+ '/var/lib/flatpak/exports/bin/ai.opencode.OpenCode',
70
+ `${home}/.local/share/flatpak/exports/bin/ai.opencode.OpenCode`,
71
+ // Nix (Linux/macOS)
72
+ '/nix/store/opencode/bin/opencode',
73
+ `${home}/.nix-profile/bin/opencode`,
74
+ '/run/current-system/sw/bin/opencode',
75
+ // Cargo (Rust toolchain)
76
+ `${home}/.cargo/bin/opencode`,
77
+ // npm/npx global
78
+ `${home}/.npm-global/bin/opencode`,
79
+ '/usr/local/lib/node_modules/opencode/bin/opencode',
80
+ // Yarn global
81
+ `${home}/.yarn/bin/opencode`,
82
+ // PNPM
83
+ `${home}/.pnpm-global/bin/opencode`,
84
+ ];
85
+ }
86
+
87
+ export function resolveOpenCodePath(): string {
88
+ if (cachedOpenCodePath) {
89
+ return cachedOpenCodePath;
90
+ }
91
+
92
+ const pathOpenCodePath = resolvePathCommand('opencode');
93
+ if (pathOpenCodePath) {
94
+ cachedOpenCodePath = pathOpenCodePath;
95
+ return pathOpenCodePath;
96
+ }
97
+
98
+ const paths = getOpenCodePaths();
99
+
100
+ for (const opencodePath of paths) {
101
+ if (opencodePath === 'opencode') continue;
102
+ try {
103
+ const stat = statSync(opencodePath);
104
+ if (stat.isFile()) {
105
+ cachedOpenCodePath = opencodePath;
106
+ return opencodePath;
107
+ }
108
+ } catch {
109
+ // Try next path
110
+ }
111
+ }
112
+
113
+ // Fallback to 'opencode' and hope it's in PATH
114
+ return 'opencode';
115
+ }
116
+
117
+ export async function isOpenCodeInstalled(): Promise<boolean> {
118
+ const pathOpenCodePath = resolvePathCommand('opencode');
119
+
120
+ if (pathOpenCodePath && canExecute(pathOpenCodePath, ['--version'])) {
121
+ cachedOpenCodePath = pathOpenCodePath;
122
+ return true;
123
+ }
124
+
125
+ const paths = getOpenCodePaths();
126
+
127
+ for (const opencodePath of paths) {
128
+ if (opencodePath === 'opencode') continue;
129
+ try {
130
+ const proc = crossSpawn([opencodePath, '--version'], {
131
+ stdout: 'pipe',
132
+ stderr: 'pipe',
133
+ });
134
+ await proc.exited;
135
+ if (proc.exitCode === 0) {
136
+ cachedOpenCodePath = opencodePath;
137
+ return true;
138
+ }
139
+ } catch {
140
+ // Try next path
141
+ }
142
+ }
143
+ return false;
144
+ }
145
+
146
+ export async function getOpenCodeVersion(): Promise<string | null> {
147
+ const opencodePath = resolveOpenCodePath();
148
+ try {
149
+ const proc = crossSpawn([opencodePath, '--version'], {
150
+ stdout: 'pipe',
151
+ stderr: 'pipe',
152
+ });
153
+ const outputPromise = proc.stdout();
154
+ await proc.exited;
155
+ if (proc.exitCode === 0) {
156
+ return (await outputPromise).trim();
157
+ }
158
+ } catch {
159
+ // Failed
160
+ }
161
+ return null;
162
+ }
163
+
164
+ export function getOpenCodePath(): string | null {
165
+ const path = resolveOpenCodePath();
166
+ return path === 'opencode' ? null : path;
167
+ }
168
+
169
+ export async function fetchLatestVersion(
170
+ packageName: string,
171
+ ): Promise<string | null> {
172
+ try {
173
+ const res = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
174
+ if (!res.ok) return null;
175
+ const data = (await res.json()) as { version: string };
176
+ return data.version;
177
+ } catch {
178
+ return null;
179
+ }
180
+ }
@@ -0,0 +1,43 @@
1
+ export type BooleanArg = 'yes' | 'no';
2
+
3
+ export interface InstallArgs {
4
+ tui: boolean;
5
+ skills?: BooleanArg;
6
+ preset?: string;
7
+ dryRun?: boolean;
8
+ reset?: boolean;
9
+ }
10
+
11
+ export interface OpenCodeConfig {
12
+ plugin?: unknown[];
13
+ provider?: Record<string, unknown>;
14
+ agent?: Record<string, unknown>;
15
+ [key: string]: unknown;
16
+ }
17
+
18
+ export interface InstallConfig {
19
+ installSkills: boolean;
20
+ installCustomSkills: boolean;
21
+ preset?: string;
22
+ promptForStar?: boolean;
23
+ dryRun?: boolean;
24
+ reset: boolean;
25
+ }
26
+
27
+ export interface ConfigMergeResult {
28
+ success: boolean;
29
+ configPath: string;
30
+ error?: string;
31
+ }
32
+
33
+ export interface DetectedConfig {
34
+ isInstalled: boolean;
35
+ hasKimi: boolean;
36
+ hasOpenAI: boolean;
37
+ hasAnthropic?: boolean;
38
+ hasCopilot?: boolean;
39
+ hasZaiPlan?: boolean;
40
+ hasAntigravity: boolean;
41
+ hasChutes?: boolean;
42
+ hasOpencodeZen: boolean;
43
+ }
@@ -0,0 +1,58 @@
1
+ // Agent names
2
+ export const AGENT_ALIASES: Record<string, string> = {
3
+ explore: 'explorer',
4
+ 'frontend-ui-ux-engineer': 'designer',
5
+ };
6
+
7
+ export const SUBAGENT_NAMES = [
8
+ 'explorer',
9
+ 'librarian',
10
+ 'oracle',
11
+ 'designer',
12
+ 'fixer',
13
+ 'steward',
14
+ 'interpreter',
15
+ ] as const;
16
+
17
+ export const ORCHESTRATOR_NAME = 'orchestrator' as const;
18
+
19
+ export const ALL_AGENT_NAMES = [ORCHESTRATOR_NAME, ...SUBAGENT_NAMES] as const;
20
+
21
+ // Agent name type (for use in DEFAULT_MODELS)
22
+ export type AgentName = (typeof ALL_AGENT_NAMES)[number];
23
+
24
+ // Default models for each agent
25
+ // Hybrid NeuralWatt + OpenCode-Go strategy:
26
+ // - Orchestrator on NeuralWatt GLM-5.1 (energy-efficient, strong routing)
27
+ // - Explorer on NeuralWatt Qwen3.5-397B-Fast (cheap MoE, tool-calling, no reasoning overhead)
28
+ // - Oracle, Librarian, Designer, Fixer on OpenCode-Go (proven reliability)
29
+ export const DEFAULT_MODELS: Record<AgentName, string | undefined> = {
30
+ orchestrator: 'neuralwatt/zai-org/GLM-5.1-FP8',
31
+ oracle: 'opencode-go/deepseek-v4-flash',
32
+ librarian: 'opencode-go/deepseek-v4-flash',
33
+ explorer: 'neuralwatt/qwen3.5-397b-fast',
34
+ designer: 'opencode-go/mimo-v2.5-pro',
35
+ fixer: 'opencode-go/deepseek-v4-flash',
36
+ steward: 'opencode-go/deepseek-v4-flash',
37
+ interpreter: 'opencode-go/mimo-v2.5-pro',
38
+ };
39
+
40
+ // Polling configuration
41
+ export const POLL_INTERVAL_MS = 500;
42
+
43
+ // Timeouts
44
+ export const MAX_POLL_TIME_MS = 5 * 60 * 1000; // 5 minutes
45
+
46
+ // Subagent depth limits
47
+ export const DEFAULT_MAX_SUBAGENT_DEPTH = 10;
48
+
49
+ // Workflow reminders
50
+ export const PHASE_REMINDER_TEXT = `!IMPORTANT! Follow <first_gate> order in system prompt; delegate_subagent in the same turn you name the agent. !END!`;
51
+
52
+ // Polling stability
53
+ export const STABLE_POLLS_THRESHOLD = 3;
54
+
55
+ // SDK discovery timeout for local MCP/skill scans (milliseconds).
56
+ // Prevents plugin init from hanging when the SDK is not ready.
57
+ // Adjustable via config override at build/runtime.
58
+ export const SDK_DISCOVERY_TIMEOUT_MS = 10_000; // 10 seconds
@@ -0,0 +1,4 @@
1
+ export * from './constants';
2
+ export { deepMerge, loadAgentPrompt, loadPluginConfig } from './loader';
3
+ export * from './schema';
4
+ export { getAgentOverride } from './utils';