oh-my-codex 0.16.3 → 0.16.4
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/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/README.md +3 -3
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/cli/__tests__/cleanup.test.js +27 -0
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +101 -6
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +131 -2
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +47 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +2 -2
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +272 -26
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +85 -3
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +1 -1
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +108 -0
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +69 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +54 -8
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +8 -4
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/codex-feature-probe.d.ts +9 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -0
- package/dist/cli/codex-feature-probe.js +28 -0
- package/dist/cli/codex-feature-probe.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +152 -17
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +135 -17
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +8 -8
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +3 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +88 -0
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +21 -0
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +4 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +7 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -3
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +114 -44
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +1 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +64 -5
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/uninstall.d.ts +2 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +12 -3
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
- package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
- package/dist/config/__tests__/codex-feature-flags.test.js +35 -0
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.js +7 -0
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +70 -9
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +116 -11
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
- package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
- package/dist/config/codex-feature-flags.d.ts +21 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -0
- package/dist/config/codex-feature-flags.js +56 -0
- package/dist/config/codex-feature-flags.js.map +1 -0
- package/dist/config/codex-hooks.d.ts +2 -0
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +25 -3
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/generator.d.ts +11 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +221 -123
- package/dist/config/generator.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +3 -1
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
- package/dist/config/omx-first-party-mcp.js +2 -2
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +92 -2
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +125 -1
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
- package/dist/hooks/agents-overlay.js +2 -2
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +7 -5
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +164 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +4 -5
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +61 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +166 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +23 -2
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +22 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +57 -26
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +5 -0
- package/dist/modes/base.js.map +1 -1
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +316 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +481 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/artifacts.test.js +533 -4
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/__tests__/context-pack-status.test.js +524 -0
- package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
- package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
- package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
- package/dist/planning/__tests__/markdown-structure.test.js +459 -0
- package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +523 -1
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -1
- package/dist/planning/artifacts.d.ts +1 -1
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +227 -28
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/planning/context-pack-status.d.ts +25 -0
- package/dist/planning/context-pack-status.d.ts.map +1 -1
- package/dist/planning/context-pack-status.js +272 -31
- package/dist/planning/context-pack-status.js.map +1 -1
- package/dist/planning/markdown-structure.d.ts +20 -0
- package/dist/planning/markdown-structure.d.ts.map +1 -0
- package/dist/planning/markdown-structure.js +137 -0
- package/dist/planning/markdown-structure.js.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.js +121 -0
- package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
- package/dist/ralph/completion-audit.d.ts +8 -0
- package/dist/ralph/completion-audit.d.ts.map +1 -0
- package/dist/ralph/completion-audit.js +99 -0
- package/dist/ralph/completion-audit.js.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +220 -13
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js +126 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +133 -54
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +4 -2
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-dispatcher.js +30 -1
- package/dist/scripts/notify-dispatcher.js.map +1 -1
- package/dist/scripts/notify-hook.js +3 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +102 -27
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +9 -3
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +7 -0
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +25 -8
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +1 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +22 -15
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.js +3 -3
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.js +39 -0
- package/dist/team/__tests__/approved-execution.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +5 -0
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +497 -2
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +1 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +8 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/approved-execution.d.ts.map +1 -1
- package/dist/team/approved-execution.js +3 -0
- package/dist/team/approved-execution.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +43 -0
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +4 -0
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +2 -6
- package/dist/team/state.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +124 -1
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts +44 -2
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +197 -13
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/wiki/lifecycle.js +1 -1
- package/dist/wiki/lifecycle.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/.mcp.json +5 -5
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +21 -24
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
- package/skills/analyze/SKILL.md +0 -2
- package/skills/ask-claude/SKILL.md +5 -3
- package/skills/ask-gemini/SKILL.md +5 -3
- package/skills/autopilot/SKILL.md +2 -2
- package/skills/code-review/SKILL.md +1 -3
- package/skills/deep-interview/SKILL.md +5 -7
- package/skills/doctor/SKILL.md +2 -2
- package/skills/ecomode/SKILL.md +105 -1
- package/skills/frontend-ui-ux/SKILL.md +4 -26
- package/skills/git-master/SKILL.md +2 -4
- package/skills/omx-setup/SKILL.md +3 -3
- package/skills/pipeline/SKILL.md +3 -3
- package/skills/plan/SKILL.md +3 -6
- package/skills/ralph/SKILL.md +9 -10
- package/skills/swarm/SKILL.md +5 -3
- package/skills/tdd/SKILL.md +95 -1
- package/skills/ultragoal/SKILL.md +36 -3
- package/skills/ultraqa/SKILL.md +21 -24
- package/skills/ultrawork/SKILL.md +8 -8
- package/skills/web-clone/SKILL.md +348 -1
- package/skills/wiki/SKILL.md +13 -13
- package/src/scripts/__tests__/codex-native-hook.test.ts +231 -13
- package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
- package/src/scripts/codex-native-hook.ts +160 -43
- package/src/scripts/codex-native-pre-post.ts +4 -1
- package/src/scripts/notify-dispatcher.ts +40 -1
- package/src/scripts/notify-hook.ts +3 -1
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
* 3. [table] sections (shell_environment_policy.set, mcp_servers, tui)
|
|
11
11
|
*/
|
|
12
12
|
import type { UnifiedMcpRegistryServer } from "./mcp-registry.js";
|
|
13
|
+
import { type CodexHookFeatureFlag } from "./codex-feature-flags.js";
|
|
13
14
|
import type { HudPreset } from "../hud/types.js";
|
|
14
15
|
interface MergeOptions {
|
|
15
16
|
includeTui?: boolean;
|
|
16
17
|
codexHooksFile?: string;
|
|
18
|
+
codexHookFeatureFlag?: CodexHookFeatureFlag;
|
|
17
19
|
modelOverride?: string;
|
|
18
20
|
sharedMcpServers?: UnifiedMcpRegistryServer[];
|
|
19
21
|
sharedMcpRegistrySource?: string;
|
|
@@ -21,6 +23,7 @@ interface MergeOptions {
|
|
|
21
23
|
statusLinePreset?: HudPreset;
|
|
22
24
|
forceStatusLinePreset?: boolean;
|
|
23
25
|
notifyCommand?: string[] | false;
|
|
26
|
+
includeFirstPartyMcp?: boolean;
|
|
24
27
|
}
|
|
25
28
|
export interface ModelContextRecommendation {
|
|
26
29
|
model: string;
|
|
@@ -43,6 +46,7 @@ export declare function getRootModelName(config: string): string | undefined;
|
|
|
43
46
|
export declare function formatTomlStringArray(values: readonly string[]): string;
|
|
44
47
|
export declare function getRootTomlArray(config: string, key: string): string[] | null;
|
|
45
48
|
export declare function isOmxManagedNotifyCommand(command: readonly string[] | null | undefined, pkgRoot?: string): boolean;
|
|
49
|
+
export declare function sanitizePreviousNotifyCommand(command: readonly string[] | null | undefined, pkgRoot?: string): string[] | null;
|
|
46
50
|
export declare function stripOmxSeededBehavioralDefaults(config: string): string;
|
|
47
51
|
/**
|
|
48
52
|
* Remove any existing OMX-owned top-level keys so we can re-insert them
|
|
@@ -51,7 +55,7 @@ export declare function stripOmxSeededBehavioralDefaults(config: string): string
|
|
|
51
55
|
export declare function stripOmxTopLevelKeys(config: string): string;
|
|
52
56
|
export declare function stripManagedCodexHookTrustState(config: string): string;
|
|
53
57
|
export declare function upsertManagedCodexHookTrustState(config: string, pkgRoot: string, codexHooksFile: string | undefined): string;
|
|
54
|
-
export declare function upsertPluginModeRuntimeFeatureFlags(config: string): string;
|
|
58
|
+
export declare function upsertPluginModeRuntimeFeatureFlags(config: string, codexHookFeatureFlag?: CodexHookFeatureFlag): string;
|
|
55
59
|
/**
|
|
56
60
|
* Remove OMX-owned feature flags from the [features] section.
|
|
57
61
|
* If the section becomes empty after removal, remove the section header too.
|
|
@@ -61,7 +65,7 @@ export declare function stripOmxFeatureFlags(config: string): string;
|
|
|
61
65
|
* Preserve native Codex hook enablement without re-adding other OMX feature
|
|
62
66
|
* flags. Used by uninstall when user-owned hooks remain in hooks.json.
|
|
63
67
|
*/
|
|
64
|
-
export declare function upsertCodexHooksFeatureFlag(config: string): string;
|
|
68
|
+
export declare function upsertCodexHooksFeatureFlag(config: string, codexHookFeatureFlag?: CodexHookFeatureFlag): string;
|
|
65
69
|
export declare function stripOmxEnvSettings(config: string): string;
|
|
66
70
|
export declare function stripExistingOmxBlocks(config: string): {
|
|
67
71
|
cleaned: string;
|
|
@@ -71,6 +75,11 @@ export declare function stripExistingSharedMcpRegistryBlock(config: string): {
|
|
|
71
75
|
cleaned: string;
|
|
72
76
|
removed: number;
|
|
73
77
|
};
|
|
78
|
+
export declare function extractSharedMcpRegistryServersFromConfig(config: string): {
|
|
79
|
+
servers: UnifiedMcpRegistryServer[];
|
|
80
|
+
sourcePath?: string;
|
|
81
|
+
};
|
|
82
|
+
export declare function mergeSharedMcpRegistryBlock(config: string, servers: UnifiedMcpRegistryServer[], sourcePath?: string): string;
|
|
74
83
|
/**
|
|
75
84
|
* Merge OMX config into existing config.toml
|
|
76
85
|
* Preserves existing user settings, appends OMX block if not present.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/config/generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/config/generator.ts"],"names":[],"mappings":"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"}
|
package/dist/config/generator.js
CHANGED
|
@@ -11,15 +11,19 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { readFile, writeFile } from "fs/promises";
|
|
13
13
|
import { existsSync } from "fs";
|
|
14
|
-
import {
|
|
14
|
+
import { join, resolve } from "path";
|
|
15
15
|
import TOML from "@iarna/toml";
|
|
16
16
|
import { AGENT_DEFINITIONS } from "../agents/definitions.js";
|
|
17
17
|
import { DEFAULT_FRONTIER_MODEL } from "./models.js";
|
|
18
|
-
import {
|
|
18
|
+
import { DEFAULT_CODEX_HOOK_FEATURE_FLAG, CODEX_HOOK_FEATURE_FLAGS, formatCodexHookFeatureFlagLine, normalizeCodexHookFeatureFlag, } from "./codex-feature-flags.js";
|
|
19
|
+
import { OMX_FIRST_PARTY_MCP_SERVER_NAMES, getOmxFirstPartySetupMcpServers, } from "./omx-first-party-mcp.js";
|
|
19
20
|
import { buildManagedCodexHookTrustToml } from "./codex-hooks.js";
|
|
20
21
|
function escapeTomlString(value) {
|
|
21
22
|
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
22
23
|
}
|
|
24
|
+
function isRecord(value) {
|
|
25
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26
|
+
}
|
|
23
27
|
// ---------------------------------------------------------------------------
|
|
24
28
|
// Top-level OMX keys (must live before any [table] header)
|
|
25
29
|
// ---------------------------------------------------------------------------
|
|
@@ -206,23 +210,37 @@ export function getRootTomlArray(config, key) {
|
|
|
206
210
|
return null;
|
|
207
211
|
}
|
|
208
212
|
}
|
|
213
|
+
function resolveNotifyEntrypoint(command) {
|
|
214
|
+
if (!/(?:^|[\\/])node(?:\.exe)?$/i.test(command[0] ?? "")) {
|
|
215
|
+
return command[0];
|
|
216
|
+
}
|
|
217
|
+
return command.slice(1).find((arg) => !arg.startsWith("-"));
|
|
218
|
+
}
|
|
209
219
|
export function isOmxManagedNotifyCommand(command, pkgRoot) {
|
|
210
220
|
if (!command)
|
|
211
221
|
return false;
|
|
222
|
+
const entrypoint = resolveNotifyEntrypoint(command);
|
|
223
|
+
if (!entrypoint)
|
|
224
|
+
return false;
|
|
225
|
+
if (!/(?:^|[\\/])notify-(?:hook|dispatcher)\.js$/.test(entrypoint)) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
212
228
|
const managedScripts = pkgRoot
|
|
213
229
|
? new Set([
|
|
214
230
|
resolve(pkgRoot, "dist", "scripts", "notify-hook.js"),
|
|
215
231
|
resolve(pkgRoot, "dist", "scripts", "notify-dispatcher.js"),
|
|
216
232
|
])
|
|
217
233
|
: new Set();
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return
|
|
225
|
-
|
|
234
|
+
if (pkgRoot && managedScripts.has(resolve(entrypoint)))
|
|
235
|
+
return true;
|
|
236
|
+
return /(?:^|[\\/])oh-my-codex(?:[\\/]|$)/.test(entrypoint);
|
|
237
|
+
}
|
|
238
|
+
export function sanitizePreviousNotifyCommand(command, pkgRoot) {
|
|
239
|
+
if (!command || command.length === 0)
|
|
240
|
+
return null;
|
|
241
|
+
if (isOmxManagedNotifyCommand(command, pkgRoot))
|
|
242
|
+
return null;
|
|
243
|
+
return [...command];
|
|
226
244
|
}
|
|
227
245
|
function getOmxTopLevelLines(pkgRoot, existingConfig = "", modelOverride, notifyCommand = getDefaultNotifyCommand(pkgRoot)) {
|
|
228
246
|
const rootValues = parseRootKeyValues(existingConfig);
|
|
@@ -346,16 +364,56 @@ export function stripOmxTopLevelKeys(config) {
|
|
|
346
364
|
// ---------------------------------------------------------------------------
|
|
347
365
|
// [features] upsert
|
|
348
366
|
// ---------------------------------------------------------------------------
|
|
349
|
-
function
|
|
367
|
+
function isFeatureFlagLine(line, featureFlag) {
|
|
368
|
+
return new RegExp(`^\\s*${featureFlag}\\s*=`).test(line);
|
|
369
|
+
}
|
|
370
|
+
function isAnyCodexHookFeatureFlagLine(line) {
|
|
371
|
+
return CODEX_HOOK_FEATURE_FLAGS.some((flag) => isFeatureFlagLine(line, flag));
|
|
372
|
+
}
|
|
373
|
+
function upsertCodexHookFeatureFlagInSection(lines, featuresStart, sectionEnd, codexHookFeatureFlag) {
|
|
374
|
+
const featureFlag = normalizeCodexHookFeatureFlag(codexHookFeatureFlag);
|
|
375
|
+
let featureFlagIdx = -1;
|
|
376
|
+
let fallbackAliasIdx = -1;
|
|
377
|
+
for (let i = featuresStart + 1; i < sectionEnd; i++) {
|
|
378
|
+
if (isFeatureFlagLine(lines[i], featureFlag)) {
|
|
379
|
+
featureFlagIdx = i;
|
|
380
|
+
}
|
|
381
|
+
else if (isAnyCodexHookFeatureFlagLine(lines[i]) && fallbackAliasIdx < 0) {
|
|
382
|
+
fallbackAliasIdx = i;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (featureFlagIdx < 0 && fallbackAliasIdx >= 0) {
|
|
386
|
+
featureFlagIdx = fallbackAliasIdx;
|
|
387
|
+
}
|
|
388
|
+
if (featureFlagIdx >= 0) {
|
|
389
|
+
lines[featureFlagIdx] = formatCodexHookFeatureFlagLine(featureFlag);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
lines.splice(sectionEnd, 0, formatCodexHookFeatureFlagLine(featureFlag));
|
|
393
|
+
featureFlagIdx = sectionEnd;
|
|
394
|
+
sectionEnd += 1;
|
|
395
|
+
}
|
|
396
|
+
for (let i = sectionEnd - 1; i > featuresStart; i--) {
|
|
397
|
+
if (i !== featureFlagIdx && isAnyCodexHookFeatureFlagLine(lines[i])) {
|
|
398
|
+
lines.splice(i, 1);
|
|
399
|
+
sectionEnd -= 1;
|
|
400
|
+
if (featureFlagIdx > i)
|
|
401
|
+
featureFlagIdx -= 1;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return { sectionEnd, featureFlagIndex: featureFlagIdx };
|
|
405
|
+
}
|
|
406
|
+
function upsertFeatureFlags(config, codexHookFeatureFlag = DEFAULT_CODEX_HOOK_FEATURE_FLAG) {
|
|
350
407
|
const lines = config.split(/\r?\n/);
|
|
351
408
|
const featuresStart = lines.findIndex((line) => /^\s*\[features\]\s*$/.test(line));
|
|
409
|
+
const hookFeatureFlagLine = formatCodexHookFeatureFlagLine(codexHookFeatureFlag);
|
|
352
410
|
if (featuresStart < 0) {
|
|
353
411
|
const base = config.trimEnd();
|
|
354
412
|
const featureBlock = [
|
|
355
413
|
"[features]",
|
|
356
414
|
"multi_agent = true",
|
|
357
415
|
"child_agents_md = true",
|
|
358
|
-
|
|
416
|
+
hookFeatureFlagLine,
|
|
359
417
|
"goals = true",
|
|
360
418
|
"",
|
|
361
419
|
].join("\n");
|
|
@@ -381,9 +439,6 @@ function upsertFeatureFlags(config) {
|
|
|
381
439
|
}
|
|
382
440
|
let multiAgentIdx = -1;
|
|
383
441
|
let childAgentsIdx = -1;
|
|
384
|
-
let codexHooksIdx = -1;
|
|
385
|
-
let unsupportedHooksIdx = -1;
|
|
386
|
-
let goalsIdx = -1;
|
|
387
442
|
for (let i = featuresStart + 1; i < sectionEnd; i++) {
|
|
388
443
|
if (/^\s*multi_agent\s*=/.test(lines[i])) {
|
|
389
444
|
multiAgentIdx = i;
|
|
@@ -391,15 +446,6 @@ function upsertFeatureFlags(config) {
|
|
|
391
446
|
else if (/^\s*child_agents_md\s*=/.test(lines[i])) {
|
|
392
447
|
childAgentsIdx = i;
|
|
393
448
|
}
|
|
394
|
-
else if (/^\s*hooks\s*=/.test(lines[i])) {
|
|
395
|
-
unsupportedHooksIdx = i;
|
|
396
|
-
}
|
|
397
|
-
else if (/^\s*codex_hooks\s*=/.test(lines[i])) {
|
|
398
|
-
codexHooksIdx = i;
|
|
399
|
-
}
|
|
400
|
-
else if (/^\s*goals\s*=/.test(lines[i])) {
|
|
401
|
-
goalsIdx = i;
|
|
402
|
-
}
|
|
403
449
|
}
|
|
404
450
|
if (multiAgentIdx >= 0) {
|
|
405
451
|
lines[multiAgentIdx] = "multi_agent = true";
|
|
@@ -415,27 +461,11 @@ function upsertFeatureFlags(config) {
|
|
|
415
461
|
lines.splice(sectionEnd, 0, "child_agents_md = true");
|
|
416
462
|
sectionEnd += 1;
|
|
417
463
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
codexHooksIdx = unsupportedHooksIdx;
|
|
424
|
-
unsupportedHooksIdx = -1;
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
lines.splice(sectionEnd, 0, "codex_hooks = true");
|
|
428
|
-
codexHooksIdx = sectionEnd;
|
|
429
|
-
sectionEnd += 1;
|
|
430
|
-
}
|
|
431
|
-
for (let i = sectionEnd - 1; i > featuresStart; i--) {
|
|
432
|
-
if (i !== codexHooksIdx && /^\s*hooks\s*=/.test(lines[i])) {
|
|
433
|
-
lines.splice(i, 1);
|
|
434
|
-
sectionEnd -= 1;
|
|
435
|
-
if (codexHooksIdx > i)
|
|
436
|
-
codexHooksIdx -= 1;
|
|
437
|
-
if (goalsIdx > i)
|
|
438
|
-
goalsIdx -= 1;
|
|
464
|
+
({ sectionEnd } = upsertCodexHookFeatureFlagInSection(lines, featuresStart, sectionEnd, codexHookFeatureFlag));
|
|
465
|
+
let goalsIdx = -1;
|
|
466
|
+
for (let i = featuresStart + 1; i < sectionEnd; i++) {
|
|
467
|
+
if (/^\s*goals\s*=/.test(lines[i])) {
|
|
468
|
+
goalsIdx = i;
|
|
439
469
|
}
|
|
440
470
|
}
|
|
441
471
|
if (goalsIdx >= 0) {
|
|
@@ -469,9 +499,38 @@ export function stripManagedCodexHookTrustState(config) {
|
|
|
469
499
|
}
|
|
470
500
|
return kept.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
471
501
|
}
|
|
502
|
+
function managedCodexHookTrustStateHeaders(hookTrustToml) {
|
|
503
|
+
const headers = new Set();
|
|
504
|
+
for (const line of hookTrustToml.split(/\r?\n/)) {
|
|
505
|
+
const trimmed = line.trim();
|
|
506
|
+
if (/^\[hooks\.state\./.test(trimmed)) {
|
|
507
|
+
headers.add(trimmed);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return headers;
|
|
511
|
+
}
|
|
512
|
+
function stripUnfencedManagedCodexHookTrustState(config, hookTrustToml) {
|
|
513
|
+
const managedHeaders = managedCodexHookTrustStateHeaders(hookTrustToml);
|
|
514
|
+
if (managedHeaders.size === 0)
|
|
515
|
+
return config;
|
|
516
|
+
const lines = config.split(/\r?\n/);
|
|
517
|
+
const kept = [];
|
|
518
|
+
for (let i = 0; i < lines.length;) {
|
|
519
|
+
if (!managedHeaders.has(lines[i].trim())) {
|
|
520
|
+
kept.push(lines[i]);
|
|
521
|
+
i += 1;
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
i += 1;
|
|
525
|
+
while (i < lines.length && !TOML_TABLE_HEADER_PATTERN.test(lines[i])) {
|
|
526
|
+
i += 1;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return kept.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
530
|
+
}
|
|
472
531
|
export function upsertManagedCodexHookTrustState(config, pkgRoot, codexHooksFile) {
|
|
473
|
-
const stripped = stripManagedCodexHookTrustState(config);
|
|
474
532
|
const hookTrustToml = buildManagedCodexHookTrustToml(codexHooksFile, pkgRoot);
|
|
533
|
+
const stripped = stripUnfencedManagedCodexHookTrustState(stripManagedCodexHookTrustState(config), hookTrustToml);
|
|
475
534
|
if (!hookTrustToml)
|
|
476
535
|
return `${stripped}\n`;
|
|
477
536
|
return [
|
|
@@ -484,14 +543,15 @@ export function upsertManagedCodexHookTrustState(config, pkgRoot, codexHooksFile
|
|
|
484
543
|
"",
|
|
485
544
|
].filter((line, index) => index !== 0 || line.length > 0).join("\n");
|
|
486
545
|
}
|
|
487
|
-
export function upsertPluginModeRuntimeFeatureFlags(config) {
|
|
546
|
+
export function upsertPluginModeRuntimeFeatureFlags(config, codexHookFeatureFlag = DEFAULT_CODEX_HOOK_FEATURE_FLAG) {
|
|
488
547
|
const lines = config.split(/\r?\n/);
|
|
489
548
|
const featuresStart = lines.findIndex((line) => /^\s*\[features\]\s*$/.test(line));
|
|
549
|
+
const hookFeatureFlagLine = formatCodexHookFeatureFlagLine(codexHookFeatureFlag);
|
|
490
550
|
if (featuresStart < 0) {
|
|
491
551
|
const base = config.trimEnd();
|
|
492
552
|
const featureBlock = [
|
|
493
553
|
"[features]",
|
|
494
|
-
|
|
554
|
+
hookFeatureFlagLine,
|
|
495
555
|
"goals = true",
|
|
496
556
|
"",
|
|
497
557
|
].join("\n");
|
|
@@ -515,43 +575,13 @@ export function upsertPluginModeRuntimeFeatureFlags(config) {
|
|
|
515
575
|
sectionEnd -= 1;
|
|
516
576
|
}
|
|
517
577
|
}
|
|
518
|
-
|
|
519
|
-
let unsupportedHooksIdx = -1;
|
|
578
|
+
({ sectionEnd } = upsertCodexHookFeatureFlagInSection(lines, featuresStart, sectionEnd, codexHookFeatureFlag));
|
|
520
579
|
let goalsIdx = -1;
|
|
521
580
|
for (let i = featuresStart + 1; i < sectionEnd; i++) {
|
|
522
|
-
if (/^\s*
|
|
523
|
-
unsupportedHooksIdx = i;
|
|
524
|
-
}
|
|
525
|
-
else if (/^\s*codex_hooks\s*=/.test(lines[i])) {
|
|
526
|
-
codexHooksIdx = i;
|
|
527
|
-
}
|
|
528
|
-
else if (/^\s*goals\s*=/.test(lines[i])) {
|
|
581
|
+
if (/^\s*goals\s*=/.test(lines[i])) {
|
|
529
582
|
goalsIdx = i;
|
|
530
583
|
}
|
|
531
584
|
}
|
|
532
|
-
if (codexHooksIdx >= 0) {
|
|
533
|
-
lines[codexHooksIdx] = "codex_hooks = true";
|
|
534
|
-
}
|
|
535
|
-
else if (unsupportedHooksIdx >= 0) {
|
|
536
|
-
lines[unsupportedHooksIdx] = "codex_hooks = true";
|
|
537
|
-
codexHooksIdx = unsupportedHooksIdx;
|
|
538
|
-
unsupportedHooksIdx = -1;
|
|
539
|
-
}
|
|
540
|
-
else {
|
|
541
|
-
lines.splice(sectionEnd, 0, "codex_hooks = true");
|
|
542
|
-
codexHooksIdx = sectionEnd;
|
|
543
|
-
sectionEnd++;
|
|
544
|
-
}
|
|
545
|
-
for (let i = sectionEnd - 1; i > featuresStart; i--) {
|
|
546
|
-
if (i !== codexHooksIdx && /^\s*hooks\s*=/.test(lines[i])) {
|
|
547
|
-
lines.splice(i, 1);
|
|
548
|
-
sectionEnd--;
|
|
549
|
-
if (codexHooksIdx > i)
|
|
550
|
-
codexHooksIdx--;
|
|
551
|
-
if (goalsIdx > i)
|
|
552
|
-
goalsIdx--;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
585
|
if (goalsIdx >= 0) {
|
|
556
586
|
lines[goalsIdx] = "goals = true";
|
|
557
587
|
}
|
|
@@ -767,12 +797,13 @@ export function stripOmxFeatureFlags(config) {
|
|
|
767
797
|
* Preserve native Codex hook enablement without re-adding other OMX feature
|
|
768
798
|
* flags. Used by uninstall when user-owned hooks remain in hooks.json.
|
|
769
799
|
*/
|
|
770
|
-
export function upsertCodexHooksFeatureFlag(config) {
|
|
800
|
+
export function upsertCodexHooksFeatureFlag(config, codexHookFeatureFlag = DEFAULT_CODEX_HOOK_FEATURE_FLAG) {
|
|
771
801
|
const lines = config.split(/\r?\n/);
|
|
772
802
|
const featuresStart = lines.findIndex((line) => /^\s*\[features\]\s*$/.test(line));
|
|
803
|
+
const hookFeatureFlagLine = formatCodexHookFeatureFlagLine(codexHookFeatureFlag);
|
|
773
804
|
if (featuresStart < 0) {
|
|
774
805
|
const base = config.trimEnd();
|
|
775
|
-
const featureBlock = ["[features]",
|
|
806
|
+
const featureBlock = ["[features]", hookFeatureFlagLine, ""].join("\n");
|
|
776
807
|
return base.length === 0 ? featureBlock : `${base}\n${featureBlock}`;
|
|
777
808
|
}
|
|
778
809
|
let sectionEnd = lines.length;
|
|
@@ -782,31 +813,7 @@ export function upsertCodexHooksFeatureFlag(config) {
|
|
|
782
813
|
break;
|
|
783
814
|
}
|
|
784
815
|
}
|
|
785
|
-
|
|
786
|
-
for (let i = featuresStart + 1; i < sectionEnd; i++) {
|
|
787
|
-
if (/^\s*codex_hooks\s*=/.test(lines[i])) {
|
|
788
|
-
codexHooksIdx = i;
|
|
789
|
-
lines[i] = "codex_hooks = true";
|
|
790
|
-
break;
|
|
791
|
-
}
|
|
792
|
-
if (codexHooksIdx < 0 && /^\s*hooks\s*=/.test(lines[i])) {
|
|
793
|
-
codexHooksIdx = i;
|
|
794
|
-
lines[i] = "codex_hooks = true";
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
if (codexHooksIdx < 0) {
|
|
798
|
-
lines.splice(sectionEnd, 0, "codex_hooks = true");
|
|
799
|
-
codexHooksIdx = sectionEnd;
|
|
800
|
-
sectionEnd += 1;
|
|
801
|
-
}
|
|
802
|
-
for (let i = sectionEnd - 1; i > featuresStart; i--) {
|
|
803
|
-
if (i !== codexHooksIdx && /^\s*hooks\s*=/.test(lines[i])) {
|
|
804
|
-
lines.splice(i, 1);
|
|
805
|
-
sectionEnd -= 1;
|
|
806
|
-
if (codexHooksIdx > i)
|
|
807
|
-
codexHooksIdx -= 1;
|
|
808
|
-
}
|
|
809
|
-
}
|
|
816
|
+
upsertCodexHookFeatureFlagInSection(lines, featuresStart, sectionEnd, codexHookFeatureFlag);
|
|
810
817
|
return lines.join("\n");
|
|
811
818
|
}
|
|
812
819
|
export function stripOmxEnvSettings(config) {
|
|
@@ -822,6 +829,13 @@ export function stripOmxEnvSettings(config) {
|
|
|
822
829
|
* Check whether a TOML table name belongs to a legacy OMX-managed agent entry.
|
|
823
830
|
* Handles both `agents.name` and `agents."name"` forms.
|
|
824
831
|
*/
|
|
832
|
+
function isOmxFirstPartyMcpSection(tableName) {
|
|
833
|
+
const match = tableName.match(/^mcp_servers\.(?:"([^"]+)"|([A-Za-z0-9_-]+))$/);
|
|
834
|
+
const name = match?.[1] ?? match?.[2];
|
|
835
|
+
return Boolean(name &&
|
|
836
|
+
(OMX_FIRST_PARTY_MCP_SERVER_NAMES.includes(name) ||
|
|
837
|
+
name === "omx_team_run"));
|
|
838
|
+
}
|
|
825
839
|
function isLegacyOmxAgentSection(tableName) {
|
|
826
840
|
const m = tableName.match(/^agents\.(?:"([^"]+)"|(\w[\w-]*))$/);
|
|
827
841
|
if (!m)
|
|
@@ -834,7 +848,8 @@ function isLegacyOmxAgentSection(tableName) {
|
|
|
834
848
|
* This covers legacy configs that were written before markers were added,
|
|
835
849
|
* or configs where the marker was accidentally removed.
|
|
836
850
|
*
|
|
837
|
-
* Targets:
|
|
851
|
+
* Targets: exact first-party [mcp_servers.<name>] entries, retired
|
|
852
|
+
* [mcp_servers.omx_team_run], and legacy [agents.<name>] entries.
|
|
838
853
|
*/
|
|
839
854
|
function stripOrphanedOmxSections(config) {
|
|
840
855
|
const lines = config.split(/\r?\n/);
|
|
@@ -848,7 +863,7 @@ function stripOrphanedOmxSections(config) {
|
|
|
848
863
|
// Note: [tui] is NOT stripped here because it could be user-owned.
|
|
849
864
|
// The marker-based stripExistingOmxBlocks already handles [tui]
|
|
850
865
|
// when it lives inside the OMX marker block.
|
|
851
|
-
const isOmxSection =
|
|
866
|
+
const isOmxSection = isOmxFirstPartyMcpSection(tableName) ||
|
|
852
867
|
isLegacyOmxAgentSection(tableName);
|
|
853
868
|
if (isOmxSection) {
|
|
854
869
|
// Remove preceding OMX comment lines and blank lines
|
|
@@ -1088,6 +1103,72 @@ export function stripExistingSharedMcpRegistryBlock(config) {
|
|
|
1088
1103
|
}
|
|
1089
1104
|
return { cleaned, removed };
|
|
1090
1105
|
}
|
|
1106
|
+
function getExistingSharedMcpRegistryBlocks(config) {
|
|
1107
|
+
const blocks = [];
|
|
1108
|
+
let cursor = 0;
|
|
1109
|
+
while (cursor < config.length) {
|
|
1110
|
+
const markerIdx = config.indexOf(SHARED_MCP_REGISTRY_MARKER, cursor);
|
|
1111
|
+
if (markerIdx < 0)
|
|
1112
|
+
break;
|
|
1113
|
+
let blockStart = config.lastIndexOf("\n", markerIdx);
|
|
1114
|
+
blockStart = blockStart >= 0 ? blockStart + 1 : 0;
|
|
1115
|
+
const previousLineEnd = blockStart - 1;
|
|
1116
|
+
if (previousLineEnd >= 0) {
|
|
1117
|
+
const previousLineStart = config.lastIndexOf("\n", previousLineEnd - 1);
|
|
1118
|
+
const previousLine = config.slice(previousLineStart + 1, previousLineEnd);
|
|
1119
|
+
if (/^# =+$/.test(previousLine.trim())) {
|
|
1120
|
+
blockStart = previousLineStart >= 0 ? previousLineStart + 1 : 0;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
let blockEnd = config.length;
|
|
1124
|
+
const endIdx = config.indexOf(SHARED_MCP_REGISTRY_END_MARKER, markerIdx);
|
|
1125
|
+
if (endIdx >= 0) {
|
|
1126
|
+
const endLineBreak = config.indexOf("\n", endIdx);
|
|
1127
|
+
blockEnd = endLineBreak >= 0 ? endLineBreak + 1 : config.length;
|
|
1128
|
+
}
|
|
1129
|
+
blocks.push(config.slice(blockStart, blockEnd));
|
|
1130
|
+
cursor = blockEnd;
|
|
1131
|
+
}
|
|
1132
|
+
return blocks;
|
|
1133
|
+
}
|
|
1134
|
+
export function extractSharedMcpRegistryServersFromConfig(config) {
|
|
1135
|
+
const servers = [];
|
|
1136
|
+
let sourcePath;
|
|
1137
|
+
for (const block of getExistingSharedMcpRegistryBlocks(config)) {
|
|
1138
|
+
sourcePath ??= block.match(/^# Source:\s*(.+?)\s*$/m)?.[1];
|
|
1139
|
+
let parsed;
|
|
1140
|
+
try {
|
|
1141
|
+
parsed = TOML.parse(block);
|
|
1142
|
+
}
|
|
1143
|
+
catch {
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
if (!isRecord(parsed) || !isRecord(parsed.mcp_servers))
|
|
1147
|
+
continue;
|
|
1148
|
+
for (const [name, value] of Object.entries(parsed.mcp_servers)) {
|
|
1149
|
+
if (!isRecord(value) || typeof value.command !== "string")
|
|
1150
|
+
continue;
|
|
1151
|
+
const args = Array.isArray(value.args)
|
|
1152
|
+
? value.args.filter((arg) => typeof arg === "string")
|
|
1153
|
+
: [];
|
|
1154
|
+
const enabled = typeof value.enabled === "boolean" ? value.enabled : true;
|
|
1155
|
+
const timeoutCandidate = typeof value.startup_timeout_sec === "number"
|
|
1156
|
+
? value.startup_timeout_sec
|
|
1157
|
+
: value.startupTimeoutSec;
|
|
1158
|
+
const startupTimeoutSec = typeof timeoutCandidate === "number" && Number.isFinite(timeoutCandidate)
|
|
1159
|
+
? timeoutCandidate
|
|
1160
|
+
: undefined;
|
|
1161
|
+
servers.push({
|
|
1162
|
+
name,
|
|
1163
|
+
command: value.command,
|
|
1164
|
+
args,
|
|
1165
|
+
enabled,
|
|
1166
|
+
...(startupTimeoutSec !== undefined ? { startupTimeoutSec } : {}),
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
return { servers, sourcePath };
|
|
1171
|
+
}
|
|
1091
1172
|
function toMcpServerTableKey(name) {
|
|
1092
1173
|
if (/^[A-Za-z0-9_-]+$/.test(name)) {
|
|
1093
1174
|
return `mcp_servers.${name}`;
|
|
@@ -1207,11 +1288,25 @@ function getSharedMcpRegistryBlock(servers, sourcePath, existingConfig) {
|
|
|
1207
1288
|
lines.push(SHARED_MCP_REGISTRY_END_MARKER);
|
|
1208
1289
|
return lines.join("\n");
|
|
1209
1290
|
}
|
|
1291
|
+
export function mergeSharedMcpRegistryBlock(config, servers, sourcePath) {
|
|
1292
|
+
const stripped = stripExistingSharedMcpRegistryBlock(config);
|
|
1293
|
+
const existing = stripped.cleaned;
|
|
1294
|
+
const sharedRegistryBlock = getSharedMcpRegistryBlock(servers, sourcePath, existing);
|
|
1295
|
+
const body = existing.trimEnd();
|
|
1296
|
+
const merged = sharedRegistryBlock
|
|
1297
|
+
? body
|
|
1298
|
+
? `${body}\n\n${sharedRegistryBlock}\n`
|
|
1299
|
+
: `${sharedRegistryBlock}\n`
|
|
1300
|
+
: body
|
|
1301
|
+
? `${body}\n`
|
|
1302
|
+
: "";
|
|
1303
|
+
return addDefaultLauncherMcpStartupTimeouts(merged);
|
|
1304
|
+
}
|
|
1210
1305
|
/**
|
|
1211
1306
|
* OMX table-section block (MCP servers, TUI).
|
|
1212
1307
|
* Contains ONLY [table] sections — no bare keys.
|
|
1213
1308
|
*/
|
|
1214
|
-
function getOmxTablesBlock(pkgRoot, includeTui = true, statusLinePreset = DEFAULT_STATUS_LINE_PRESET, codexHooksFile) {
|
|
1309
|
+
function getOmxTablesBlock(pkgRoot, includeTui = true, statusLinePreset = DEFAULT_STATUS_LINE_PRESET, codexHooksFile, includeFirstPartyMcp = false) {
|
|
1215
1310
|
const lines = [
|
|
1216
1311
|
"",
|
|
1217
1312
|
"# ============================================================",
|
|
@@ -1219,17 +1314,19 @@ function getOmxTablesBlock(pkgRoot, includeTui = true, statusLinePreset = DEFAUL
|
|
|
1219
1314
|
"# Managed by omx setup - manual edits preserved on next setup",
|
|
1220
1315
|
"# ============================================================",
|
|
1221
1316
|
];
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
.
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1317
|
+
if (includeFirstPartyMcp) {
|
|
1318
|
+
for (const server of getOmxFirstPartySetupMcpServers(pkgRoot)) {
|
|
1319
|
+
lines.push("");
|
|
1320
|
+
lines.push(server.title);
|
|
1321
|
+
lines.push(`[mcp_servers.${server.name}]`);
|
|
1322
|
+
lines.push(`command = "${escapeTomlString(server.command)}"`);
|
|
1323
|
+
lines.push(`args = [${server.args
|
|
1324
|
+
.map((arg) => `"${escapeTomlString(arg)}"`)
|
|
1325
|
+
.join(", ")}]`);
|
|
1326
|
+
lines.push(`enabled = ${server.enabled ? "true" : "false"}`);
|
|
1327
|
+
if (typeof server.startupTimeoutSec === "number") {
|
|
1328
|
+
lines.push(`startup_timeout_sec = ${server.startupTimeoutSec}`);
|
|
1329
|
+
}
|
|
1233
1330
|
}
|
|
1234
1331
|
}
|
|
1235
1332
|
const hookTrustToml = buildManagedCodexHookTrustToml(codexHooksFile, pkgRoot);
|
|
@@ -1295,11 +1392,12 @@ export function buildMergedConfig(existingConfig, pkgRoot, options = {}) {
|
|
|
1295
1392
|
}
|
|
1296
1393
|
existing = stripOrphanedManagedNotify(existing, pkgRoot);
|
|
1297
1394
|
existing = stripManagedCodexHookTrustState(existing);
|
|
1395
|
+
existing = stripUnfencedManagedCodexHookTrustState(existing, buildManagedCodexHookTrustToml(options.codexHooksFile, pkgRoot));
|
|
1298
1396
|
if (options.modelOverride) {
|
|
1299
1397
|
existing = stripRootLevelKeys(existing, ["model"]);
|
|
1300
1398
|
}
|
|
1301
1399
|
existing = stripOrphanedOmxSections(existing);
|
|
1302
|
-
existing = upsertFeatureFlags(existing);
|
|
1400
|
+
existing = upsertFeatureFlags(existing, options.codexHookFeatureFlag);
|
|
1303
1401
|
existing = upsertEnvSettings(existing);
|
|
1304
1402
|
existing = upsertAgentsSettings(existing);
|
|
1305
1403
|
const tuiUpsert = includeTui
|
|
@@ -1311,7 +1409,7 @@ export function buildMergedConfig(existingConfig, pkgRoot, options = {}) {
|
|
|
1311
1409
|
const topLines = getOmxTopLevelLines(pkgRoot, existing, options.modelOverride, options.notifyCommand === undefined
|
|
1312
1410
|
? getDefaultNotifyCommand(pkgRoot)
|
|
1313
1411
|
: options.notifyCommand);
|
|
1314
|
-
const tablesBlock = getOmxTablesBlock(pkgRoot, includeTui && !tuiUpsert.hadExistingTui, statusLinePreset, options.codexHooksFile);
|
|
1412
|
+
const tablesBlock = getOmxTablesBlock(pkgRoot, includeTui && !tuiUpsert.hadExistingTui, statusLinePreset, options.codexHooksFile, options.includeFirstPartyMcp === true);
|
|
1315
1413
|
const sharedRegistryBlock = getSharedMcpRegistryBlock(options.sharedMcpServers ?? [], options.sharedMcpRegistrySource, existing);
|
|
1316
1414
|
let body = existing.trimEnd();
|
|
1317
1415
|
if (sharedRegistryBlock) {
|