oh-my-codex 0.18.7 → 0.18.8
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 +6 -6
- package/Cargo.toml +1 -1
- package/README.md +5 -5
- package/crates/omx-sparkshell/tests/execution.rs +1 -1
- package/dist/agents/__tests__/native-config.test.js +42 -1
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts +8 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +1 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/native-config.d.ts +5 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +17 -2
- package/dist/agents/native-config.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +512 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +39 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +61 -5
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +8 -4
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +13 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +14 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +89 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +65 -0
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/state.test.js +21 -0
- package/dist/cli/__tests__/state.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +2 -2
- package/dist/cli/__tests__/update.test.js +110 -2
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +8 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +11 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +108 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +14 -2
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +62 -15
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +3 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +2 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +4 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +166 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/state.d.ts.map +1 -1
- package/dist/cli/state.js +8 -1
- package/dist/cli/state.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +16 -0
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +47 -3
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +1 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/generator.d.ts +2 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +2 -2
- package/dist/config/generator.js.map +1 -1
- package/dist/config/team-mode.d.ts +12 -0
- package/dist/config/team-mode.d.ts.map +1 -0
- package/dist/config/team-mode.js +91 -0
- package/dist/config/team-mode.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +88 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +8 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +423 -3
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +189 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +35 -2
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +3 -3
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-guidance-contract.test.js +21 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +36 -50
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +31 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +1 -1
- package/dist/hooks/extensibility/plugin-runner.js +17 -21
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +258 -12
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +6 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +1 -0
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/authority.test.js +435 -32
- package/dist/hud/__tests__/authority.test.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +2 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +42 -0
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +521 -15
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +61 -0
- package/dist/hud/__tests__/render.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +132 -4
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +180 -21
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/authority.d.ts +5 -0
- package/dist/hud/authority.d.ts.map +1 -1
- package/dist/hud/authority.js +324 -28
- package/dist/hud/authority.js.map +1 -1
- package/dist/hud/index.d.ts +3 -2
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +42 -19
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.d.ts +3 -3
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +128 -19
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +35 -0
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +61 -62
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.d.ts +24 -6
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +136 -38
- package/dist/hud/tmux.js.map +1 -1
- package/dist/hud/types.d.ts +11 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +71 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +32 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +113 -17
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/scripts/__tests__/codex-native-hook.test.js +593 -11
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-state-io.test.js +72 -1
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js +57 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js +74 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +65 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +88 -31
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +3 -1
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +3 -10
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +62 -38
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +7 -0
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +7 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +24 -18
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +75 -11
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-test-files.js +193 -22
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +61 -3
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/verify-native-agents.d.ts.map +1 -1
- package/dist/scripts/verify-native-agents.js +58 -1
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +113 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +3 -16
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +25 -0
- 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 +57 -2
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +7 -39
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +10 -14
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +1 -1
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +9 -4
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +195 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +4 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +3 -2
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/tmux-session.d.ts +2 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +142 -12
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +81 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +8 -8
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +334 -21
- package/plugins/oh-my-codex/hooks/hooks.json +1 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +3 -1
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +7 -7
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -22
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +9 -0
- package/skills/autopilot/SKILL.md +3 -1
- package/skills/code-review/SKILL.md +7 -7
- package/skills/ralph/SKILL.md +22 -22
- package/skills/ultraqa/SKILL.md +9 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +686 -13
- package/src/scripts/__tests__/notify-state-io.test.ts +95 -0
- package/src/scripts/__tests__/notify-tmux-injection.test.ts +82 -0
- package/src/scripts/__tests__/run-test-files.test.ts +102 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +75 -0
- package/src/scripts/codex-native-hook.ts +105 -28
- package/src/scripts/demo-team-e2e.sh +10 -7
- package/src/scripts/eval/eval-parity-smoke.ts +1 -1
- package/src/scripts/notify-hook/auto-nudge.ts +3 -1
- package/src/scripts/notify-hook/ralph-session-resume.ts +2 -8
- package/src/scripts/notify-hook/state-io.ts +75 -37
- package/src/scripts/notify-hook/team-leader-nudge.ts +7 -0
- package/src/scripts/notify-hook/tmux-injection.ts +35 -19
- package/src/scripts/notify-hook.ts +91 -4
- package/src/scripts/run-test-files.ts +192 -22
- package/src/scripts/sync-plugin-mirror.ts +98 -9
- package/src/scripts/verify-native-agents.ts +65 -1
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
assertSkillMirror,
|
|
14
14
|
compareSkillMirror,
|
|
15
15
|
} from "../catalog/skill-mirror.js";
|
|
16
|
+
import { MANAGED_HOOK_EVENTS } from "../config/codex-hooks.js";
|
|
16
17
|
import { buildOmxPluginMcpManifest } from "../config/omx-first-party-mcp.js";
|
|
17
18
|
|
|
18
19
|
export interface SyncPluginMirrorOptions {
|
|
@@ -56,6 +57,15 @@ const SETUP_OWNED_PLUGIN_MANIFEST_FIELDS = [
|
|
|
56
57
|
"agents",
|
|
57
58
|
"prompts",
|
|
58
59
|
] as const;
|
|
60
|
+
const OMX_PLUGIN_HOOK_COMMAND =
|
|
61
|
+
'node "${PLUGIN_ROOT}/hooks/codex-native-hook.mjs"';
|
|
62
|
+
const OMX_PLUGIN_HOOK_LAUNCHER_CONTRACT_MARKER =
|
|
63
|
+
"omx-plugin-hook-launcher:v1";
|
|
64
|
+
// Plugin-scoped Codex hooks intentionally mirror the setup-managed lifecycle
|
|
65
|
+
// roster today while using PLUGIN_ROOT-local launch commands. If plugin and
|
|
66
|
+
// setup hook coverage diverge, split this alias into a plugin-owned roster.
|
|
67
|
+
const PLUGIN_HOOK_EVENTS = MANAGED_HOOK_EVENTS;
|
|
68
|
+
type PluginHookEventName = (typeof PLUGIN_HOOK_EVENTS)[number];
|
|
59
69
|
|
|
60
70
|
async function readJsonFile<T>(path: string): Promise<T> {
|
|
61
71
|
return JSON.parse(await readFile(path, "utf-8")) as T;
|
|
@@ -65,6 +75,35 @@ function stringifyJson(value: unknown): string {
|
|
|
65
75
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
66
76
|
}
|
|
67
77
|
|
|
78
|
+
function commandHook(timeout?: number): JsonValue {
|
|
79
|
+
return {
|
|
80
|
+
type: "command",
|
|
81
|
+
command: OMX_PLUGIN_HOOK_COMMAND,
|
|
82
|
+
...(typeof timeout === "number" ? { timeout } : {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function pluginHookEntry(eventName: PluginHookEventName): JsonValue {
|
|
87
|
+
const base = {
|
|
88
|
+
hooks: [commandHook(eventName === "Stop" ? 30 : undefined)],
|
|
89
|
+
};
|
|
90
|
+
if (eventName === "SessionStart") {
|
|
91
|
+
return { ...base, matcher: "startup|resume|clear" };
|
|
92
|
+
}
|
|
93
|
+
return base;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function buildOmxPluginHooksManifest(): JsonValue {
|
|
97
|
+
return {
|
|
98
|
+
hooks: Object.fromEntries(
|
|
99
|
+
PLUGIN_HOOK_EVENTS.map((eventName) => [
|
|
100
|
+
eventName,
|
|
101
|
+
[pluginHookEntry(eventName)],
|
|
102
|
+
]),
|
|
103
|
+
),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
68
107
|
function assertDeepJsonEqual(
|
|
69
108
|
actual: unknown,
|
|
70
109
|
expected: unknown,
|
|
@@ -84,12 +123,36 @@ function assertDeepJsonEqual(
|
|
|
84
123
|
}
|
|
85
124
|
}
|
|
86
125
|
|
|
126
|
+
function assertPluginHookLauncherContractMarkerPresent(
|
|
127
|
+
path: string,
|
|
128
|
+
content: string,
|
|
129
|
+
): void {
|
|
130
|
+
const requiredMarkers = [
|
|
131
|
+
OMX_PLUGIN_HOOK_LAUNCHER_CONTRACT_MARKER,
|
|
132
|
+
];
|
|
133
|
+
const missingMarkers = requiredMarkers.filter(
|
|
134
|
+
(marker) => !content.includes(marker),
|
|
135
|
+
);
|
|
136
|
+
if (missingMarkers.length > 0) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
[
|
|
139
|
+
"plugin_bundle_metadata_out_of_sync",
|
|
140
|
+
"kind=hook-launcher",
|
|
141
|
+
`path=${path}`,
|
|
142
|
+
`missingMarkers=${JSON.stringify(missingMarkers)}`,
|
|
143
|
+
].join("\n"),
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
87
148
|
function getPluginPaths(root: string): {
|
|
88
149
|
pluginRoot: string;
|
|
89
150
|
pluginSkillsDir: string;
|
|
90
151
|
pluginMcpPath: string;
|
|
91
152
|
pluginAppsPath: string;
|
|
92
153
|
pluginManifestPath: string;
|
|
154
|
+
pluginHooksPath: string;
|
|
155
|
+
pluginHookLauncherPath: string;
|
|
93
156
|
} {
|
|
94
157
|
const pluginRoot = join(root, "plugins", PLUGIN_NAME);
|
|
95
158
|
return {
|
|
@@ -98,6 +161,8 @@ function getPluginPaths(root: string): {
|
|
|
98
161
|
pluginMcpPath: join(pluginRoot, ".mcp.json"),
|
|
99
162
|
pluginAppsPath: join(pluginRoot, ".app.json"),
|
|
100
163
|
pluginManifestPath: join(pluginRoot, ".codex-plugin", "plugin.json"),
|
|
164
|
+
pluginHooksPath: join(pluginRoot, "hooks", "hooks.json"),
|
|
165
|
+
pluginHookLauncherPath: join(pluginRoot, "hooks", "codex-native-hook.mjs"),
|
|
101
166
|
};
|
|
102
167
|
}
|
|
103
168
|
|
|
@@ -188,6 +253,7 @@ async function buildExpectedPluginManifest(
|
|
|
188
253
|
skills: "./skills/",
|
|
189
254
|
mcpServers: "./.mcp.json",
|
|
190
255
|
apps: "./.app.json",
|
|
256
|
+
hooks: "./hooks/hooks.json",
|
|
191
257
|
};
|
|
192
258
|
}
|
|
193
259
|
|
|
@@ -237,16 +303,29 @@ async function assertPluginManifestPolicy(
|
|
|
237
303
|
}
|
|
238
304
|
|
|
239
305
|
async function assertPluginMetadata(root: string): Promise<void> {
|
|
240
|
-
const {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
306
|
+
const {
|
|
307
|
+
pluginMcpPath,
|
|
308
|
+
pluginAppsPath,
|
|
309
|
+
pluginManifestPath,
|
|
310
|
+
pluginHooksPath,
|
|
311
|
+
pluginHookLauncherPath,
|
|
312
|
+
} = getPluginPaths(root);
|
|
313
|
+
const [actualMcp, actualApps, actualManifest, actualHooks, actualHookLauncher] =
|
|
314
|
+
await Promise.all([
|
|
315
|
+
readJsonFile<unknown>(pluginMcpPath),
|
|
316
|
+
readJsonFile<unknown>(pluginAppsPath),
|
|
317
|
+
readJsonFile<PluginManifest>(pluginManifestPath),
|
|
318
|
+
readJsonFile<unknown>(pluginHooksPath),
|
|
319
|
+
readFile(pluginHookLauncherPath, "utf-8"),
|
|
320
|
+
]);
|
|
247
321
|
|
|
248
322
|
assertDeepJsonEqual(actualMcp, buildOmxPluginMcpManifest(), "mcp-manifest");
|
|
249
323
|
assertDeepJsonEqual(actualApps, { apps: {} }, "apps-manifest");
|
|
324
|
+
assertDeepJsonEqual(actualHooks, buildOmxPluginHooksManifest(), "hooks-manifest");
|
|
325
|
+
assertPluginHookLauncherContractMarkerPresent(
|
|
326
|
+
pluginHookLauncherPath,
|
|
327
|
+
actualHookLauncher,
|
|
328
|
+
);
|
|
250
329
|
await assertPluginManifestPolicy(root, actualManifest);
|
|
251
330
|
}
|
|
252
331
|
|
|
@@ -254,11 +333,16 @@ async function writePluginMetadata(
|
|
|
254
333
|
root: string,
|
|
255
334
|
verbose = false,
|
|
256
335
|
): Promise<boolean> {
|
|
257
|
-
const {
|
|
258
|
-
|
|
336
|
+
const {
|
|
337
|
+
pluginMcpPath,
|
|
338
|
+
pluginAppsPath,
|
|
339
|
+
pluginManifestPath,
|
|
340
|
+
pluginHooksPath,
|
|
341
|
+
} = getPluginPaths(root);
|
|
259
342
|
const expectedMcp = buildOmxPluginMcpManifest();
|
|
260
343
|
const expectedApps = { apps: {} };
|
|
261
344
|
const expectedManifest = await buildExpectedPluginManifest(root);
|
|
345
|
+
const expectedHooks = buildOmxPluginHooksManifest();
|
|
262
346
|
const writes = [
|
|
263
347
|
{
|
|
264
348
|
path: pluginMcpPath,
|
|
@@ -275,6 +359,11 @@ async function writePluginMetadata(
|
|
|
275
359
|
content: stringifyJson(expectedManifest),
|
|
276
360
|
label: "plugin manifest",
|
|
277
361
|
},
|
|
362
|
+
{
|
|
363
|
+
path: pluginHooksPath,
|
|
364
|
+
content: stringifyJson(expectedHooks),
|
|
365
|
+
label: "plugin hooks manifest",
|
|
366
|
+
},
|
|
278
367
|
];
|
|
279
368
|
let changed = false;
|
|
280
369
|
|
|
@@ -116,13 +116,30 @@ function assertTomlStructure(
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
const metadataHeading = "## OMX Agent Metadata";
|
|
120
|
+
const metadataIndex = instructions.lastIndexOf(metadataHeading);
|
|
121
|
+
if (metadataIndex < 0) {
|
|
122
|
+
throw errorBlock("native_agent_toml_invalid", {
|
|
123
|
+
agent: agentName,
|
|
124
|
+
field: "developer_instructions",
|
|
125
|
+
missing: metadataHeading,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const metadataLines = new Set(
|
|
129
|
+
instructions
|
|
130
|
+
.slice(metadataIndex)
|
|
131
|
+
.split(/\r?\n/)
|
|
132
|
+
.map((line) => line.trim())
|
|
133
|
+
.filter(Boolean),
|
|
134
|
+
);
|
|
135
|
+
|
|
119
136
|
for (const expected of [
|
|
120
137
|
`- role: ${agentName}`,
|
|
121
138
|
`- posture: ${agent.posture}`,
|
|
122
139
|
`- model_class: ${agent.modelClass}`,
|
|
123
140
|
`- routing_role: ${agent.routingRole}`,
|
|
124
141
|
]) {
|
|
125
|
-
if (!
|
|
142
|
+
if (!metadataLines.has(expected)) {
|
|
126
143
|
throw errorBlock("native_agent_toml_invalid", {
|
|
127
144
|
agent: agentName,
|
|
128
145
|
field: "developer_instructions",
|
|
@@ -130,6 +147,53 @@ function assertTomlStructure(
|
|
|
130
147
|
});
|
|
131
148
|
}
|
|
132
149
|
}
|
|
150
|
+
|
|
151
|
+
const leafGuard = "<native_subagent_leaf_guard>";
|
|
152
|
+
const leafGuardEnd = "</native_subagent_leaf_guard>";
|
|
153
|
+
const allowedDelegation = "- native_subagent_delegation: allowed";
|
|
154
|
+
const latestGeneratedPolicyIndex = Math.max(
|
|
155
|
+
instructions.lastIndexOf("</posture_overlay>", metadataIndex),
|
|
156
|
+
instructions.lastIndexOf("</model_class_guidance>", metadataIndex),
|
|
157
|
+
instructions.lastIndexOf("</exact_model_guidance>", metadataIndex),
|
|
158
|
+
);
|
|
159
|
+
const leafGuardIndex = instructions.lastIndexOf(leafGuard);
|
|
160
|
+
const leafGuardEndIndex = instructions.lastIndexOf(leafGuardEnd);
|
|
161
|
+
const hasGeneratedLeafGuard = leafGuardIndex > latestGeneratedPolicyIndex
|
|
162
|
+
&& leafGuardEndIndex > leafGuardIndex
|
|
163
|
+
&& leafGuardEndIndex < metadataIndex;
|
|
164
|
+
if (agent.nativeSubagentDelegation === "allowed") {
|
|
165
|
+
if (!metadataLines.has(allowedDelegation)) {
|
|
166
|
+
throw errorBlock("native_agent_toml_invalid", {
|
|
167
|
+
agent: agentName,
|
|
168
|
+
field: "developer_instructions",
|
|
169
|
+
missing: allowedDelegation,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (hasGeneratedLeafGuard) {
|
|
173
|
+
throw errorBlock("native_agent_toml_invalid", {
|
|
174
|
+
agent: agentName,
|
|
175
|
+
field: "developer_instructions",
|
|
176
|
+
unexpected: leafGuard,
|
|
177
|
+
message: "delegation-allowed agents must not receive the leaf-only guard",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
if (!hasGeneratedLeafGuard) {
|
|
182
|
+
throw errorBlock("native_agent_toml_invalid", {
|
|
183
|
+
agent: agentName,
|
|
184
|
+
field: "developer_instructions",
|
|
185
|
+
missing: leafGuard,
|
|
186
|
+
message: "leaf native agents must receive the anti-recursion guard",
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (metadataLines.has(allowedDelegation)) {
|
|
190
|
+
throw errorBlock("native_agent_toml_invalid", {
|
|
191
|
+
agent: agentName,
|
|
192
|
+
field: "developer_instructions",
|
|
193
|
+
unexpected: allowedDelegation,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
133
197
|
}
|
|
134
198
|
|
|
135
199
|
export async function verifyNativeAgents(
|