oh-my-codex 0.21.13 → 0.21.15
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 +17 -0
- package/dist/adapt/herdr/__tests__/wiring.test.js +21 -0
- package/dist/adapt/herdr/__tests__/wiring.test.js.map +1 -1
- package/dist/adapt/herdr/wiring.d.ts.map +1 -1
- package/dist/adapt/herdr/wiring.js +5 -0
- package/dist/adapt/herdr/wiring.js.map +1 -1
- package/dist/auth/__tests__/hotswap.test.js +28 -0
- package/dist/auth/__tests__/hotswap.test.js.map +1 -1
- package/dist/auth/hotswap.d.ts +1 -0
- package/dist/auth/hotswap.d.ts.map +1 -1
- package/dist/auth/hotswap.js +4 -1
- package/dist/auth/hotswap.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +196 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +2 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +14 -1
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/session-timeline.test.d.ts +2 -0
- package/dist/cli/__tests__/session-timeline.test.d.ts.map +1 -0
- package/dist/cli/__tests__/session-timeline.test.js +155 -0
- package/dist/cli/__tests__/session-timeline.test.js.map +1 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +1 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +1 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +11 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/session-search.d.ts.map +1 -1
- package/dist/cli/session-search.js +7 -0
- package/dist/cli/session-search.js.map +1 -1
- package/dist/cli/session-timeline.d.ts +9 -0
- package/dist/cli/session-timeline.d.ts.map +1 -0
- package/dist/cli/session-timeline.js +174 -0
- package/dist/cli/session-timeline.js.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.js +3 -1
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +1 -0
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/codex-hooks.d.ts +1 -1
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +5 -0
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/evals/astra-defaults/__tests__/collector.test.js +51 -23
- package/dist/evals/astra-defaults/__tests__/collector.test.js.map +1 -1
- package/dist/evals/astra-defaults/collector.d.ts +2 -0
- package/dist/evals/astra-defaults/collector.d.ts.map +1 -1
- package/dist/evals/astra-defaults/collector.js +19 -8
- package/dist/evals/astra-defaults/collector.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +143 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js +120 -28
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
- package/dist/hooks/extensibility/runtime.js +1 -0
- package/dist/hooks/extensibility/runtime.js.map +1 -1
- package/dist/hooks/extensibility/types.d.ts +2 -0
- package/dist/hooks/extensibility/types.d.ts.map +1 -1
- package/dist/hooks/native/types.d.ts +1 -1
- package/dist/hooks/native/types.d.ts.map +1 -1
- package/dist/hooks/native/types.js.map +1 -1
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js +200 -2
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -1
- package/dist/notifications/lifecycle-dedupe.d.ts +10 -0
- package/dist/notifications/lifecycle-dedupe.d.ts.map +1 -1
- package/dist/notifications/lifecycle-dedupe.js +175 -19
- package/dist/notifications/lifecycle-dedupe.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +278 -6
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/native-hook-protocol.test.d.ts +2 -0
- package/dist/scripts/__tests__/native-hook-protocol.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/native-hook-protocol.test.js +329 -0
- package/dist/scripts/__tests__/native-hook-protocol.test.js.map +1 -0
- package/dist/scripts/__tests__/smoke-packed-install.test.js +7 -6
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/codex-execution-surface.d.ts +1 -1
- package/dist/scripts/codex-execution-surface.d.ts.map +1 -1
- package/dist/scripts/codex-execution-surface.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +124 -13
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/hook-payload-guard.d.ts +1 -1
- package/dist/scripts/hook-payload-guard.d.ts.map +1 -1
- package/dist/scripts/hook-payload-guard.js +1 -0
- package/dist/scripts/hook-payload-guard.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +2 -2
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +12 -1
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/session-history/__tests__/timeline.test.d.ts +2 -0
- package/dist/session-history/__tests__/timeline.test.d.ts.map +1 -0
- package/dist/session-history/__tests__/timeline.test.js +459 -0
- package/dist/session-history/__tests__/timeline.test.js.map +1 -0
- package/dist/session-history/export.d.ts +2 -3
- package/dist/session-history/export.d.ts.map +1 -1
- package/dist/session-history/export.js +5 -66
- package/dist/session-history/export.js.map +1 -1
- package/dist/session-history/timeline.d.ts +97 -0
- package/dist/session-history/timeline.d.ts.map +1 -0
- package/dist/session-history/timeline.js +325 -0
- package/dist/session-history/timeline.js.map +1 -0
- package/dist/session-history/transcript.d.ts +16 -0
- package/dist/session-history/transcript.d.ts.map +1 -0
- package/dist/session-history/transcript.js +111 -0
- package/dist/session-history/transcript.js.map +1 -0
- package/dist/subagents/tracker.d.ts +6 -0
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +32 -0
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +12 -3
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +25 -0
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +30 -0
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +9 -1
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/wiki/__tests__/session-hooks.test.js +26 -0
- package/dist/wiki/__tests__/session-hooks.test.js.map +1 -1
- package/dist/wiki/lifecycle.d.ts.map +1 -1
- package/dist/wiki/lifecycle.js +6 -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/hooks/codex-native-hook.mjs +85 -18
- package/plugins/oh-my-codex/hooks/hooks.json +10 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +273 -5
- package/src/scripts/__tests__/native-hook-protocol.test.ts +362 -0
- package/src/scripts/__tests__/smoke-packed-install.test.ts +7 -6
- package/src/scripts/codex-execution-surface.ts +1 -0
- package/src/scripts/codex-native-hook.ts +130 -11
- package/src/scripts/hook-payload-guard.ts +1 -0
- package/src/scripts/smoke-packed-install.ts +12 -1
|
@@ -7,7 +7,7 @@ import { fileURLToPath, pathToFileURL } from "url";
|
|
|
7
7
|
import { readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
|
|
8
8
|
import { redactAuthSecrets } from "../auth/redact.js";
|
|
9
9
|
import { SKILL_ACTIVE_STATE_FILE, extractSessionIdFromInitializedStatePath, getSkillActiveStatePathsForStateDir, listActiveSkills, readSkillActiveState, readVisibleSkillActiveStateForStateDir, } from "../state/skill-active.js";
|
|
10
|
-
import { fenceNativeSubagentAuthorities, forceGlobalAuthorityDenial, consumeDirectChildReopenContext, isTrustedSubagentThread, readSubagentSessionSummary, readSubagentTrackingState, recordNativeSubagentAuthorityObservation, recordSubagentTurnForSession, repairPersistedRootIdentity, quarantinePersistedRootAuthority, revokeNativeSubagentAuthorities, resolveInstalledRoleName, } from "../subagents/tracker.js";
|
|
10
|
+
import { fenceNativeSubagentAuthorities, forceGlobalAuthorityDenial, consumeDirectChildReopenContext, isTrustedSubagentThread, readSubagentSessionSummary, readSubagentTrackingState, recordNativeSubagentAuthorityObservation, recordSubagentTurnForSession, recordSubagentTurnForSessionPartitions, repairPersistedRootIdentity, quarantinePersistedRootAuthority, revokeNativeSubagentAuthorities, resolveInstalledRoleName, } from "../subagents/tracker.js";
|
|
11
11
|
import { readRoleRoutingMarker, writeRoleRoutingMarker } from "../subagents/role-routing-marker.js";
|
|
12
12
|
import { reconcileRalplanAdvisory, observeRalplanAdvisoryPrompt, } from "../ralplan/advisory.js";
|
|
13
13
|
import { activateOrResumeRalplanAdvisory } from "../ralplan/advisory-activation.js";
|
|
@@ -39,6 +39,7 @@ import { dispatchHookEventRuntime } from "../hooks/extensibility/runtime.js";
|
|
|
39
39
|
import { getNotificationConfig, getVerbosity } from "../notifications/config.js";
|
|
40
40
|
import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
|
|
41
41
|
import { onPreCompact as buildWikiPreCompactContext, onSessionStart as buildWikiSessionStartContext, } from "../wiki/lifecycle.js";
|
|
42
|
+
import { sessionModelInstructionsPath } from "../hooks/agents-overlay.js";
|
|
42
43
|
import { readAutoresearchCompletionStatus, readAutoresearchModeStateForActiveDecision } from "../autoresearch/skill-validation.js";
|
|
43
44
|
import { deriveAutopilotChildPhase, normalizeAutopilotPhase } from "../autopilot/fsm.js";
|
|
44
45
|
import { CONDUCTOR_ORCHESTRATION_METADATA_PREFIXES, LEADER_CONDUCTOR_BLOCK, LEADER_CONDUCTOR_REUSE_AND_LEDGER_GUIDANCE, NATIVE_SUBAGENT_SUPPORT_BLOCKER_FILE, actionKindForConductorArtifact, authorizeConductorAction, buildRoleRoutingUnavailableGuidance, buildUnsupportedNativeSubagentGuidance, canonicalizeNativeCollaborationToolName, classifyConductorArtifactKind, parseNativeSubagentResultDisposition, resolveNativeSubagentSupportStatus } from "../leader/contract.js";
|
|
@@ -449,6 +450,7 @@ function readHookEventName(payload) {
|
|
|
449
450
|
|| raw === "UserPromptSubmit"
|
|
450
451
|
|| raw === "PreCompact"
|
|
451
452
|
|| raw === "PostCompact"
|
|
453
|
+
|| raw === "SubagentStop"
|
|
452
454
|
|| raw === "Stop") {
|
|
453
455
|
return raw;
|
|
454
456
|
}
|
|
@@ -472,6 +474,8 @@ export function mapCodexHookEventToOmxEvent(hookEventName) {
|
|
|
472
474
|
return "pre-compact";
|
|
473
475
|
case "PostCompact":
|
|
474
476
|
return "post-compact";
|
|
477
|
+
case "SubagentStop":
|
|
478
|
+
return "subagent-stop";
|
|
475
479
|
case "Stop":
|
|
476
480
|
return "stop";
|
|
477
481
|
default:
|
|
@@ -605,9 +609,11 @@ function sanitizePayloadForHookContext(payload, hookEventName, canonicalSessionI
|
|
|
605
609
|
delete sanitized.text;
|
|
606
610
|
return sanitized;
|
|
607
611
|
}
|
|
608
|
-
if (hookEventName === "Stop") {
|
|
612
|
+
if (hookEventName === "Stop" || hookEventName === "SubagentStop") {
|
|
609
613
|
delete sanitized.stop_hook_active;
|
|
610
614
|
delete sanitized.stopHookActive;
|
|
615
|
+
}
|
|
616
|
+
if (hookEventName === "Stop") {
|
|
611
617
|
delete sanitized.sessionId;
|
|
612
618
|
sanitized.session_id = canonicalSessionId.trim() || safeString(payload.session_id ?? payload.sessionId).trim();
|
|
613
619
|
}
|
|
@@ -1789,6 +1795,21 @@ async function buildPersistedSubagentReopenContext(cwd, sessionId, options) {
|
|
|
1789
1795
|
}
|
|
1790
1796
|
async function buildSessionStartContext(cwd, sessionId, options = {}) {
|
|
1791
1797
|
const sections = [];
|
|
1798
|
+
let startupInstructions = "";
|
|
1799
|
+
const startupFile = process.env.OMX_STARTUP_MODEL_INSTRUCTIONS_FILE;
|
|
1800
|
+
if (readSessionStartSource(options.payload) === "startup" && startupFile
|
|
1801
|
+
&& resolve(startupFile) === sessionModelInstructionsPath(cwd, sessionId)) {
|
|
1802
|
+
try {
|
|
1803
|
+
startupInstructions = await readFile(startupFile, "utf-8");
|
|
1804
|
+
}
|
|
1805
|
+
catch {
|
|
1806
|
+
// Missing launch evidence must preserve hook-delivered memory.
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
const startupMemory = startupInstructions.match(/(?:^|\n)\*\*Project Context:\*\*\r?\n([\s\S]*?)(?=\r?\n\r?\n|$)/)?.[1] ?? "";
|
|
1810
|
+
const alreadyInStartupInstructions = (label, value) => startupMemory.split(/\r?\n/).some(line => line.trim().replace(/\s+/g, " ") === `- ${label}: ${value}`);
|
|
1811
|
+
const startupPriority = startupInstructions.match(/(?:^|\n)\*\*Priority Notes:\*\*\r?\n([\s\S]*?)(?=\r?\n\r?\n|$)/)?.[1]
|
|
1812
|
+
.replace(/\s+/g, " ").trim();
|
|
1792
1813
|
sections.push(buildExecutionEnvironmentSection(cwd, {
|
|
1793
1814
|
hookEventName: options.hookEventName,
|
|
1794
1815
|
payload: options.payload,
|
|
@@ -1831,16 +1852,16 @@ async function buildSessionStartContext(cwd, sessionId, options = {}) {
|
|
|
1831
1852
|
const summary = [];
|
|
1832
1853
|
const relativeMemoryPath = relative(cwd, projectMemoryPath).replace(/\\/g, "/");
|
|
1833
1854
|
summary.push(`- source: ${relativeMemoryPath === "project-memory.json" ? "project-memory.json" : ".omx/project-memory.json"}`);
|
|
1834
|
-
if (techStack)
|
|
1855
|
+
if (techStack && !alreadyInStartupInstructions("Stack", techStack))
|
|
1835
1856
|
summary.push(`- stack: ${techStack}`);
|
|
1836
|
-
if (conventions)
|
|
1857
|
+
if (conventions && !alreadyInStartupInstructions("Conventions", conventions))
|
|
1837
1858
|
summary.push(`- conventions: ${conventions}`);
|
|
1838
|
-
if (build)
|
|
1859
|
+
if (build && !alreadyInStartupInstructions("Build", build))
|
|
1839
1860
|
summary.push(`- build: ${build}`);
|
|
1840
1861
|
if (directives.length > 0) {
|
|
1841
1862
|
const firstDirective = directives[0];
|
|
1842
1863
|
const directive = safeContextSnippet(firstDirective.directive);
|
|
1843
|
-
if (directive)
|
|
1864
|
+
if (directive && !alreadyInStartupInstructions("Directive", directive))
|
|
1844
1865
|
summary.push(`- directive: ${directive}`);
|
|
1845
1866
|
}
|
|
1846
1867
|
if (notes.length > 0) {
|
|
@@ -1867,7 +1888,7 @@ async function buildSessionStartContext(cwd, sessionId, options = {}) {
|
|
|
1867
1888
|
.map((line) => line.trim())
|
|
1868
1889
|
.filter(Boolean)
|
|
1869
1890
|
.join(" ");
|
|
1870
|
-
if (section) {
|
|
1891
|
+
if (section && startupPriority !== section.replace(/\s+/g, " ")) {
|
|
1871
1892
|
sections.push(`[Priority notes]\n- ${section.slice(0, 220)}`);
|
|
1872
1893
|
}
|
|
1873
1894
|
}
|
|
@@ -20952,6 +20973,75 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
20952
20973
|
const cwd = options.cwd ?? (safeString(payload.cwd).trim() || process.cwd());
|
|
20953
20974
|
const reconcileAdvisory = options.reconcileRalplanAdvisoryFn ?? reconcileRalplanAdvisory;
|
|
20954
20975
|
const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
|
|
20976
|
+
if (hookEventName === "SubagentStop") {
|
|
20977
|
+
// This event names the parent session and child agent separately; it is not a leader Stop.
|
|
20978
|
+
const parentSessionId = readStrictStopPayloadSessionId(payload);
|
|
20979
|
+
const agentId = normalizeSessionId(safeString(payload.agent_id).trim());
|
|
20980
|
+
let sessionId = null;
|
|
20981
|
+
let pluginDiscoveryCwd;
|
|
20982
|
+
if (parentSessionId && agentId && agentId !== parentSessionId) {
|
|
20983
|
+
const authoritativeTeamWorker = hasRawTeamWorkerDeclaration()
|
|
20984
|
+
? await resolveAuthoritativeTeamWorkerContext(cwd)
|
|
20985
|
+
: null;
|
|
20986
|
+
if (authoritativeTeamWorker) {
|
|
20987
|
+
// Team workers can own child agents without the shared leader pointer or tracker summary.
|
|
20988
|
+
sessionId = parentSessionId;
|
|
20989
|
+
pluginDiscoveryCwd = authoritativeTeamWorker.canonicalLeaderCwd;
|
|
20990
|
+
}
|
|
20991
|
+
else {
|
|
20992
|
+
const pointer = await readSessionPointer(resolveSessionPointerContext(cwd));
|
|
20993
|
+
if (pointer.status === "usable" && pointer.state && !sessionPointerAliases(pointer.state).has(agentId)) {
|
|
20994
|
+
const candidateSessionId = pointer.state.session_id;
|
|
20995
|
+
const summary = await readSubagentSessionSummary(cwd, candidateSessionId);
|
|
20996
|
+
if (payloadMatchesSessionPointer(parentSessionId, pointer.state)
|
|
20997
|
+
|| summary?.allThreadIds.includes(parentSessionId)) {
|
|
20998
|
+
sessionId = candidateSessionId;
|
|
20999
|
+
}
|
|
21000
|
+
}
|
|
21001
|
+
}
|
|
21002
|
+
}
|
|
21003
|
+
if (sessionId && agentId) {
|
|
21004
|
+
try {
|
|
21005
|
+
await recordSubagentTurnForSessionPartitions(cwd, {
|
|
21006
|
+
sessionId,
|
|
21007
|
+
threadId: agentId,
|
|
21008
|
+
turnId: readPayloadTurnId(payload) || undefined,
|
|
21009
|
+
kind: "subagent",
|
|
21010
|
+
mode: safeString(payload.agent_type).trim() || undefined,
|
|
21011
|
+
completed: true,
|
|
21012
|
+
completionSource: "native_stop_event",
|
|
21013
|
+
});
|
|
21014
|
+
}
|
|
21015
|
+
catch (error) {
|
|
21016
|
+
await logNativeHookCliError(cwd, "native_subagent_completion_tracking_error", error, payload, { agent_id: agentId });
|
|
21017
|
+
return { hookEventName, omxEventName, skillState: null, outputJson: null };
|
|
21018
|
+
}
|
|
21019
|
+
if (!shouldSuppressSubagentLifecycleHookDispatch()) {
|
|
21020
|
+
try {
|
|
21021
|
+
await dispatchHookEventRuntime({
|
|
21022
|
+
event: buildNativeHookEvent(omxEventName, {
|
|
21023
|
+
...buildBaseContext(cwd, payload, hookEventName, sessionId),
|
|
21024
|
+
native_session_id: agentId,
|
|
21025
|
+
codex_session_id: agentId,
|
|
21026
|
+
omx_session_id: sessionId,
|
|
21027
|
+
}, {
|
|
21028
|
+
session_id: sessionId,
|
|
21029
|
+
thread_id: agentId,
|
|
21030
|
+
turn_id: readPayloadTurnId(payload) || undefined,
|
|
21031
|
+
mode: safeString(payload.agent_type).trim() || undefined,
|
|
21032
|
+
}),
|
|
21033
|
+
cwd,
|
|
21034
|
+
...(pluginDiscoveryCwd ? { pluginDiscoveryCwd } : {}),
|
|
21035
|
+
allowTeamWorkerSideEffects: false,
|
|
21036
|
+
});
|
|
21037
|
+
}
|
|
21038
|
+
catch (error) {
|
|
21039
|
+
await logNativeHookCliError(cwd, "native_subagent_completion_dispatch_error", error, payload, { agent_id: agentId });
|
|
21040
|
+
}
|
|
21041
|
+
}
|
|
21042
|
+
}
|
|
21043
|
+
return { hookEventName, omxEventName, skillState: null, outputJson: null };
|
|
21044
|
+
}
|
|
20955
21045
|
// #3497 / C1 boundary: documented-leader PreToolUse hard gate removed.
|
|
20956
21046
|
if (hookEventName === "PreToolUse" && safeString(payload.tool_name).trim() === "Bash") {
|
|
20957
21047
|
void payload;
|
|
@@ -21100,7 +21190,18 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
21100
21190
|
// never promote itself into a root/leader session or emit an independent
|
|
21101
21191
|
// session-start notification at session/minimal verbosity.
|
|
21102
21192
|
isSubagentSessionStart = true;
|
|
21103
|
-
if (
|
|
21193
|
+
if (authoritativeTeamWorker && authoritativeWorkerPayloadSessionId === nativeSessionId) {
|
|
21194
|
+
// A Team worker shares the leader pointer but owns its native child tree.
|
|
21195
|
+
// Retain descriptive child records under the transcript's immediate parent
|
|
21196
|
+
// without letting this child inherit the leader's session scope.
|
|
21197
|
+
canonicalSessionId = "";
|
|
21198
|
+
resolvedNativeSessionId = nativeSessionId;
|
|
21199
|
+
skipCanonicalSessionStartContext = true;
|
|
21200
|
+
allowImplicitSessionSideEffects = false;
|
|
21201
|
+
recordedNativeSubagentSessionStart = true;
|
|
21202
|
+
await recordNativeSubagentSessionStart(cwd, subagentSessionStart.parentThreadId, nativeSessionId, subagentSessionStart, transcriptPath, "", "absent", implicatedChildThreadIds);
|
|
21203
|
+
}
|
|
21204
|
+
else if (canonicalSessionId) {
|
|
21104
21205
|
const belongsToCanonicalSession = await nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonicalSessionId, currentSessionState, subagentSessionStart);
|
|
21105
21206
|
if (belongsToCanonicalSession) {
|
|
21106
21207
|
resolvedNativeSessionId = nativeSessionId;
|
|
@@ -21569,6 +21670,8 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
21569
21670
|
&& /^[ \t]*omx[ \t]+cancel\b/.test(readPreToolUseCommand(payload));
|
|
21570
21671
|
if (omxEventName && !bypassGenericPreToolUsePluginDispatch && allowImplicitSessionSideEffects && allowGlobalSideEffects && !skipCanonicalSessionStartContext && !suppressNoisySubagentLifecycleDispatch) {
|
|
21571
21672
|
const baseContext = buildBaseContext(cwd, payload, hookEventName, canonicalSessionId);
|
|
21673
|
+
if (isSubagentStop)
|
|
21674
|
+
baseContext.is_subagent_stop = true;
|
|
21572
21675
|
if (resolvedNativeSessionId) {
|
|
21573
21676
|
baseContext.native_session_id = resolvedNativeSessionId;
|
|
21574
21677
|
baseContext.codex_session_id = resolvedNativeSessionId;
|
|
@@ -21585,6 +21688,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
21585
21688
|
await dispatchHookEventRuntime({
|
|
21586
21689
|
event,
|
|
21587
21690
|
cwd,
|
|
21691
|
+
pluginDiscoveryCwd: authoritativeTeamWorkerEvidence?.canonicalLeaderCwd,
|
|
21588
21692
|
allowTeamWorkerSideEffects: false,
|
|
21589
21693
|
});
|
|
21590
21694
|
}
|
|
@@ -21730,6 +21834,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
21730
21834
|
await recordSubagentTurnForSession(cwd, {
|
|
21731
21835
|
sessionId: canonicalSessionId.trim(),
|
|
21732
21836
|
threadId: threadId.trim(),
|
|
21837
|
+
turnId: readPayloadTurnId(payload) || undefined,
|
|
21733
21838
|
completed: true,
|
|
21734
21839
|
completionSource: 'native_stop_event',
|
|
21735
21840
|
timestamp: new Date().toISOString(),
|
|
@@ -21832,8 +21937,10 @@ async function readStdinJson() {
|
|
|
21832
21937
|
};
|
|
21833
21938
|
}
|
|
21834
21939
|
}
|
|
21835
|
-
function inferHookEventNameFromMalformedInput(raw) {
|
|
21836
|
-
|
|
21940
|
+
function inferHookEventNameFromMalformedInput(raw, rawHookEventName) {
|
|
21941
|
+
if (rawHookEventName)
|
|
21942
|
+
return rawHookEventName;
|
|
21943
|
+
const match = raw.match(/(?:\"|['"])?hook[_-]?event[_-]?name(?:\"|['"])?\s*:\s*(?:\"|['"])?(SessionStart|PreToolUse|PostToolUse|UserPromptSubmit|PreCompact|PostCompact|SubagentStop|Stop)\b/i);
|
|
21837
21944
|
const value = match?.[1];
|
|
21838
21945
|
if (!value)
|
|
21839
21946
|
return null;
|
|
@@ -21849,13 +21956,15 @@ function buildUnparseablePreToolUseDenyOutput(reason, systemMessage) {
|
|
|
21849
21956
|
},
|
|
21850
21957
|
};
|
|
21851
21958
|
}
|
|
21852
|
-
function buildMalformedStdinHookOutput(parseError, rawInput, cwd = process.cwd()) {
|
|
21959
|
+
function buildMalformedStdinHookOutput(parseError, rawInput, cwd = process.cwd(), rawHookEventName) {
|
|
21853
21960
|
const reason = "OMX native hook received malformed JSON input. Preserve runtime state, inspect the emitting hook payload yourself, and retry with valid JSON.";
|
|
21854
21961
|
const systemMessage = `${reason} stdin JSON parsing failed inside codex-native-hook: ${parseError.message}.`;
|
|
21855
|
-
const inferredHookEventName = inferHookEventNameFromMalformedInput(rawInput);
|
|
21962
|
+
const inferredHookEventName = inferHookEventNameFromMalformedInput(rawInput, rawHookEventName);
|
|
21856
21963
|
if (inferredHookEventName === "PreToolUse") {
|
|
21857
21964
|
return buildUnparseablePreToolUseDenyOutput(reason, systemMessage);
|
|
21858
21965
|
}
|
|
21966
|
+
if (inferredHookEventName === "SubagentStop")
|
|
21967
|
+
return {};
|
|
21859
21968
|
if (inferredHookEventName === "Stop" || (!inferredHookEventName && hasNativeStopRuntimeSurface(cwd))) {
|
|
21860
21969
|
return {
|
|
21861
21970
|
decision: "block",
|
|
@@ -21895,6 +22004,8 @@ function buildOversizedStopInactiveWorkflowOutput() {
|
|
|
21895
22004
|
}
|
|
21896
22005
|
async function buildOversizedStdinHookOutput(rawHookEventName, cwd) {
|
|
21897
22006
|
const systemMessage = `OMX native hook rejected oversized stdin JSON before parsing; maxBytes=${MAX_NATIVE_STDIN_JSON_BYTES}.`;
|
|
22007
|
+
if (rawHookEventName === "SubagentStop")
|
|
22008
|
+
return {};
|
|
21898
22009
|
if (rawHookEventName === "PreToolUse") {
|
|
21899
22010
|
return buildUnparseablePreToolUseDenyOutput(systemMessage, systemMessage);
|
|
21900
22011
|
}
|
|
@@ -21974,7 +22085,7 @@ export async function runCodexNativeHookCli() {
|
|
|
21974
22085
|
}
|
|
21975
22086
|
if (parseError) {
|
|
21976
22087
|
await logNativeHookCliError(process.cwd(), "native_hook_stdin_parse_error", parseError, {}, buildRawInputLogFields(rawInput));
|
|
21977
|
-
writeNativeHookJsonStdout(buildMalformedStdinHookOutput(parseError, rawInput, process.cwd()));
|
|
22088
|
+
writeNativeHookJsonStdout(buildMalformedStdinHookOutput(parseError, rawInput, process.cwd(), rawHookEventName));
|
|
21978
22089
|
return;
|
|
21979
22090
|
}
|
|
21980
22091
|
try {
|