oh-my-opencode 3.8.5 → 3.9.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 (51) hide show
  1. package/bin/oh-my-opencode.js +96 -34
  2. package/bin/platform.d.ts +14 -0
  3. package/bin/platform.js +44 -0
  4. package/bin/platform.test.ts +56 -1
  5. package/dist/agents/atlas/agent.d.ts +1 -1
  6. package/dist/agents/env-context.d.ts +1 -1
  7. package/dist/agents/hephaestus.d.ts +1 -1
  8. package/dist/agents/sisyphus.d.ts +1 -1
  9. package/dist/cli/config-manager/antigravity-provider-configuration.d.ts +3 -3
  10. package/dist/cli/index.js +199 -59
  11. package/dist/cli/run/event-state.d.ts +2 -0
  12. package/dist/cli/run/poll-for-completion.d.ts +2 -0
  13. package/dist/config/schema/agent-overrides.d.ts +1 -0
  14. package/dist/config/schema/categories.d.ts +2 -0
  15. package/dist/config/schema/oh-my-opencode-config.d.ts +3 -12
  16. package/dist/features/background-agent/manager.d.ts +9 -0
  17. package/dist/features/boulder-state/storage.d.ts +1 -1
  18. package/dist/features/boulder-state/types.d.ts +2 -0
  19. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  20. package/dist/hooks/anthropic-context-window-limit-recovery/types.d.ts +1 -0
  21. package/dist/hooks/atlas/boulder-continuation-injector.d.ts +1 -0
  22. package/dist/hooks/atlas/types.d.ts +1 -0
  23. package/dist/hooks/background-notification/hook.d.ts +11 -0
  24. package/dist/hooks/no-hephaestus-non-gpt/hook.d.ts +5 -1
  25. package/dist/hooks/ralph-loop/completion-promise-detector.d.ts +1 -0
  26. package/dist/hooks/ralph-loop/loop-state-controller.d.ts +2 -0
  27. package/dist/hooks/ralph-loop/ralph-loop-hook.d.ts +1 -0
  28. package/dist/hooks/ralph-loop/types.d.ts +1 -0
  29. package/dist/hooks/session-notification.d.ts +1 -0
  30. package/dist/hooks/start-work/index.d.ts +3 -0
  31. package/dist/hooks/start-work/parse-user-request.d.ts +5 -0
  32. package/dist/hooks/start-work/worktree-detector.d.ts +1 -0
  33. package/dist/hooks/stop-continuation-guard/hook.d.ts +6 -1
  34. package/dist/hooks/think-mode/hook.d.ts +14 -2
  35. package/dist/hooks/think-mode/switcher.d.ts +0 -56
  36. package/dist/hooks/think-mode/types.d.ts +1 -15
  37. package/dist/hooks/todo-continuation-enforcer/constants.d.ts +1 -1
  38. package/dist/hooks/todo-continuation-enforcer/pending-question-detection.d.ts +14 -0
  39. package/dist/index.js +1310 -503
  40. package/dist/oh-my-opencode.schema.json +9 -13
  41. package/dist/shared/model-suggestion-retry.d.ts +4 -2
  42. package/dist/shared/prompt-timeout-context.d.ts +12 -0
  43. package/dist/shared/spawn-with-windows-hide.d.ts +15 -0
  44. package/dist/tools/delegate-task/category-resolver.d.ts +1 -0
  45. package/dist/tools/delegate-task/skill-resolver.d.ts +1 -0
  46. package/dist/tools/delegate-task/token-limiter.d.ts +4 -0
  47. package/dist/tools/delegate-task/types.d.ts +9 -0
  48. package/dist/tools/hashline-edit/tool-description.d.ts +1 -1
  49. package/dist/tools/hashline-edit/validation.d.ts +1 -0
  50. package/package.json +13 -8
  51. package/postinstall.mjs +23 -7
@@ -3,8 +3,9 @@
3
3
  // Wrapper script that detects platform and spawns the correct binary
4
4
 
5
5
  import { spawnSync } from "node:child_process";
6
+ import { readFileSync } from "node:fs";
6
7
  import { createRequire } from "node:module";
7
- import { getPlatformPackage, getBinaryPath } from "./platform.js";
8
+ import { getPlatformPackageCandidates, getBinaryPath } from "./platform.js";
8
9
 
9
10
  const require = createRequire(import.meta.url);
10
11
 
@@ -26,55 +27,116 @@ function getLibcFamily() {
26
27
  }
27
28
  }
28
29
 
30
+ function supportsAvx2() {
31
+ if (process.arch !== "x64") {
32
+ return null;
33
+ }
34
+
35
+ if (process.env.OH_MY_OPENCODE_FORCE_BASELINE === "1") {
36
+ return false;
37
+ }
38
+
39
+ if (process.platform === "linux") {
40
+ try {
41
+ const cpuInfo = readFileSync("/proc/cpuinfo", "utf8").toLowerCase();
42
+ return cpuInfo.includes("avx2");
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+
48
+ if (process.platform === "darwin") {
49
+ const probe = spawnSync("sysctl", ["-n", "machdep.cpu.leaf7_features"], {
50
+ encoding: "utf8",
51
+ });
52
+
53
+ if (probe.error || probe.status !== 0) {
54
+ return null;
55
+ }
56
+
57
+ return probe.stdout.toUpperCase().includes("AVX2");
58
+ }
59
+
60
+ return null;
61
+ }
62
+
63
+ function getSignalExitCode(signal) {
64
+ const signalCodeByName = {
65
+ SIGINT: 2,
66
+ SIGILL: 4,
67
+ SIGKILL: 9,
68
+ SIGTERM: 15,
69
+ };
70
+
71
+ return 128 + (signalCodeByName[signal] ?? 1);
72
+ }
73
+
29
74
  function main() {
30
75
  const { platform, arch } = process;
31
76
  const libcFamily = getLibcFamily();
77
+ const avx2Supported = supportsAvx2();
32
78
 
33
- // Get platform package name
34
- let pkg;
79
+ let packageCandidates;
35
80
  try {
36
- pkg = getPlatformPackage({ platform, arch, libcFamily });
81
+ packageCandidates = getPlatformPackageCandidates({
82
+ platform,
83
+ arch,
84
+ libcFamily,
85
+ preferBaseline: avx2Supported === false,
86
+ });
37
87
  } catch (error) {
38
88
  console.error(`\noh-my-opencode: ${error.message}\n`);
39
89
  process.exit(1);
40
90
  }
41
-
42
- // Resolve binary path
43
- const binRelPath = getBinaryPath(pkg, platform);
44
-
45
- let binPath;
46
- try {
47
- binPath = require.resolve(binRelPath);
48
- } catch {
91
+
92
+ const resolvedBinaries = packageCandidates
93
+ .map((pkg) => {
94
+ try {
95
+ return { pkg, binPath: require.resolve(getBinaryPath(pkg, platform)) };
96
+ } catch {
97
+ return null;
98
+ }
99
+ })
100
+ .filter((entry) => entry !== null);
101
+
102
+ if (resolvedBinaries.length === 0) {
49
103
  console.error(`\noh-my-opencode: Platform binary not installed.`);
50
104
  console.error(`\nYour platform: ${platform}-${arch}${libcFamily === "musl" ? "-musl" : ""}`);
51
- console.error(`Expected package: ${pkg}`);
105
+ console.error(`Expected packages (in order): ${packageCandidates.join(", ")}`);
52
106
  console.error(`\nTo fix, run:`);
53
- console.error(` npm install ${pkg}\n`);
107
+ console.error(` npm install ${packageCandidates[0]}\n`);
54
108
  process.exit(1);
55
109
  }
56
-
57
- // Spawn the binary
58
- const result = spawnSync(binPath, process.argv.slice(2), {
59
- stdio: "inherit",
60
- });
61
-
62
- // Handle spawn errors
63
- if (result.error) {
64
- console.error(`\noh-my-opencode: Failed to execute binary.`);
65
- console.error(`Error: ${result.error.message}\n`);
66
- process.exit(2);
67
- }
68
-
69
- // Handle signals
70
- if (result.signal) {
71
- const signalNum = result.signal === "SIGTERM" ? 15 :
72
- result.signal === "SIGKILL" ? 9 :
73
- result.signal === "SIGINT" ? 2 : 1;
74
- process.exit(128 + signalNum);
110
+
111
+ for (let index = 0; index < resolvedBinaries.length; index += 1) {
112
+ const currentBinary = resolvedBinaries[index];
113
+ const hasFallback = index < resolvedBinaries.length - 1;
114
+ const result = spawnSync(currentBinary.binPath, process.argv.slice(2), {
115
+ stdio: "inherit",
116
+ });
117
+
118
+ if (result.error) {
119
+ if (hasFallback) {
120
+ continue;
121
+ }
122
+
123
+ console.error(`\noh-my-opencode: Failed to execute binary.`);
124
+ console.error(`Error: ${result.error.message}\n`);
125
+ process.exit(2);
126
+ }
127
+
128
+ if (result.signal === "SIGILL" && hasFallback) {
129
+ continue;
130
+ }
131
+
132
+ if (result.signal) {
133
+ process.exit(getSignalExitCode(result.signal));
134
+ }
135
+
136
+ process.exit(result.status ?? 1);
75
137
  }
76
138
 
77
- process.exit(result.status ?? 1);
139
+ process.exit(1);
78
140
  }
79
141
 
80
142
  main();
@@ -0,0 +1,14 @@
1
+ export declare function getPlatformPackage(options: {
2
+ platform: string;
3
+ arch: string;
4
+ libcFamily?: string | null;
5
+ }): string;
6
+
7
+ export declare function getPlatformPackageCandidates(options: {
8
+ platform: string;
9
+ arch: string;
10
+ libcFamily?: string | null;
11
+ preferBaseline?: boolean;
12
+ }): string[];
13
+
14
+ export declare function getBinaryPath(pkg: string, platform: string): string;
package/bin/platform.js CHANGED
@@ -26,6 +26,50 @@ export function getPlatformPackage({ platform, arch, libcFamily }) {
26
26
  return `oh-my-opencode-${os}-${arch}${suffix}`;
27
27
  }
28
28
 
29
+ /** @param {{ platform: string, arch: string, libcFamily?: string | null, preferBaseline?: boolean }} options */
30
+ export function getPlatformPackageCandidates({ platform, arch, libcFamily, preferBaseline = false }) {
31
+ const primaryPackage = getPlatformPackage({ platform, arch, libcFamily });
32
+ const baselinePackage = getBaselinePlatformPackage({ platform, arch, libcFamily });
33
+
34
+ if (!baselinePackage) {
35
+ return [primaryPackage];
36
+ }
37
+
38
+ return preferBaseline ? [baselinePackage, primaryPackage] : [primaryPackage, baselinePackage];
39
+ }
40
+
41
+ /** @param {{ platform: string, arch: string, libcFamily?: string | null }} options */
42
+ function getBaselinePlatformPackage({ platform, arch, libcFamily }) {
43
+ if (arch !== "x64") {
44
+ return null;
45
+ }
46
+
47
+ if (platform === "darwin") {
48
+ return "oh-my-opencode-darwin-x64-baseline";
49
+ }
50
+
51
+ if (platform === "win32") {
52
+ return "oh-my-opencode-windows-x64-baseline";
53
+ }
54
+
55
+ if (platform === "linux") {
56
+ if (libcFamily === null || libcFamily === undefined) {
57
+ throw new Error(
58
+ "Could not detect libc on Linux. " +
59
+ "Please ensure detect-libc is installed or report this issue."
60
+ );
61
+ }
62
+
63
+ if (libcFamily === "musl") {
64
+ return "oh-my-opencode-linux-x64-musl-baseline";
65
+ }
66
+
67
+ return "oh-my-opencode-linux-x64-baseline";
68
+ }
69
+
70
+ return null;
71
+ }
72
+
29
73
  /**
30
74
  * Get the path to the binary within a platform package
31
75
  * @param {string} pkg Package name
@@ -1,6 +1,6 @@
1
1
  // bin/platform.test.ts
2
2
  import { describe, expect, test } from "bun:test";
3
- import { getPlatformPackage, getBinaryPath } from "./platform.js";
3
+ import { getBinaryPath, getPlatformPackage, getPlatformPackageCandidates } from "./platform.js";
4
4
 
5
5
  describe("getPlatformPackage", () => {
6
6
  // #region Darwin platforms
@@ -146,3 +146,58 @@ describe("getBinaryPath", () => {
146
146
  expect(result).toBe("oh-my-opencode-linux-x64/bin/oh-my-opencode");
147
147
  });
148
148
  });
149
+
150
+ describe("getPlatformPackageCandidates", () => {
151
+ test("returns x64 and baseline candidates for Linux glibc", () => {
152
+ // #given Linux x64 with glibc
153
+ const input = { platform: "linux", arch: "x64", libcFamily: "glibc" };
154
+
155
+ // #when getting package candidates
156
+ const result = getPlatformPackageCandidates(input);
157
+
158
+ // #then returns modern first then baseline fallback
159
+ expect(result).toEqual([
160
+ "oh-my-opencode-linux-x64",
161
+ "oh-my-opencode-linux-x64-baseline",
162
+ ]);
163
+ });
164
+
165
+ test("returns x64 musl and baseline candidates for Linux musl", () => {
166
+ // #given Linux x64 with musl
167
+ const input = { platform: "linux", arch: "x64", libcFamily: "musl" };
168
+
169
+ // #when getting package candidates
170
+ const result = getPlatformPackageCandidates(input);
171
+
172
+ // #then returns musl modern first then musl baseline fallback
173
+ expect(result).toEqual([
174
+ "oh-my-opencode-linux-x64-musl",
175
+ "oh-my-opencode-linux-x64-musl-baseline",
176
+ ]);
177
+ });
178
+
179
+ test("returns baseline first when preferBaseline is true", () => {
180
+ // #given Windows x64 and baseline preference
181
+ const input = { platform: "win32", arch: "x64", preferBaseline: true };
182
+
183
+ // #when getting package candidates
184
+ const result = getPlatformPackageCandidates(input);
185
+
186
+ // #then baseline package is preferred first
187
+ expect(result).toEqual([
188
+ "oh-my-opencode-windows-x64-baseline",
189
+ "oh-my-opencode-windows-x64",
190
+ ]);
191
+ });
192
+
193
+ test("returns only one candidate for ARM64", () => {
194
+ // #given non-x64 platform
195
+ const input = { platform: "linux", arch: "arm64", libcFamily: "glibc" };
196
+
197
+ // #when getting package candidates
198
+ const result = getPlatformPackageCandidates(input);
199
+
200
+ // #then baseline fallback is not included
201
+ expect(result).toEqual(["oh-my-opencode-linux-arm64"]);
202
+ });
203
+ });
@@ -30,6 +30,6 @@ export interface OrchestratorContext {
30
30
  export declare function getAtlasPrompt(model?: string): string;
31
31
  export declare function createAtlasAgent(ctx: OrchestratorContext): AgentConfig;
32
32
  export declare namespace createAtlasAgent {
33
- var mode: "primary";
33
+ var mode: "all";
34
34
  }
35
35
  export declare const atlasPromptMetadata: AgentPromptMetadata;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Creates OmO-specific environment context (time, timezone, locale).
2
+ * Creates OmO-specific environment context (timezone, locale).
3
3
  * Note: Working directory, platform, and date are already provided by OpenCode's system.ts,
4
4
  * so we only include fields that OpenCode doesn't provide to avoid duplication.
5
5
  * See: https://github.com/code-yeongyu/oh-my-opencode/issues/379
@@ -2,5 +2,5 @@ import type { AgentConfig } from "@opencode-ai/sdk";
2
2
  import type { AvailableAgent, AvailableSkill, AvailableCategory } from "./dynamic-agent-prompt-builder";
3
3
  export declare function createHephaestusAgent(model: string, availableAgents?: AvailableAgent[], availableToolNames?: string[], availableSkills?: AvailableSkill[], availableCategories?: AvailableCategory[], useTaskSystem?: boolean): AgentConfig;
4
4
  export declare namespace createHephaestusAgent {
5
- var mode: "primary";
5
+ var mode: "all";
6
6
  }
@@ -4,5 +4,5 @@ export declare const SISYPHUS_PROMPT_METADATA: AgentPromptMetadata;
4
4
  import type { AvailableAgent, AvailableSkill, AvailableCategory } from "./dynamic-agent-prompt-builder";
5
5
  export declare function createSisyphusAgent(model: string, availableAgents?: AvailableAgent[], availableToolNames?: string[], availableSkills?: AvailableSkill[], availableCategories?: AvailableCategory[], useTaskSystem?: boolean): AgentConfig;
6
6
  export declare namespace createSisyphusAgent {
7
- var mode: "primary";
7
+ var mode: "all";
8
8
  }
@@ -4,10 +4,10 @@
4
4
  * IMPORTANT: Model names MUST use `antigravity-` prefix for stability.
5
5
  *
6
6
  * Since opencode-antigravity-auth v1.3.0, models use a variant system:
7
- * - `antigravity-gemini-3-pro` with variants: low, high
7
+ * - `antigravity-gemini-3.1-pro` with variants: low, high
8
8
  * - `antigravity-gemini-3-flash` with variants: minimal, low, medium, high
9
9
  *
10
- * Legacy tier-suffixed names (e.g., `antigravity-gemini-3-pro-high`) still work
10
+ * Legacy tier-suffixed names (e.g., `antigravity-gemini-3.1-pro-high`) still work
11
11
  * but variants are the recommended approach.
12
12
  *
13
13
  * @see https://github.com/NoeFabris/opencode-antigravity-auth#models
@@ -16,7 +16,7 @@ export declare const ANTIGRAVITY_PROVIDER_CONFIG: {
16
16
  google: {
17
17
  name: string;
18
18
  models: {
19
- "antigravity-gemini-3-pro": {
19
+ "antigravity-gemini-3.1-pro": {
20
20
  name: string;
21
21
  limit: {
22
22
  context: number;