oh-my-opencode 4.8.0 → 4.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -62121,7 +62121,7 @@ var {
62121
62121
  // package.json
62122
62122
  var package_default = {
62123
62123
  name: "oh-my-opencode",
62124
- version: "4.8.0",
62124
+ version: "4.8.1",
62125
62125
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
62126
62126
  main: "./dist/index.js",
62127
62127
  types: "dist/index.d.ts",
@@ -62258,17 +62258,17 @@ var package_default = {
62258
62258
  zod: "^4.4.3"
62259
62259
  },
62260
62260
  optionalDependencies: {
62261
- "oh-my-opencode-darwin-arm64": "4.8.0",
62262
- "oh-my-opencode-darwin-x64": "4.8.0",
62263
- "oh-my-opencode-darwin-x64-baseline": "4.8.0",
62264
- "oh-my-opencode-linux-arm64": "4.8.0",
62265
- "oh-my-opencode-linux-arm64-musl": "4.8.0",
62266
- "oh-my-opencode-linux-x64": "4.8.0",
62267
- "oh-my-opencode-linux-x64-baseline": "4.8.0",
62268
- "oh-my-opencode-linux-x64-musl": "4.8.0",
62269
- "oh-my-opencode-linux-x64-musl-baseline": "4.8.0",
62270
- "oh-my-opencode-windows-x64": "4.8.0",
62271
- "oh-my-opencode-windows-x64-baseline": "4.8.0"
62261
+ "oh-my-opencode-darwin-arm64": "4.8.1",
62262
+ "oh-my-opencode-darwin-x64": "4.8.1",
62263
+ "oh-my-opencode-darwin-x64-baseline": "4.8.1",
62264
+ "oh-my-opencode-linux-arm64": "4.8.1",
62265
+ "oh-my-opencode-linux-arm64-musl": "4.8.1",
62266
+ "oh-my-opencode-linux-x64": "4.8.1",
62267
+ "oh-my-opencode-linux-x64-baseline": "4.8.1",
62268
+ "oh-my-opencode-linux-x64-musl": "4.8.1",
62269
+ "oh-my-opencode-linux-x64-musl-baseline": "4.8.1",
62270
+ "oh-my-opencode-windows-x64": "4.8.1",
62271
+ "oh-my-opencode-windows-x64-baseline": "4.8.1"
62272
62272
  },
62273
62273
  overrides: {
62274
62274
  hono: "^4.12.18",
@@ -63921,19 +63921,10 @@ function ensureCodexMultiAgentV2Config(config) {
63921
63921
  const maxThreadsValue = CODEX_MULTI_AGENT_V2_MAX_CONCURRENT_THREADS_PER_SESSION.toString();
63922
63922
  if (!section) {
63923
63923
  return appendBlock(normalizedConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
63924
- enabled = true
63925
- max_concurrent_threads_per_session = ${maxThreadsValue}
63926
- `);
63927
- }
63928
- const enabledConfig = replaceOrInsertSetting(normalizedConfig, section, "enabled", "true");
63929
- const updatedSection = findTomlSection(enabledConfig, CODEX_MULTI_AGENT_V2_HEADER);
63930
- if (!updatedSection) {
63931
- return appendBlock(enabledConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
63932
- enabled = true
63933
63924
  max_concurrent_threads_per_session = ${maxThreadsValue}
63934
63925
  `);
63935
63926
  }
63936
- return replaceOrInsertSetting(enabledConfig, updatedSection, "max_concurrent_threads_per_session", maxThreadsValue);
63927
+ return replaceOrInsertSetting(normalizedConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
63937
63928
  }
63938
63929
  function removeFeatureFlagSetting(config, featureName) {
63939
63930
  const section = findTomlSection(config, "features");
@@ -86728,6 +86719,42 @@ function createCliPostHog2() {
86728
86719
 
86729
86720
  // src/cli/run/runner.ts
86730
86721
  init_prompt_async_gate();
86722
+
86723
+ // src/cli/run/runnable-agent-resolver.ts
86724
+ init_shared();
86725
+ init_agent_display_names();
86726
+ async function resolveRunnableRunAgent(client3, resolvedAgent, config2 = {}) {
86727
+ try {
86728
+ const agentsRes = await client3.app.agents();
86729
+ const agents = normalizeSDKResponse(agentsRes, [], {
86730
+ preferResponseOnMissingData: true
86731
+ });
86732
+ const exactAgent = agents.find((agent) => agent.name === resolvedAgent)?.name;
86733
+ if (exactAgent)
86734
+ return exactAgent;
86735
+ const resolvedConfigKey = getAgentConfigKey(resolvedAgent);
86736
+ const configuredDisplayName = config2.agents?.[resolvedConfigKey]?.displayName;
86737
+ const configuredAgent = agents.find((agent) => {
86738
+ if (!agent.name || !configuredDisplayName)
86739
+ return false;
86740
+ return agent.name === configuredDisplayName;
86741
+ })?.name;
86742
+ if (configuredAgent)
86743
+ return configuredAgent;
86744
+ return agents.find((agent) => {
86745
+ if (!agent.name)
86746
+ return false;
86747
+ return getAgentConfigKey(agent.name) === resolvedConfigKey;
86748
+ })?.name ?? resolvedAgent;
86749
+ } catch (error51) {
86750
+ if (!(error51 instanceof Error)) {
86751
+ throw error51;
86752
+ }
86753
+ return resolvedAgent;
86754
+ }
86755
+ }
86756
+
86757
+ // src/cli/run/runner.ts
86731
86758
  var EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2000;
86732
86759
  async function waitForEventProcessorShutdown(eventProcessor, timeoutMs = EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS) {
86733
86760
  const completed = await Promise.race([
@@ -86783,6 +86810,7 @@ Interrupted. Shutting down...`));
86783
86810
  sessionId: options.sessionId,
86784
86811
  directory
86785
86812
  });
86813
+ const runnableAgent = await resolveRunnableRunAgent(client3, resolvedAgent, pluginConfig);
86786
86814
  console.log(import_picocolors16.default.dim(`Session: ${sessionID}`));
86787
86815
  if (resolvedModel) {
86788
86816
  console.log(import_picocolors16.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
@@ -86808,7 +86836,7 @@ Interrupted. Shutting down...`));
86808
86836
  input: {
86809
86837
  path: { id: sessionID },
86810
86838
  body: {
86811
- agent: resolvedAgent,
86839
+ agent: runnableAgent,
86812
86840
  ...resolvedModel ? { model: resolvedModel } : {},
86813
86841
  tools: {
86814
86842
  question: false
@@ -1 +1,12 @@
1
+ /**
2
+ * Configure multi_agent_v2 thread limits without forcing the feature on.
3
+ *
4
+ * Whether V2 is active is determined at runtime by the model's server-side
5
+ * catalog entry (`ModelInfo.multi_agent_version`). Forcing `enabled = true`
6
+ * in config breaks models whose API does not support encrypted tool
7
+ * parameters (e.g. gpt-5.5-medium, API-key-only models, third-party
8
+ * providers). The installer therefore only sets the tuning knob
9
+ * (`max_concurrent_threads_per_session`) so that sessions that DO activate
10
+ * V2 benefit from the higher limit.
11
+ */
1
12
  export declare function ensureCodexMultiAgentV2Config(config: string): string;
@@ -0,0 +1,11 @@
1
+ export interface RunAgentListClient {
2
+ readonly app: {
3
+ readonly agents: () => Promise<unknown>;
4
+ };
5
+ }
6
+ export interface RunAgentDisplayNameConfig {
7
+ readonly agents?: Readonly<Record<string, {
8
+ readonly displayName?: string;
9
+ } | undefined>>;
10
+ }
11
+ export declare function resolveRunnableRunAgent(client: RunAgentListClient, resolvedAgent: string, config?: RunAgentDisplayNameConfig): Promise<string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
4
4
  "description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
5
5
  "main": "./dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -137,17 +137,17 @@
137
137
  "zod": "^4.4.3"
138
138
  },
139
139
  "optionalDependencies": {
140
- "oh-my-opencode-darwin-arm64": "4.8.0",
141
- "oh-my-opencode-darwin-x64": "4.8.0",
142
- "oh-my-opencode-darwin-x64-baseline": "4.8.0",
143
- "oh-my-opencode-linux-arm64": "4.8.0",
144
- "oh-my-opencode-linux-arm64-musl": "4.8.0",
145
- "oh-my-opencode-linux-x64": "4.8.0",
146
- "oh-my-opencode-linux-x64-baseline": "4.8.0",
147
- "oh-my-opencode-linux-x64-musl": "4.8.0",
148
- "oh-my-opencode-linux-x64-musl-baseline": "4.8.0",
149
- "oh-my-opencode-windows-x64": "4.8.0",
150
- "oh-my-opencode-windows-x64-baseline": "4.8.0"
140
+ "oh-my-opencode-darwin-arm64": "4.8.1",
141
+ "oh-my-opencode-darwin-x64": "4.8.1",
142
+ "oh-my-opencode-darwin-x64-baseline": "4.8.1",
143
+ "oh-my-opencode-linux-arm64": "4.8.1",
144
+ "oh-my-opencode-linux-arm64-musl": "4.8.1",
145
+ "oh-my-opencode-linux-x64": "4.8.1",
146
+ "oh-my-opencode-linux-x64-baseline": "4.8.1",
147
+ "oh-my-opencode-linux-x64-musl": "4.8.1",
148
+ "oh-my-opencode-linux-x64-musl-baseline": "4.8.1",
149
+ "oh-my-opencode-windows-x64": "4.8.1",
150
+ "oh-my-opencode-windows-x64-baseline": "4.8.1"
151
151
  },
152
152
  "overrides": {
153
153
  "hono": "^4.12.18",
@@ -1,4 +1,4 @@
1
- import { truncateBudget, truncateRule } from "./truncator.js";
1
+ import { isNeverTruncatedRule, truncateBudget, truncateRule } from "./truncator.js";
2
2
  import type { LoadedRule } from "./types.js";
3
3
 
4
4
  export interface FormatOptions {
@@ -35,13 +35,12 @@ function truncateRules(rules: ReadonlyArray<LoadedRule>, options: FormatOptions)
35
35
  const perRuleBudgeted = perRuleNormalized.map((rule) => ({
36
36
  path: rule.path,
37
37
  relativePath: rule.relativePath,
38
- body:
39
- rule.source === "plugin-bundled"
40
- ? truncateRule(rule.body, { maxChars: perRuleResultChars, relativePath: rule.relativePath }).body
41
- : truncateRule(rule.body, {
42
- maxChars: Math.min(options.maxRuleChars, perRuleResultChars),
43
- relativePath: rule.relativePath,
44
- }).body,
38
+ body: isNeverTruncatedRule(rule.relativePath)
39
+ ? rule.body
40
+ : truncateRule(rule.body, {
41
+ maxChars: Math.min(options.maxRuleChars, perRuleResultChars),
42
+ relativePath: rule.relativePath,
43
+ }).body,
45
44
  }));
46
45
  const budgetedRules = truncateBudget({
47
46
  rules: perRuleBudgeted.map((rule) => ({ body: rule.body, relativePath: rule.relativePath })),
@@ -14,6 +14,13 @@ function truncationNotice(relativePath: string): string {
14
14
  return TRUNCATION_NOTICE.replace("{path}", relativePath);
15
15
  }
16
16
 
17
+ export function isNeverTruncatedRule(relativePath: string): boolean {
18
+ const normalized = relativePath.replace(/\\/g, "/");
19
+ const segments = normalized.split("/").filter((segment) => segment.length > 0);
20
+ const filename = segments.at(-1) ?? normalized;
21
+ return filename.toLowerCase() === "hephaestus.md";
22
+ }
23
+
17
24
  function safeSliceEnd(body: string, end: number): number {
18
25
  if (end <= 0) {
19
26
  return 0;
@@ -28,6 +35,10 @@ function safeSliceEnd(body: string, end: number): number {
28
35
  }
29
36
 
30
37
  export function truncateRule(body: string, options: { maxChars: number; relativePath: string }): TruncationResult {
38
+ if (isNeverTruncatedRule(options.relativePath)) {
39
+ return { body, truncated: false, originalLength: body.length };
40
+ }
41
+
31
42
  if (body.length <= options.maxChars) {
32
43
  return { body, truncated: false, originalLength: body.length };
33
44
  }
@@ -46,6 +57,12 @@ export function truncateBudget(input: { rules: ReadonlyArray<BudgetRule>; maxRes
46
57
  let remainingBudget = input.maxResultChars;
47
58
 
48
59
  for (const rule of input.rules) {
60
+ if (isNeverTruncatedRule(rule.relativePath)) {
61
+ results.push({ body: rule.body, truncated: false, relativePath: rule.relativePath });
62
+ remainingBudget -= rule.body.length;
63
+ continue;
64
+ }
65
+
49
66
  if (remainingBudget >= rule.body.length) {
50
67
  results.push({ body: rule.body, truncated: false, relativePath: rule.relativePath });
51
68
  remainingBudget -= rule.body.length;
@@ -145,6 +145,26 @@ describe("rules formatter hook context", () => {
145
145
  expect(block).not.toContain("must read project rules:");
146
146
  });
147
147
 
148
+ it("#given an oversized Hephaestus static rule #when formatting under a tight result budget #then its body is never truncated", () => {
149
+ // given
150
+ const tailMarker = "HEPHAESTUS_TAIL_SENTINEL";
151
+ const rule = loadedRule({
152
+ path: "/repo/bundled-rules/hephaestus.md",
153
+ relativePath: "bundled-rules/hephaestus.md",
154
+ body: `${"H".repeat(500)}\n\n${tailMarker}`,
155
+ });
156
+
157
+ // when
158
+ const block = formatStaticBlock([rule], {
159
+ maxRuleChars: 120,
160
+ maxResultChars: 200,
161
+ });
162
+
163
+ // then
164
+ expect(block).toContain(tailMarker);
165
+ expect(block).not.toContain("[Truncated. Full:");
166
+ });
167
+
148
168
  it("#given multiple oversized rules #when formatting under a tight result budget #then every rule receives a fair truncated share with a read-full guide", () => {
149
169
  // given
150
170
  const rules = [
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Runtime migration: undo the installer-forced `enabled = true` on
3
+ * `[features.multi_agent_v2]`.
4
+ *
5
+ * Whether V2 is active should be determined at runtime by the model's
6
+ * server-side catalog entry (`ModelInfo.multi_agent_version`). Previous
7
+ * installer versions unconditionally set `enabled = true`, which forces
8
+ * V2 for ALL models --- including those whose API does not support
9
+ * encrypted tool parameters (spawn_agent). This guard removes the
10
+ * forced flag so the Codex runtime can make the right decision per model.
11
+ */
12
+ export function disableMultiAgentV2IfForced(config) {
13
+ const section = findMultiAgentV2Section(config);
14
+ if (!section) return config;
15
+
16
+ const enabledPattern = /^(\s*)enabled\s*=\s*true\s*$/m;
17
+ if (!enabledPattern.test(section.text)) return config;
18
+
19
+ const patched = section.text.replace(enabledPattern, "$1enabled = false");
20
+ return config.slice(0, section.start) + patched + config.slice(section.end);
21
+ }
22
+
23
+ function findMultiAgentV2Section(config) {
24
+ const headerLine = "[features.multi_agent_v2]";
25
+ const lines = config.match(/[^\n]*\n?|$/g) ?? [];
26
+ let offset = 0;
27
+ let start = -1;
28
+ for (const line of lines) {
29
+ if (line.length === 0) break;
30
+ const trimmed = line.trim();
31
+ if (start === -1) {
32
+ if (trimmed === headerLine) start = offset;
33
+ } else if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
34
+ return { start, end: offset, text: config.slice(start, offset) };
35
+ }
36
+ offset += line.length;
37
+ }
38
+ if (start === -1) return null;
39
+ return { start, end: config.length, text: config.slice(start) };
40
+ }
@@ -6,6 +6,7 @@ import { pathToFileURL } from "node:url";
6
6
 
7
7
  import { FALLBACK_CATALOG, readModelCatalog } from "./migrate-codex-config/catalog.mjs";
8
8
  import { configPaths } from "./migrate-codex-config/config-paths.mjs";
9
+ import { disableMultiAgentV2IfForced } from "./migrate-codex-config/multi-agent-v2-guard.mjs";
9
10
  import { ensureCodexReasoningConfig as applyReasoningProfile, readRootSettings } from "./migrate-codex-config/root-settings.mjs";
10
11
  import { readState, resolveStatePath, writeState } from "./migrate-codex-config/state.mjs";
11
12
 
@@ -41,12 +42,28 @@ export async function migrateCodexConfig({ env = process.env, cwd = process.cwd(
41
42
  export async function migrateConfigFile(configPath, { catalog = FALLBACK_CATALOG, previousState } = {}) {
42
43
  const before = await readConfig(configPath);
43
44
  const decision = shouldApplyCatalog(before, catalog, previousState);
44
- if (!decision.apply) return { changed: false, written: readRootSettings(before), managed: decision.managed };
45
- const after = ensureCodexReasoningConfig(before, catalog.current);
46
- if (after === before) return { changed: false, written: catalog.current, managed: true };
47
- await mkdir(dirname(configPath), { recursive: true });
48
- await writeFile(configPath, `${after.trimEnd()}\n`);
49
- return { changed: true, written: catalog.current, managed: true };
45
+
46
+ let config = before;
47
+ let reasoningApplied = false;
48
+
49
+ if (decision.apply) {
50
+ config = ensureCodexReasoningConfig(config, catalog.current);
51
+ reasoningApplied = config !== before;
52
+ }
53
+
54
+ const afterMultiAgentGuard = disableMultiAgentV2IfForced(config);
55
+ const multiAgentChanged = afterMultiAgentGuard !== config;
56
+ if (multiAgentChanged) config = afterMultiAgentGuard;
57
+
58
+ const changed = reasoningApplied || multiAgentChanged;
59
+ if (changed) {
60
+ await mkdir(dirname(configPath), { recursive: true });
61
+ await writeFile(configPath, `${config.trimEnd()}\n`);
62
+ }
63
+
64
+ const written = decision.apply ? catalog.current : readRootSettings(config);
65
+ const managed = decision.apply ? true : decision.managed;
66
+ return { changed, written, managed };
50
67
  }
51
68
 
52
69
  function shouldApplyCatalog(config, catalog, previousState) {
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
4
4
  import { dirname, join } from "node:path";
5
5
  import test from "node:test";
6
6
 
7
+ import { disableMultiAgentV2IfForced } from "../scripts/migrate-codex-config/multi-agent-v2-guard.mjs";
7
8
  import { ensureCodexReasoningConfig, migrateCodexConfig } from "../scripts/migrate-codex-config.mjs";
8
9
 
9
10
  test("#given stale root reasoning config #when ensuring config #then replaces stale values without duplicate keys", () => {
@@ -361,6 +362,84 @@ test("#given config already matches current catalog #when catalog version advanc
361
362
  assert.equal(state.files[configPath].catalogVersion, "test.role-only");
362
363
  });
363
364
 
365
+ test("#given installer-forced multi_agent_v2 enabled #when migrating config #then disables it so runtime decides per model", () => {
366
+ const config = [
367
+ 'model = "gpt-5.5"',
368
+ 'model_reasoning_effort = "high"',
369
+ "",
370
+ "[features.multi_agent_v2]",
371
+ "enabled = true",
372
+ "max_concurrent_threads_per_session = 10000",
373
+ "",
374
+ ].join("\n");
375
+
376
+ const result = disableMultiAgentV2IfForced(config);
377
+
378
+ assert.match(result, /enabled = false/);
379
+ assert.doesNotMatch(result, /enabled = true/);
380
+ assert.match(result, /max_concurrent_threads_per_session = 10000/);
381
+ });
382
+
383
+ test("#given no multi_agent_v2 section #when migrating config #then returns config unchanged", () => {
384
+ const config = [
385
+ 'model = "gpt-5.5"',
386
+ 'model_reasoning_effort = "high"',
387
+ "",
388
+ "[features]",
389
+ "plugins = true",
390
+ "",
391
+ ].join("\n");
392
+
393
+ const result = disableMultiAgentV2IfForced(config);
394
+
395
+ assert.equal(result, config);
396
+ });
397
+
398
+ test("#given multi_agent_v2 already disabled #when migrating config #then returns config unchanged", () => {
399
+ const config = [
400
+ 'model = "gpt-5.5"',
401
+ 'model_reasoning_effort = "high"',
402
+ "",
403
+ "[features.multi_agent_v2]",
404
+ "enabled = false",
405
+ "max_concurrent_threads_per_session = 10000",
406
+ "",
407
+ ].join("\n");
408
+
409
+ const result = disableMultiAgentV2IfForced(config);
410
+
411
+ assert.equal(result, config);
412
+ });
413
+
414
+ test("#given global config with forced multi_agent_v2 #when full migration runs #then disables it on disk", async () => {
415
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-multi-agent-v2-guard-"));
416
+ const codexHome = join(root, "codex-home");
417
+ await mkdir(codexHome, { recursive: true });
418
+ const configPath = join(codexHome, "config.toml");
419
+ await writeFile(
420
+ configPath,
421
+ [
422
+ 'model = "gpt-5.5"',
423
+ 'model_reasoning_effort = "high"',
424
+ "",
425
+ "[features.multi_agent_v2]",
426
+ "enabled = true",
427
+ "max_concurrent_threads_per_session = 10000",
428
+ "",
429
+ ].join("\n"),
430
+ );
431
+
432
+ const result = await migrateCodexConfig({
433
+ env: { CODEX_HOME: codexHome, LAZYCODEX_MODEL_CATALOG_STATE_PATH: join(root, "model-state.json") },
434
+ cwd: root,
435
+ });
436
+
437
+ assert.deepEqual(result.changed, [configPath]);
438
+ const content = await readFile(configPath, "utf8");
439
+ assert.match(content, /enabled = false/);
440
+ assert.doesNotMatch(content, /enabled = true/);
441
+ });
442
+
364
443
  async function canCreateSymlink(type) {
365
444
  const root = await mkdtemp(join(tmpdir(), "lazycodex-symlink-capability-"));
366
445
  const target = join(root, "target");
@@ -253,3 +253,5 @@ function parseJsonString(value) {
253
253
  return null;
254
254
  }
255
255
  }
256
+
257
+
@@ -3,6 +3,16 @@ import { appendBlock, findTomlSection, removeSetting, replaceOrInsertSetting } f
3
3
  const CODEX_MULTI_AGENT_V2_HEADER = "features.multi_agent_v2";
4
4
  const CODEX_MULTI_AGENT_V2_MAX_CONCURRENT_THREADS_PER_SESSION = 10000;
5
5
 
6
+ /**
7
+ * Configure multi_agent_v2 thread limits without forcing the feature on.
8
+ *
9
+ * Whether V2 is active is determined at runtime by the model's server-side
10
+ * catalog entry (ModelInfo.multi_agent_version). Forcing enabled = true
11
+ * in config breaks models whose API does not support encrypted tool
12
+ * parameters. The installer therefore only sets the tuning knob
13
+ * (max_concurrent_threads_per_session) so that sessions that DO activate
14
+ * V2 benefit from the higher limit.
15
+ */
6
16
  export function ensureCodexMultiAgentV2Config(config) {
7
17
  const normalizedConfig = removeLegacyAgentsMaxThreadsSetting(removeFeatureFlagSetting(config, "multi_agent_v2"));
8
18
  const section = findTomlSection(normalizedConfig, CODEX_MULTI_AGENT_V2_HEADER);
@@ -10,19 +20,11 @@ export function ensureCodexMultiAgentV2Config(config) {
10
20
  if (!section) {
11
21
  return appendBlock(
12
22
  normalizedConfig,
13
- `[${CODEX_MULTI_AGENT_V2_HEADER}]\nenabled = true\nmax_concurrent_threads_per_session = ${maxThreadsValue}\n`,
23
+ `[${CODEX_MULTI_AGENT_V2_HEADER}]\nmax_concurrent_threads_per_session = ${maxThreadsValue}\n`,
14
24
  );
15
25
  }
16
26
 
17
- const enabledConfig = replaceOrInsertSetting(normalizedConfig, section, "enabled", "true");
18
- const updatedSection = findTomlSection(enabledConfig, CODEX_MULTI_AGENT_V2_HEADER);
19
- if (!updatedSection) {
20
- return appendBlock(
21
- enabledConfig,
22
- `[${CODEX_MULTI_AGENT_V2_HEADER}]\nenabled = true\nmax_concurrent_threads_per_session = ${maxThreadsValue}\n`,
23
- );
24
- }
25
- return replaceOrInsertSetting(enabledConfig, updatedSection, "max_concurrent_threads_per_session", maxThreadsValue);
27
+ return replaceOrInsertSetting(normalizedConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
26
28
  }
27
29
 
28
30
  function removeFeatureFlagSetting(config, featureName) {