@zaip-ai/cli 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +11 -6
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/codex-config-template.d.ts +2 -2
- package/dist/services/codex-config-template.d.ts.map +1 -1
- package/dist/services/codex-config-template.js +4 -3
- package/dist/services/codex-config-template.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +10 -11
- package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.test.d.ts +2 -0
- package/dist/services/codex-pre-tool-hook-template.test.d.ts.map +1 -0
- package/dist/services/codex-pre-tool-hook-template.test.js +33 -0
- package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -0
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +3 -0
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/codex-windows-hook-command.d.ts +3 -0
- package/dist/services/codex-windows-hook-command.d.ts.map +1 -0
- package/dist/services/codex-windows-hook-command.js +10 -0
- package/dist/services/codex-windows-hook-command.js.map +1 -0
- package/dist/services/codex-windows-hook-command.test.d.ts +2 -0
- package/dist/services/codex-windows-hook-command.test.d.ts.map +1 -0
- package/dist/services/codex-windows-hook-command.test.js +44 -0
- package/dist/services/codex-windows-hook-command.test.js.map +1 -0
- package/dist/services/global-codex-config.d.ts.map +1 -1
- package/dist/services/global-codex-config.js +27 -13
- package/dist/services/global-codex-config.js.map +1 -1
- package/dist/services/global-codex-config.test.js +27 -2
- package/dist/services/global-codex-config.test.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/config/agents/discovery.json +1 -1
- package/templates/.agents/dashboard/.zaip-managed.json +11 -11
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/design/.zaip-managed.json +3 -3
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/requirements/autonomous-assurance.md +1 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +1 -1
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +1 -1
- package/templates/.agents/requirements/execution-engine.md +1 -1
- package/templates/.agents/requirements/kanban-dashboard.md +1 -1
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +1 -1
- package/templates/.agents/requirements/software-architecture.md +1 -1
- package/templates/.agents/requirements/strategic-improvements.md +1 -1
- package/templates/.agents/requirements/work-lifecycle.md +1 -1
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +23 -21
- package/templates/.agents/runtime/checksums.sha256 +5 -5
- package/templates/.agents/runtime/manifest.json +1 -1
- package/templates/.agents/runtime/provenance.json +4 -4
- package/templates/.agents/runtime/sbom.cdx.json +1 -1
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/template-manifest.json +42 -42
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/services/adapters.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,kBAAkB,EAGxB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/services/adapters.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,kBAAkB,EAGxB,MAAM,qBAAqB,CAAC;AAM7B,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAuLD,wBAAgB,YAAY,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,SAAS,WAAW,EAAE,CAqDxB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,CAAC,CAYD;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,UAAQ,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,CAyB7D;AASD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAuBvE"}
|
|
@@ -5,8 +5,9 @@ import { CODEX_CONVERSATION_LIFECYCLE_HOOK, CODEX_PRE_TOOL_HOOK, CODEX_SUBAGENT_
|
|
|
5
5
|
import { codexAgentConfig, parsePublicAgentCatalog, publicAgentAdapterFiles, } from "./agent-adapters.js";
|
|
6
6
|
import { formatAgentDiscovery, serializeAgentDiscovery } from "./agent-discovery.js";
|
|
7
7
|
import { CODEX_GITHUB_DEPLOY_RULES, CODEX_SECURITY_RULES } from "./codex-rules.js";
|
|
8
|
+
import { codexWindowsHookCommand } from "./codex-windows-hook-command.js";
|
|
8
9
|
import { applyTransactionalChanges, assertSafeDestination } from "./transactional-files.js";
|
|
9
|
-
export const ADAPTERS_VERSION = "4.
|
|
10
|
+
export const ADAPTERS_VERSION = "4.1.0";
|
|
10
11
|
const ROOT_GUIDANCE = `# ZAIP-AIOS
|
|
11
12
|
|
|
12
13
|
Read \`.agents/config/project.yaml\` first. Apply ZAIP only for literal boolean \`zaip.enabled: true\`, except framework maintenance or \`zaip enable\`. \`AGENTS.md\` is a bootstrap; canonical guidance lives in \`.agents/\`.
|
|
@@ -121,7 +122,7 @@ matcher = "^(Bash|shell_command|exec_command|apply_patch|Edit|Write)$"
|
|
|
121
122
|
[[hooks.PreToolUse.hooks]]
|
|
122
123
|
type = "command"
|
|
123
124
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-pre-tool-use.mjs"'''
|
|
124
|
-
command_windows = '''
|
|
125
|
+
command_windows = '''__ZAIP_WINDOWS_PRE_TOOL_HOOK__'''
|
|
125
126
|
timeout = 10
|
|
126
127
|
statusMessage = "Applying ZAIP workspace safety policy"
|
|
127
128
|
|
|
@@ -132,7 +133,7 @@ matcher = "*"
|
|
|
132
133
|
type = "command"
|
|
133
134
|
async = false
|
|
134
135
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-conversation-lifecycle.mjs"'''
|
|
135
|
-
command_windows = '''
|
|
136
|
+
command_windows = '''__ZAIP_WINDOWS_CONVERSATION_HOOK__'''
|
|
136
137
|
timeout = 10
|
|
137
138
|
statusMessage = "Reconciling ZAIP task closure and telemetry"
|
|
138
139
|
|
|
@@ -155,7 +156,7 @@ matcher = "*"
|
|
|
155
156
|
[[hooks.SubagentStart.hooks]]
|
|
156
157
|
type = "command"
|
|
157
158
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-subagent-lifecycle.mjs"'''
|
|
158
|
-
command_windows = '''
|
|
159
|
+
command_windows = '''__ZAIP_WINDOWS_SUBAGENT_HOOK__'''
|
|
159
160
|
timeout = 3
|
|
160
161
|
statusMessage = "Attributing ZAIP subagent Run"
|
|
161
162
|
|
|
@@ -165,7 +166,7 @@ matcher = "*"
|
|
|
165
166
|
[[hooks.SubagentStop.hooks]]
|
|
166
167
|
type = "command"
|
|
167
168
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-subagent-lifecycle.mjs"'''
|
|
168
|
-
command_windows = '''
|
|
169
|
+
command_windows = '''__ZAIP_WINDOWS_SUBAGENT_HOOK__'''
|
|
169
170
|
timeout = 3
|
|
170
171
|
statusMessage = "Finalizing ZAIP subagent Run"
|
|
171
172
|
`;
|
|
@@ -179,7 +180,11 @@ const CLAUDE_SETTINGS = `{
|
|
|
179
180
|
}
|
|
180
181
|
`;
|
|
181
182
|
export function adapterFiles(workspaceRoot, catalog) {
|
|
182
|
-
const codexConfig = CODEX_CONFIG
|
|
183
|
+
const codexConfig = CODEX_CONFIG
|
|
184
|
+
.replaceAll(CODEX_WORKSPACE_ROOT_PLACEHOLDER, JSON.stringify(resolve(workspaceRoot)))
|
|
185
|
+
.replaceAll("__ZAIP_WINDOWS_PRE_TOOL_HOOK__", codexWindowsHookCommand("zaip-pre-tool-use.mjs", workspaceRoot))
|
|
186
|
+
.replaceAll("__ZAIP_WINDOWS_CONVERSATION_HOOK__", codexWindowsHookCommand("zaip-conversation-lifecycle.mjs", workspaceRoot))
|
|
187
|
+
.replaceAll("__ZAIP_WINDOWS_SUBAGENT_HOOK__", codexWindowsHookCommand("zaip-subagent-lifecycle.mjs", workspaceRoot));
|
|
183
188
|
return [
|
|
184
189
|
...(catalog === undefined
|
|
185
190
|
? []
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/services/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,iCAAiC,EACjC,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,gBAAgB,EAEhB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAE5F,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAOxC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;CAcrB,CAAC;AAEF,SAAS,kBAAkB,CAAC,OAA4B;IACtD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,oBAAoB,CAAC,CAAC;IACvF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,aAAa,CAAC,OAAO,CAC1B,8YAA8Y,EAC9Y,qlCAAqlC,CACtlC,CAAC;AACJ,CAAC;AAED,MAAM,eAAe,GAAG;;;;;;;;;;;;;;CAcvB,CAAC;AAEF,MAAM,+BAA+B,GAAG;;;;CAIvC,CAAC;AAEF,MAAM,gCAAgC,GAAG,8BAA8B,CAAC;AAExE,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;6CAgBwB,gCAAgC
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/services/adapters.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const CODEX_WORKSPACE_ROOT_PLACEHOLDER = "__ZAIP_WORKSPACE_ROOT_TOML__";
|
|
2
|
-
export declare const CODEX_PRE_TOOL_USE_HOOK
|
|
3
|
-
export declare const CODEX_CONFIG
|
|
2
|
+
export declare const CODEX_PRE_TOOL_USE_HOOK: string;
|
|
3
|
+
export declare const CODEX_CONFIG: string;
|
|
4
4
|
//# sourceMappingURL=codex-config-template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-config-template.d.ts","sourceRoot":"","sources":["../../src/services/codex-config-template.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codex-config-template.d.ts","sourceRoot":"","sources":["../../src/services/codex-config-template.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gCAAgC,iCAAiC,CAAC;AAE/E,eAAO,MAAM,uBAAuB,QAQoB,CAAC;AAEzD,eAAO,MAAM,YAAY,QAiGxB,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { codexWindowsHookCommand } from "./codex-windows-hook-command.js";
|
|
1
2
|
export const CODEX_WORKSPACE_ROOT_PLACEHOLDER = "__ZAIP_WORKSPACE_ROOT_TOML__";
|
|
2
3
|
export const CODEX_PRE_TOOL_USE_HOOK = `[[hooks.PreToolUse]]
|
|
3
4
|
matcher = "^(Bash|shell_command|exec_command|apply_patch|Edit|Write)$"
|
|
@@ -5,7 +6,7 @@ matcher = "^(Bash|shell_command|exec_command|apply_patch|Edit|Write)$"
|
|
|
5
6
|
[[hooks.PreToolUse.hooks]]
|
|
6
7
|
type = "command"
|
|
7
8
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-pre-tool-use.mjs"'''
|
|
8
|
-
command_windows = '''
|
|
9
|
+
command_windows = '''${codexWindowsHookCommand("zaip-pre-tool-use.mjs")}'''
|
|
9
10
|
timeout = 10
|
|
10
11
|
statusMessage = "Applying ZAIP workspace safety policy"`;
|
|
11
12
|
export const CODEX_CONFIG = `project_doc_fallback_filenames = ["AGENTS.md"]
|
|
@@ -92,7 +93,7 @@ matcher = "*"
|
|
|
92
93
|
[[hooks.SubagentStart.hooks]]
|
|
93
94
|
type = "command"
|
|
94
95
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-subagent-lifecycle.mjs"'''
|
|
95
|
-
command_windows = '''
|
|
96
|
+
command_windows = '''${codexWindowsHookCommand("zaip-subagent-lifecycle.mjs")}'''
|
|
96
97
|
timeout = 3
|
|
97
98
|
statusMessage = "Attributing ZAIP subagent Run"
|
|
98
99
|
|
|
@@ -102,7 +103,7 @@ matcher = "*"
|
|
|
102
103
|
[[hooks.SubagentStop.hooks]]
|
|
103
104
|
type = "command"
|
|
104
105
|
command = '''node "$(git rev-parse --show-toplevel)/.codex/hooks/zaip-subagent-lifecycle.mjs"'''
|
|
105
|
-
command_windows = '''
|
|
106
|
+
command_windows = '''${codexWindowsHookCommand("zaip-subagent-lifecycle.mjs")}'''
|
|
106
107
|
timeout = 3
|
|
107
108
|
statusMessage = "Finalizing ZAIP subagent Run"
|
|
108
109
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-config-template.js","sourceRoot":"","sources":["../../src/services/codex-config-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gCAAgC,GAAG,8BAA8B,CAAC;AAE/E,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;
|
|
1
|
+
{"version":3,"file":"codex-config-template.js","sourceRoot":"","sources":["../../src/services/codex-config-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,MAAM,CAAC,MAAM,gCAAgC,GAAG,8BAA8B,CAAC;AAE/E,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;uBAMhB,uBAAuB,CAAC,uBAAuB,CAAC;;wDAEf,CAAC;AAEzD,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;6CAgBiB,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+C3E,uBAAuB;;;;;;;;;;;;;;;;;;;;;uBAqBF,uBAAuB,CAAC,6BAA6B,CAAC;;;;;;;;;;uBAUtD,uBAAuB,CAAC,6BAA6B,CAAC;;;CAG5E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-pre-tool-hook-template.d.ts","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"codex-pre-tool-hook-template.d.ts","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,QA8xB/B,CAAC"}
|
|
@@ -10,20 +10,13 @@ const execute = promisify(execFile);
|
|
|
10
10
|
const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
11
11
|
const deletionCommandPattern = /\b(?:Remove-Item|rm|rmdir|rd|del|erase)\b/i;
|
|
12
12
|
const allowedExplicitNetworkHosts = new Set([
|
|
13
|
-
"127.0.0.1",
|
|
14
|
-
"api.github.com",
|
|
15
|
-
"github.com",
|
|
16
|
-
"localhost",
|
|
17
|
-
"objects.githubusercontent.com",
|
|
18
|
-
"::1",
|
|
13
|
+
"127.0.0.1", "api.github.com", "github.com", "localhost", "objects.githubusercontent.com", "::1",
|
|
19
14
|
]);
|
|
20
15
|
const networkClientPattern = /\b(?:curl|wget|Invoke-WebRequest|Invoke-RestMethod|iwr|irm)\b/i;
|
|
21
16
|
const cloudRunnerScript = ".agents/tools/cloud-runner.mjs";
|
|
22
17
|
const cloudContractPath = ".agents/config/autonomous-cloud-contract.json";
|
|
23
18
|
const cloudOperationProviders = new Map([
|
|
24
|
-
["cloudflare:dns:read", "cloudflare"],
|
|
25
|
-
["cloudflare:dns:create", "cloudflare"],
|
|
26
|
-
["cloudflare:dns:edit", "cloudflare"],
|
|
19
|
+
["cloudflare:dns:read", "cloudflare"], ["cloudflare:dns:create", "cloudflare"], ["cloudflare:dns:edit", "cloudflare"],
|
|
27
20
|
["hostinger:vps:read", "hostinger"],
|
|
28
21
|
["hostinger:ssh:read", "hostinger"],
|
|
29
22
|
["hostinger:ssh:configure", "hostinger"],
|
|
@@ -101,7 +94,7 @@ const destructivePatterns = [
|
|
|
101
94
|
reason: "OS persistence and service changes are blocked.",
|
|
102
95
|
},
|
|
103
96
|
{
|
|
104
|
-
pattern: /\b(?:diskpart|
|
|
97
|
+
pattern: /\b(?:diskpart|bcdedit|fsutil|takeown|icacls|Set-Acl|chmod|chown)\b|(?:^|[\s;&|"'(])format(?:\.com)?\b|\bcipher\s+\/w\b/i,
|
|
105
98
|
reason: "Disk, boot, ownership, and access-control changes are blocked.",
|
|
106
99
|
},
|
|
107
100
|
{
|
|
@@ -777,7 +770,13 @@ if (typeof event.cwd !== "string" || !isWithinRepository(event.cwd)) {
|
|
|
777
770
|
deny("Tool execution outside the ZAIP-AIOS repository is blocked.");
|
|
778
771
|
}
|
|
779
772
|
|
|
780
|
-
const
|
|
773
|
+
const toolInput = event?.tool_input;
|
|
774
|
+
const commandFromCmd = toolInput?.cmd;
|
|
775
|
+
const commandFromCommand = toolInput?.command;
|
|
776
|
+
if (typeof commandFromCmd === "string" && typeof commandFromCommand === "string" && commandFromCmd !== commandFromCommand) {
|
|
777
|
+
deny("Conflicting tool commands were rejected.");
|
|
778
|
+
}
|
|
779
|
+
const command = typeof commandFromCmd === "string" ? commandFromCmd : commandFromCommand;
|
|
781
780
|
if (typeof command !== "string") deny("A matched tool call without a command was rejected.");
|
|
782
781
|
|
|
783
782
|
if (requiresOrchestratorRun(event, command) && !(await hasCurrentTaskOrchestratorRun(event))) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-pre-tool-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"codex-pre-tool-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8xB5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-pre-tool-hook-template.test.d.ts","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { afterEach, expect, it } from "vitest";
|
|
6
|
+
import { CODEX_PRE_TOOL_HOOK } from "./codex-pre-tool-hook-template.js";
|
|
7
|
+
const roots = [];
|
|
8
|
+
afterEach(async () => {
|
|
9
|
+
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
10
|
+
});
|
|
11
|
+
it("uses tool_input.cmd, rejects conflicting commands, and keeps read-only git formatting", async () => {
|
|
12
|
+
const root = await mkdtemp(join(tmpdir(), "zaip-cli-pre-tool-"));
|
|
13
|
+
roots.push(root);
|
|
14
|
+
const hookPath = join(root, ".codex", "hooks", "zaip-pre-tool-use.mjs");
|
|
15
|
+
await mkdir(join(root, ".codex", "hooks"), { recursive: true });
|
|
16
|
+
await writeFile(hookPath, CODEX_PRE_TOOL_HOOK);
|
|
17
|
+
const invoke = (tool_input) => spawnSync(process.execPath, [hookPath], {
|
|
18
|
+
cwd: root,
|
|
19
|
+
encoding: "utf8",
|
|
20
|
+
input: JSON.stringify({ cwd: root, tool_name: "exec_command", tool_input }),
|
|
21
|
+
});
|
|
22
|
+
const allowed = invoke({ cmd: "git log -1 --format='%H %s'" });
|
|
23
|
+
expect(allowed.status).toBe(0);
|
|
24
|
+
expect(allowed.stdout).toBe("");
|
|
25
|
+
const denied = invoke({ cmd: "git status", command: "git reset --hard" });
|
|
26
|
+
expect(denied.status).toBe(0);
|
|
27
|
+
expect(JSON.parse(denied.stdout).hookSpecificOutput.permissionDecision).toBe("deny");
|
|
28
|
+
const diskDenied = invoke({ cmd: "format" + " C:" });
|
|
29
|
+
expect(JSON.parse(diskDenied.stdout).hookSpecificOutput.permissionDecision).toBe("deny");
|
|
30
|
+
const nestedDiskDenied = invoke({ cmd: "cmd /c " + "format" + " C:" });
|
|
31
|
+
expect(JSON.parse(nestedDiskDenied.stdout).hookSpecificOutput.permissionDecision).toBe("deny");
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=codex-pre-tool-hook-template.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-pre-tool-hook-template.test.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CODEX_SUBAGENT_LIFECYCLE_HOOK = "import { existsSync } from \"node:fs\";\nimport { promises as fs } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst hookPath = fileURLToPath(import.meta.url);\nconst repositoryRoot = resolve(dirname(hookPath), \"..\", \"..\");\nconst diagnosticPath = resolve(\n repositoryRoot,\n \".agents\",\n \"local\",\n \"hooks\",\n \"subagent-lifecycle.ndjson\",\n);\nconst pendingRoot = resolve(repositoryRoot, \".local\", \"hooks\", \"subagent-pending\");\n\nif (process.argv[2] === \"--capture-runner\") {\n await runCaptureRunner(process.argv[3]);\n process.exit(0);\n}\nif (process.argv[2] === \"--replay-pending\") {\n const files = await fs.readdir(pendingRoot).catch(() => []);\n let replayed = 0;\n for (const file of files.filter((name) => /^[a-f0-9]{64}\\.json$/.test(name)).slice(0, 256)) {\n const path = resolve(pendingRoot, file);\n const receipt = await fs.readFile(path, \"utf8\").then(JSON.parse).catch(() => null);\n if (receipt?.state === \"pending\" && Array.isArray(receipt.capture_arguments)) { await runCaptureRunner(path, true); if (++replayed >= 3) break; }\n }\n process.exit(0);\n}\n\nlet raw = \"\";\nfor await (const chunk of process.stdin) raw += chunk;\n\ntry {\n const event = JSON.parse(raw);\n const cwd = text(event.cwd);\n const scoped = cwd === null ? \"..\" : relative(repositoryRoot, resolve(cwd));\n if (cwd === null || scoped.startsWith(\"..\")) process.exit(0);\n const eventName = text(event.hook_event_name);\n const lifecycleEvent =\n eventName === \"SubagentStart\" ? \"start\" : eventName === \"SubagentStop\" ? \"stop\" : null;\n const session = text(event.session_id);\n const turn = text(event.turn_id);\n const agentId = text(event.agent_id);\n const agentType = text(event.agent_type);\n const model = text(event.model);\n const reasoningEffort = reasoningEffortValue(\n event.model_reasoning_effort ?? event.reasoning_effort,\n );\n const parentAgentId = text(event.parent_agent_id ?? event.parent_id);\n const parentRunId = text(event.parent_run_id ?? event.root_run_id);\n const status = terminalStatus(event.status);\n const required = [lifecycleEvent, session, turn, agentId, agentType];\n if (lifecycleEvent === null) {\n await diagnostic(\"ignored_unrecognized_event\", { eventName });\n process.exit(0);\n }\n const terminalFallback =\n lifecycleEvent === \"stop\" &&\n status !== null &&\n agentId !== null &&\n parentAgentId !== null &&\n parentRunId !== null &&\n (session === null || turn === null);\n if (\n (!terminalFallback && required.some((value) => value === null)) ||\n (lifecycleEvent === \"start\" && model === null) ||\n (lifecycleEvent === \"stop\" && status === null)\n ) {\n await fs.mkdir(pendingRoot, { recursive: true });\n const identity = JSON.stringify({ eventName, session, turn, agentId, agentType, parentAgentId, parentRunId });\n const pending = resolve(pendingRoot, createHash(\"sha256\").update(identity).digest(\"hex\") + \".json\");\n await atomicSave(pending, { schema_version: 1, state: \"pending\", last_error: \"incomplete_host_metadata\", identity: JSON.parse(identity), recovery: \"Capture observed native metadata manually; never infer completed status.\" });\n await diagnostic(\"ignored_incomplete_event\", {\n eventName,\n session,\n turn,\n agentId,\n agentType,\n missing_model: lifecycleEvent === \"start\" && model === null,\n });\n process.exit(0);\n }\n const candidates = [\n resolve(repositoryRoot, \".agents\", \"runtime\", \"bin\", \"zaip.mjs\"),\n resolve(repositoryRoot, \"packages\", \"cli\", \"dist\", \"index.js\"),\n ];\n const cli = candidates.find(existsSync);\n if (cli === undefined) {\n await diagnostic(\"cli_not_found\", { eventName, candidates });\n process.exit(0);\n }\n const captureArguments = terminalFallback\n ? [\n \"subagent\",\n \"capture-terminal\",\n \"--parent-agent-id\",\n parentAgentId,\n \"--parent-run-id\",\n parentRunId,\n \"--agent-id\",\n agentId,\n \"--agent-type\",\n agentType,\n \"--status\",\n status,\n \"--json\",\n ]\n : [\n \"subagent\",\n \"capture\",\n \"--event\",\n lifecycleEvent,\n \"--session\",\n session,\n \"--turn\",\n turn,\n \"--agent-id\",\n agentId,\n \"--agent-type\",\n agentType,\n ...(model === null ? [] : [\"--model\", model]),\n ...(reasoningEffort === null ? [] : [\"--reasoning-effort\", reasoningEffort]),\n ...(parentAgentId === null ? [] : [\"--parent-agent-id\", parentAgentId]),\n ...(lifecycleEvent !== \"stop\" || status === null ? [] : [\"--status\", status]),\n \"--json\",\n ];\n const pending = await persistPending(cli, captureArguments);\n const receipt = await fs.readFile(pending, \"utf8\").then(JSON.parse);\n if (receipt.state !== \"acknowledged\") {\n const runner = spawn(\n process.execPath,\n [hookPath, \"--capture-runner\", pending],\n {\n cwd: repositoryRoot,\n detached: true,\n windowsHide: true,\n stdio: \"ignore\",\n },\n );\n runner.once(\"error\", (error) =>\n diagnostic(\"runner_spawn_failed\", { eventName, error: error.message }),\n );\n runner.unref();\n }\n if (lifecycleEvent === \"start\") {\n process.stdout.write(JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"SubagentStart\",\n additionalContext:\n \"ZAIP Codex delegation policy: a Sub-Run is only a native collaboration subagent. Do not use create_thread or fork_thread as a Sub-Run, fallback, retry, or delegation proof; those create independent chats and require an explicit user request. If native delegation is unavailable, report the limitation rather than create an independent chat. A catalog name, task_name, title, or prompt is not native ancestry. Before retrying the same bounded dispatch, await or reuse its pending native child; capture only ancestry observed from native host spawn/terminal results or SubagentStart/SubagentStop events, and work only as a cataloged zaip-agent-NOME identity. Delegation is recursive; do not use default, worker, explorer, or ad-hoc agent types.\",\n },\n }));\n }\n} catch (error) {\n await diagnostic(\"hook_exception\", {\n error: error instanceof Error ? error.message : String(error),\n });\n}\n\nasync function atomicSave(path, value) {\n const temporary = path + \".tmp-\" + randomUUID();\n await fs.writeFile(temporary, JSON.stringify(value), { flag: \"wx\", mode: 0o600 });\n for (let retry = 0; ; retry++) {\n try { await fs.rename(temporary, path); break; }\n catch (error) { if (![\"EPERM\", \"EACCES\", \"EBUSY\"].includes(error.code) || retry >= 5) throw error; await new Promise(done => setTimeout(done, 20 * (retry + 1))); }\n }\n}\n\nasync function runCaptureRunner(receiptPath, replay = false) {\n if (typeof receiptPath !== \"string\" || dirname(resolve(receiptPath)) !== pendingRoot) return;\n const lockPath = receiptPath + \".lock\";\n let lease;\n try {\n lease = await fs.open(lockPath, \"wx\");\n await lease.writeFile(JSON.stringify({ pid: process.pid }));\n } catch (error) {\n if (error.code !== \"EEXIST\") return;\n const owner = await fs.readFile(lockPath, \"utf8\").then(JSON.parse).catch(() => null);\n if (!Number.isSafeInteger(owner?.pid) || owner.pid <= 0) return;\n try { process.kill(owner.pid, 0); return; } catch (failure) { if (failure.code !== \"ESRCH\") return; }\n // Serialize stale lock recovery so two recovering workers cannot remove a new lease.\n let recovery;\n try { recovery = await fs.open(lockPath + \".recover\", \"wx\"); } catch { return; }\n try {\n const current = await fs.readFile(lockPath, \"utf8\").then(JSON.parse).catch(() => null);\n if (current?.pid !== owner.pid) return;\n await fs.unlink(lockPath);\n lease = await fs.open(lockPath, \"wx\");\n await lease.writeFile(JSON.stringify({ pid: process.pid }));\n } finally { await recovery.close(); await fs.unlink(lockPath + \".recover\").catch(() => {}); }\n if (!lease) return;\n }\n try {\n const receipt = await fs.readFile(receiptPath, \"utf8\").then(JSON.parse);\n if (receipt.schema_version !== 1 || receipt.state === \"acknowledged\" || (!replay && receipt.attempts >= 3)) return;\n const cli = receipt.cli, args = receipt.capture_arguments;\n const allowedCli = [resolve(repositoryRoot, \".agents/runtime/bin/zaip.mjs\"), resolve(repositoryRoot, \"packages/cli/dist/index.js\")];\n if (!allowedCli.includes(cli) || !Array.isArray(args) || !args.every(x => typeof x === \"string\") || args[0] !== \"subagent\" || ![\"capture\", \"capture-terminal\"].includes(args[1])) return;\n const digest = createHash(\"sha256\").update(JSON.stringify({ cli, arguments: args })).digest(\"hex\");\n if (resolve(pendingRoot, digest + \".json\") !== resolve(receiptPath)) return;\n const value = flag => args[args.indexOf(flag) + 1];\n const stop = args[1] === \"capture-terminal\" || value(\"--event\") === \"stop\";\n if (stop && ![\"completed\", \"failed\", \"cancelled\"].includes(value(\"--status\"))) return;\n for (let retry = 0; retry < 3; retry++) {\n receipt.attempts = (receipt.attempts ?? 0) + 1;\n receipt.updated_at = new Date().toISOString();\n await atomicSave(receiptPath, receipt);\n const outcome = await capture(cli, args);\n let result;\n try { result = JSON.parse(outcome.stdout); } catch { result = null; }\n const runId = result?.run?.run_id ?? result?.run?.id;\n const status = result?.status ?? result?.run?.status;\n if (outcome.code === 0 && result?.captured === true && typeof runId === \"string\" && runId.startsWith(\"RUN-\") && (!stop || status === value(\"--status\"))) {\n receipt.state = \"acknowledged\";\n receipt.run_id = runId;\n receipt.acknowledged_at = new Date().toISOString();\n delete receipt.last_error;\n await atomicSave(receiptPath, receipt);\n return;\n }\n receipt.last_error = outcome.error ?? (outcome.code === 0 ? \"capture_not_confirmed\" : \"capture_exit_nonzero\");\n await atomicSave(receiptPath, receipt);\n if (retry < 2) await new Promise(done => setTimeout(done, 250 * (retry + 1)));\n }\n await persistDiagnostic(\"capture_pending\", { receipt: receiptPath, attempts: receipt.attempts, error: receipt.last_error });\n } catch (error) {\n await persistDiagnostic(\"runner_exception\", { error: error instanceof Error ? error.message : String(error) });\n } finally {\n await lease?.close();\n await fs.unlink(lockPath).catch(() => {});\n }\n}\n\nasync function capture(cli, args) {\n const child = spawn(process.execPath, [cli, ...args], { cwd: repositoryRoot, windowsHide: true, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\", overflow = false;\n child.stdout.on(\"data\", chunk => { stdout += String(chunk); if (stdout.length > 262144) { overflow = true; stdout = \"\"; child.kill(); } });\n child.stderr.resume();\n return await new Promise(done => {\n let settled = false;\n const finish = result => { if (settled) return; settled = true; clearTimeout(timer); done({ ...result, stdout: overflow ? \"\" : stdout }); };\n const timer = setTimeout(() => { child.kill(); finish({ error: \"capture_timeout\" }); }, 15000);\n child.once(\"error\", () => finish({ error: \"capture_spawn_failed\" }));\n child.once(\"close\", code => finish({ code }));\n });\n}\n\nasync function persistPending(cli, captureArguments) {\n const identity = JSON.stringify({ cli, arguments: captureArguments });\n const digest = createHash(\"sha256\").update(identity).digest(\"hex\");\n const path = resolve(pendingRoot, digest + \".json\");\n await fs.mkdir(pendingRoot, { recursive: true });\n const receipt = { schema_version: 1, state: \"pending\", cli, capture_arguments: captureArguments, attempts: 0, created_at: new Date().toISOString() };\n // Publish a complete immutable initial receipt without overwriting another worker's acknowledgement.\n const temporary = path + \".tmp-\" + randomUUID();\n await fs.writeFile(temporary, JSON.stringify(receipt), { flag: \"wx\", mode: 0o600 });\n try { await fs.link(temporary, path); } catch (error) { if (error.code !== \"EEXIST\") throw error; }\n finally { await fs.unlink(temporary); }\n return path;\n}\n\nasync function persistDiagnostic(code, detail) {\n const line = `${JSON.stringify({\n source: \"zaip-subagent-lifecycle-runner\",\n code,\n occurred_at: new Date().toISOString(),\n detail,\n })}\\n`;\n await fs.mkdir(dirname(diagnosticPath), { recursive: true });\n const size = await fs.stat(diagnosticPath).then((entry) => entry.size).catch(() => 0);\n if (size + Buffer.byteLength(line) > 262_144) {\n await fs.writeFile(diagnosticPath, \"\", \"utf8\");\n }\n await fs.appendFile(diagnosticPath, line, \"utf8\");\n}\n\nasync function diagnostic(code, detail) {\n await persistDiagnostic(code, detail);\n process.stderr.write(\n `${JSON.stringify({ source: \"zaip-subagent-lifecycle\", code, detail })}\\n`,\n );\n}\n\nfunction text(value) {\n if (typeof value !== \"string\") return null;\n const normalized = value.trim();\n return normalized.length > 0 && normalized.length <= 200 ? normalized : null;\n}\n\nfunction reasoningEffortValue(value) {\n const normalized = text(value);\n return [\"low\", \"medium\", \"high\", \"xhigh\"].includes(normalized) ? normalized : null;\n}\n\nfunction terminalStatus(value) {\n const normalized = text(value);\n return [\"completed\", \"failed\", \"cancelled\"].includes(normalized) ? normalized : null;\n}\n";
|
|
1
|
+
export declare const CODEX_SUBAGENT_LIFECYCLE_HOOK = "import { existsSync } from \"node:fs\";\nimport { promises as fs } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst hookPath = fileURLToPath(import.meta.url);\nconst repositoryRoot = resolve(dirname(hookPath), \"..\", \"..\");\nconst diagnosticPath = resolve(\n repositoryRoot,\n \".agents\",\n \"local\",\n \"hooks\",\n \"subagent-lifecycle.ndjson\",\n);\nconst pendingRoot = resolve(repositoryRoot, \".local\", \"hooks\", \"subagent-pending\");\n\nif (process.argv[2] === \"--capture-runner\") {\n await runCaptureRunner(process.argv[3]);\n process.exit(0);\n}\nif (process.argv[2] === \"--replay-pending\") {\n const files = await fs.readdir(pendingRoot).catch(() => []);\n let replayed = 0;\n for (const file of files.filter((name) => /^[a-f0-9]{64}\\.json$/.test(name)).slice(0, 256)) {\n const path = resolve(pendingRoot, file);\n const receipt = await fs.readFile(path, \"utf8\").then(JSON.parse).catch(() => null);\n if (receipt?.state === \"pending\" && Array.isArray(receipt.capture_arguments)) { await runCaptureRunner(path, true); if (++replayed >= 3) break; }\n }\n process.exit(0);\n}\n\nlet raw = \"\";\nfor await (const chunk of process.stdin) raw += chunk;\n\ntry {\n const event = JSON.parse(raw);\n const cwd = text(event.cwd);\n const scoped = cwd === null ? \"..\" : relative(repositoryRoot, resolve(cwd));\n if (cwd === null || scoped.startsWith(\"..\")) process.exit(0);\n const eventName = text(event.hook_event_name);\n const lifecycleEvent =\n eventName === \"SubagentStart\" ? \"start\" : eventName === \"SubagentStop\" ? \"stop\" : null;\n const session = text(event.session_id);\n const turn = text(event.turn_id);\n const agentId = text(event.agent_id);\n const agentType = text(event.agent_type);\n const model = text(event.model);\n const reasoningEffort = reasoningEffortValue(\n event.model_reasoning_effort ?? event.reasoning_effort,\n );\n const parentAgentId = text(event.parent_agent_id ?? event.parent_id);\n const parentRunId = text(event.parent_run_id ?? event.root_run_id);\n const status = terminalStatus(event.status);\n const required = [lifecycleEvent, session, turn, agentId, agentType];\n if (lifecycleEvent === null) {\n await diagnostic(\"ignored_unrecognized_event\", { eventName });\n process.exit(0);\n }\n const terminalFallback =\n lifecycleEvent === \"stop\" &&\n status !== null &&\n agentId !== null &&\n parentAgentId !== null &&\n parentRunId !== null &&\n (session === null || turn === null);\n if (\n (!terminalFallback && required.some((value) => value === null)) ||\n (lifecycleEvent === \"start\" && model === null) ||\n (lifecycleEvent === \"stop\" && status === null)\n ) {\n await fs.mkdir(pendingRoot, { recursive: true });\n const identity = JSON.stringify({ eventName, session, turn, agentId, agentType, parentAgentId, parentRunId });\n const pending = resolve(pendingRoot, createHash(\"sha256\").update(identity).digest(\"hex\") + \".json\");\n await atomicSave(pending, { schema_version: 1, state: \"pending\", last_error: \"incomplete_host_metadata\", identity: JSON.parse(identity), recovery: \"Capture observed native metadata manually; never infer completed status.\" });\n await diagnostic(\"ignored_incomplete_event\", {\n eventName,\n session,\n turn,\n agentId,\n agentType,\n missing_model: lifecycleEvent === \"start\" && model === null,\n });\n process.exit(0);\n }\n const candidates = [\n resolve(repositoryRoot, \".agents\", \"runtime\", \"bin\", \"zaip.mjs\"),\n resolve(repositoryRoot, \"packages\", \"cli\", \"dist\", \"index.js\"),\n ];\n const cli = candidates.find(existsSync);\n if (cli === undefined) {\n await diagnostic(\"cli_not_found\", { eventName, candidates });\n process.exit(0);\n }\n const captureArguments = terminalFallback\n ? [\n \"subagent\",\n \"capture-terminal\",\n \"--parent-agent-id\",\n parentAgentId,\n \"--parent-run-id\",\n parentRunId,\n \"--agent-id\",\n agentId,\n \"--agent-type\",\n agentType,\n \"--status\",\n status,\n \"--json\",\n ]\n : [\n \"subagent\",\n \"capture\",\n \"--event\",\n lifecycleEvent,\n \"--session\",\n session,\n \"--turn\",\n turn,\n \"--agent-id\",\n agentId,\n \"--agent-type\",\n agentType,\n ...(model === null ? [] : [\"--model\", model]),\n ...(reasoningEffort === null ? [] : [\"--reasoning-effort\", reasoningEffort]),\n ...(parentAgentId === null ? [] : [\"--parent-agent-id\", parentAgentId]),\n ...(lifecycleEvent !== \"stop\" || status === null ? [] : [\"--status\", status]),\n \"--json\",\n ];\n const pending = await persistPending(cli, captureArguments);\n const receipt = await fs.readFile(pending, \"utf8\").then(JSON.parse);\n if (receipt.state !== \"acknowledged\") {\n const runner = spawn(\n process.execPath,\n [hookPath, \"--capture-runner\", pending],\n {\n cwd: repositoryRoot,\n detached: true,\n windowsHide: true,\n stdio: \"ignore\",\n },\n );\n runner.once(\"error\", (error) =>\n diagnostic(\"runner_spawn_failed\", { eventName, error: error.message }),\n );\n runner.unref();\n }\n if (lifecycleEvent === \"start\") {\n process.stdout.write(JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"SubagentStart\",\n additionalContext:\n \"ZAIP Codex delegation policy: a Sub-Run is only a native collaboration subagent. Do not use create_thread or fork_thread as a Sub-Run, fallback, retry, or delegation proof; those create independent chats and require an explicit user request. If native delegation is unavailable, report the limitation rather than create an independent chat. A catalog name, task_name, title, or prompt is not native ancestry. Before retrying the same bounded dispatch, await or reuse its pending native child; capture only ancestry observed from native host spawn/terminal results or SubagentStart/SubagentStop events, and work only as a cataloged zaip-agent-NOME identity. Delegation is recursive; do not use default, worker, explorer, or ad-hoc agent types.\",\n },\n }));\n } else {\n // Codex expects one JSON object on stdout for SubagentStop as well.\n process.stdout.write(JSON.stringify({}));\n }\n} catch (error) {\n await diagnostic(\"hook_exception\", {\n error: error instanceof Error ? error.message : String(error),\n });\n}\n\nasync function atomicSave(path, value) {\n const temporary = path + \".tmp-\" + randomUUID();\n await fs.writeFile(temporary, JSON.stringify(value), { flag: \"wx\", mode: 0o600 });\n for (let retry = 0; ; retry++) {\n try { await fs.rename(temporary, path); break; }\n catch (error) { if (![\"EPERM\", \"EACCES\", \"EBUSY\"].includes(error.code) || retry >= 5) throw error; await new Promise(done => setTimeout(done, 20 * (retry + 1))); }\n }\n}\n\nasync function runCaptureRunner(receiptPath, replay = false) {\n if (typeof receiptPath !== \"string\" || dirname(resolve(receiptPath)) !== pendingRoot) return;\n const lockPath = receiptPath + \".lock\";\n let lease;\n try {\n lease = await fs.open(lockPath, \"wx\");\n await lease.writeFile(JSON.stringify({ pid: process.pid }));\n } catch (error) {\n if (error.code !== \"EEXIST\") return;\n const owner = await fs.readFile(lockPath, \"utf8\").then(JSON.parse).catch(() => null);\n if (!Number.isSafeInteger(owner?.pid) || owner.pid <= 0) return;\n try { process.kill(owner.pid, 0); return; } catch (failure) { if (failure.code !== \"ESRCH\") return; }\n // Serialize stale lock recovery so two recovering workers cannot remove a new lease.\n let recovery;\n try { recovery = await fs.open(lockPath + \".recover\", \"wx\"); } catch { return; }\n try {\n const current = await fs.readFile(lockPath, \"utf8\").then(JSON.parse).catch(() => null);\n if (current?.pid !== owner.pid) return;\n await fs.unlink(lockPath);\n lease = await fs.open(lockPath, \"wx\");\n await lease.writeFile(JSON.stringify({ pid: process.pid }));\n } finally { await recovery.close(); await fs.unlink(lockPath + \".recover\").catch(() => {}); }\n if (!lease) return;\n }\n try {\n const receipt = await fs.readFile(receiptPath, \"utf8\").then(JSON.parse);\n if (receipt.schema_version !== 1 || receipt.state === \"acknowledged\" || (!replay && receipt.attempts >= 3)) return;\n const cli = receipt.cli, args = receipt.capture_arguments;\n const allowedCli = [resolve(repositoryRoot, \".agents/runtime/bin/zaip.mjs\"), resolve(repositoryRoot, \"packages/cli/dist/index.js\")];\n if (!allowedCli.includes(cli) || !Array.isArray(args) || !args.every(x => typeof x === \"string\") || args[0] !== \"subagent\" || ![\"capture\", \"capture-terminal\"].includes(args[1])) return;\n const digest = createHash(\"sha256\").update(JSON.stringify({ cli, arguments: args })).digest(\"hex\");\n if (resolve(pendingRoot, digest + \".json\") !== resolve(receiptPath)) return;\n const value = flag => args[args.indexOf(flag) + 1];\n const stop = args[1] === \"capture-terminal\" || value(\"--event\") === \"stop\";\n if (stop && ![\"completed\", \"failed\", \"cancelled\"].includes(value(\"--status\"))) return;\n for (let retry = 0; retry < 3; retry++) {\n receipt.attempts = (receipt.attempts ?? 0) + 1;\n receipt.updated_at = new Date().toISOString();\n await atomicSave(receiptPath, receipt);\n const outcome = await capture(cli, args);\n let result;\n try { result = JSON.parse(outcome.stdout); } catch { result = null; }\n const runId = result?.run?.run_id ?? result?.run?.id;\n const status = result?.status ?? result?.run?.status;\n if (outcome.code === 0 && result?.captured === true && typeof runId === \"string\" && runId.startsWith(\"RUN-\") && (!stop || status === value(\"--status\"))) {\n receipt.state = \"acknowledged\";\n receipt.run_id = runId;\n receipt.acknowledged_at = new Date().toISOString();\n delete receipt.last_error;\n await atomicSave(receiptPath, receipt);\n return;\n }\n receipt.last_error = outcome.error ?? (outcome.code === 0 ? \"capture_not_confirmed\" : \"capture_exit_nonzero\");\n await atomicSave(receiptPath, receipt);\n if (retry < 2) await new Promise(done => setTimeout(done, 250 * (retry + 1)));\n }\n await persistDiagnostic(\"capture_pending\", { receipt: receiptPath, attempts: receipt.attempts, error: receipt.last_error });\n } catch (error) {\n await persistDiagnostic(\"runner_exception\", { error: error instanceof Error ? error.message : String(error) });\n } finally {\n await lease?.close();\n await fs.unlink(lockPath).catch(() => {});\n }\n}\n\nasync function capture(cli, args) {\n const child = spawn(process.execPath, [cli, ...args], { cwd: repositoryRoot, windowsHide: true, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\", overflow = false;\n child.stdout.on(\"data\", chunk => { stdout += String(chunk); if (stdout.length > 262144) { overflow = true; stdout = \"\"; child.kill(); } });\n child.stderr.resume();\n return await new Promise(done => {\n let settled = false;\n const finish = result => { if (settled) return; settled = true; clearTimeout(timer); done({ ...result, stdout: overflow ? \"\" : stdout }); };\n const timer = setTimeout(() => { child.kill(); finish({ error: \"capture_timeout\" }); }, 15000);\n child.once(\"error\", () => finish({ error: \"capture_spawn_failed\" }));\n child.once(\"close\", code => finish({ code }));\n });\n}\n\nasync function persistPending(cli, captureArguments) {\n const identity = JSON.stringify({ cli, arguments: captureArguments });\n const digest = createHash(\"sha256\").update(identity).digest(\"hex\");\n const path = resolve(pendingRoot, digest + \".json\");\n await fs.mkdir(pendingRoot, { recursive: true });\n const receipt = { schema_version: 1, state: \"pending\", cli, capture_arguments: captureArguments, attempts: 0, created_at: new Date().toISOString() };\n // Publish a complete immutable initial receipt without overwriting another worker's acknowledgement.\n const temporary = path + \".tmp-\" + randomUUID();\n await fs.writeFile(temporary, JSON.stringify(receipt), { flag: \"wx\", mode: 0o600 });\n try { await fs.link(temporary, path); } catch (error) { if (error.code !== \"EEXIST\") throw error; }\n finally { await fs.unlink(temporary); }\n return path;\n}\n\nasync function persistDiagnostic(code, detail) {\n const line = `${JSON.stringify({\n source: \"zaip-subagent-lifecycle-runner\",\n code,\n occurred_at: new Date().toISOString(),\n detail,\n })}\\n`;\n await fs.mkdir(dirname(diagnosticPath), { recursive: true });\n const size = await fs.stat(diagnosticPath).then((entry) => entry.size).catch(() => 0);\n if (size + Buffer.byteLength(line) > 262_144) {\n await fs.writeFile(diagnosticPath, \"\", \"utf8\");\n }\n await fs.appendFile(diagnosticPath, line, \"utf8\");\n}\n\nasync function diagnostic(code, detail) {\n await persistDiagnostic(code, detail);\n process.stderr.write(\n `${JSON.stringify({ source: \"zaip-subagent-lifecycle\", code, detail })}\\n`,\n );\n}\n\nfunction text(value) {\n if (typeof value !== \"string\") return null;\n const normalized = value.trim();\n return normalized.length > 0 && normalized.length <= 200 ? normalized : null;\n}\n\nfunction reasoningEffortValue(value) {\n const normalized = text(value);\n return [\"low\", \"medium\", \"high\", \"xhigh\"].includes(normalized) ? normalized : null;\n}\n\nfunction terminalStatus(value) {\n const normalized = text(value);\n return [\"completed\", \"failed\", \"cancelled\"].includes(normalized) ? normalized : null;\n}\n";
|
|
2
2
|
//# sourceMappingURL=codex-subagent-hook-template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-subagent-hook-template.d.ts","sourceRoot":"","sources":["../../src/services/codex-subagent-hook-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"codex-subagent-hook-template.d.ts","sourceRoot":"","sources":["../../src/services/codex-subagent-hook-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B,2ybAiTzC,CAAC"}
|
|
@@ -154,6 +154,9 @@ try {
|
|
|
154
154
|
"ZAIP Codex delegation policy: a Sub-Run is only a native collaboration subagent. Do not use create_thread or fork_thread as a Sub-Run, fallback, retry, or delegation proof; those create independent chats and require an explicit user request. If native delegation is unavailable, report the limitation rather than create an independent chat. A catalog name, task_name, title, or prompt is not native ancestry. Before retrying the same bounded dispatch, await or reuse its pending native child; capture only ancestry observed from native host spawn/terminal results or SubagentStart/SubagentStop events, and work only as a cataloged zaip-agent-NOME identity. Delegation is recursive; do not use default, worker, explorer, or ad-hoc agent types.",
|
|
155
155
|
},
|
|
156
156
|
}));
|
|
157
|
+
} else {
|
|
158
|
+
// Codex expects one JSON object on stdout for SubagentStop as well.
|
|
159
|
+
process.stdout.write(JSON.stringify({}));
|
|
157
160
|
}
|
|
158
161
|
} catch (error) {
|
|
159
162
|
await diagnostic("hook_exception", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-subagent-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-subagent-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,6BAA6B,GAAG
|
|
1
|
+
{"version":3,"file":"codex-subagent-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-subagent-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiT5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-windows-hook-command.d.ts","sourceRoot":"","sources":["../../src/services/codex-windows-hook-command.ts"],"names":[],"mappings":"AAEA,wEAAwE;AACxE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAKpF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
/** Encode PowerShell before TOML and cmd.exe parse the hook command. */
|
|
3
|
+
export function codexWindowsHookCommand(hook, workspaceRoot) {
|
|
4
|
+
if (!/^zaip-[a-z-]+\.mjs$/.test(hook))
|
|
5
|
+
throw new Error(`Invalid ZAIP hook name: ${hook}`);
|
|
6
|
+
const literalRoot = workspaceRoot === undefined ? "(Get-Location)" : `'${resolve(workspaceRoot).replaceAll("'", "''")}'`;
|
|
7
|
+
const script = `$git = Join-Path ${literalRoot} '.local\\git\\cmd\\git.exe'; if (!(Test-Path -LiteralPath $git -PathType Leaf)) { $git = (Get-Command git -ErrorAction SilentlyContinue).Source }; if (!$git) { exit 0 }; $root = & $git rev-parse --show-toplevel 2>$null; if ($LASTEXITCODE -ne 0 -or !$root) { exit 0 }; $hook = Join-Path $root '.codex/hooks/${hook}'; if (!(Test-Path -LiteralPath $hook -PathType Leaf)) { exit 0 }; & node $hook; exit $LASTEXITCODE`;
|
|
8
|
+
return `powershell -NoProfile -NonInteractive -EncodedCommand ${Buffer.from(script, "utf16le").toString("base64")}`;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=codex-windows-hook-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-windows-hook-command.js","sourceRoot":"","sources":["../../src/services/codex-windows-hook-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,wEAAwE;AACxE,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,aAAsB;IAC1E,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;IAC1F,MAAM,WAAW,GAAG,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IACzH,MAAM,MAAM,GAAG,oBAAoB,WAAW,sTAAsT,IAAI,qGAAqG,CAAC;IAC9c,OAAO,yDAAyD,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;AACtH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-windows-hook-command.test.d.ts","sourceRoot":"","sources":["../../src/services/codex-windows-hook-command.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { codexWindowsHookCommand } from "./codex-windows-hook-command.js";
|
|
7
|
+
const roots = [];
|
|
8
|
+
afterEach(async () => {
|
|
9
|
+
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
10
|
+
});
|
|
11
|
+
describe.skipIf(process.platform !== "win32")("Codex Windows hook command", () => {
|
|
12
|
+
it("passes stdin and JSON stdout through cmd.exe from a path with spaces", async () => {
|
|
13
|
+
const root = await mkdtemp(join(tmpdir(), "zaip hook workspace "));
|
|
14
|
+
roots.push(root);
|
|
15
|
+
const init = spawnSync("git", ["init", "-q"], { cwd: root, encoding: "utf8" });
|
|
16
|
+
expect(init.status).toBe(0);
|
|
17
|
+
const hooks = join(root, ".codex", "hooks");
|
|
18
|
+
await mkdir(hooks, { recursive: true });
|
|
19
|
+
await writeFile(join(hooks, "zaip-pre-tool-use.mjs"), 'let value = ""; for await (const chunk of process.stdin) value += chunk; process.stdout.write(JSON.stringify({input: JSON.parse(value)}));\n');
|
|
20
|
+
const command = codexWindowsHookCommand("zaip-pre-tool-use.mjs");
|
|
21
|
+
const result = spawnSync("cmd.exe", ["/d", "/s", "/c", command], {
|
|
22
|
+
cwd: root,
|
|
23
|
+
input: JSON.stringify({ hook_event_name: "PreToolUse", tool_input: { cmd: "git status" } }),
|
|
24
|
+
encoding: "utf8",
|
|
25
|
+
});
|
|
26
|
+
expect(result.status).toBe(0);
|
|
27
|
+
expect(JSON.parse(result.stdout)).toEqual({
|
|
28
|
+
input: { hook_event_name: "PreToolUse", tool_input: { cmd: "git status" } },
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
it("exits successfully outside a repository or when its hook is absent", async () => {
|
|
32
|
+
const root = await mkdtemp(join(tmpdir(), "zaip hook absent "));
|
|
33
|
+
roots.push(root);
|
|
34
|
+
const command = codexWindowsHookCommand("zaip-subagent-lifecycle.mjs");
|
|
35
|
+
const result = spawnSync("cmd.exe", ["/d", "/s", "/c", command], {
|
|
36
|
+
cwd: root,
|
|
37
|
+
input: "{}",
|
|
38
|
+
encoding: "utf8",
|
|
39
|
+
});
|
|
40
|
+
expect(result.status).toBe(0);
|
|
41
|
+
expect(result.stdout).toBe("");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=codex-windows-hook-command.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-windows-hook-command.test.js","sourceRoot":"","sources":["../../src/services/codex-windows-hook-command.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,MAAM,KAAK,GAAa,EAAE,CAAC;AAC3B,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC/E,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,MAAM,SAAS,CACb,IAAI,CAAC,KAAK,EAAE,uBAAuB,CAAC,EACpC,8IAA8I,CAC/I,CAAC;QACF,MAAM,OAAO,GAAG,uBAAuB,CAAC,uBAAuB,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;YAC/D,GAAG,EAAE,IAAI;YACT,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,CAAC;YAC3F,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YACxC,KAAK,EAAE,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE;SAC5E,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,uBAAuB,CAAC,6BAA6B,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;YAC/D,GAAG,EAAE,IAAI;YACT,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"global-codex-config.d.ts","sourceRoot":"","sources":["../../src/services/global-codex-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAM1E,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,EAAE,EAAE,OAAO,EAAE,CAAC;IACd,SAAS,EAAE,OAAO,SAAS,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"global-codex-config.d.ts","sourceRoot":"","sources":["../../src/services/global-codex-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAM1E,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,EAAE,EAAE,OAAO,EAAE,CAAC;IACd,SAAS,EAAE,OAAO,SAAS,CAAC;CAC7B;AAgBD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,SAAS,SAAsD,EAC/D,UAAU,SAAiD,EAC3D,UAAU,GAAE,2BAA4C,GACvD,OAAO,CAAC,uBAAuB,CAAC,CAuClC;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAY1D;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,gBAAgB,GAAE,SAAS,MAAM,EAAO,GACvC;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CASA"}
|
|
@@ -6,11 +6,15 @@ import { CODEX_PRE_TOOL_USE_HOOK } from "./codex-config-template.js";
|
|
|
6
6
|
const nodeFileSystem = { mkdir, readFile, rename, rm, writeFile };
|
|
7
7
|
const ANY_TOML_TABLE = /^\[\[?[^\]\r\n]+\]\]?(?:\r?\n|$)/;
|
|
8
8
|
const AGENT_TABLE = /^\[agents\."([^"]+)"\](?:\r?\n|$)/;
|
|
9
|
-
const
|
|
10
|
-
const PRE_TOOL_USE_CHILD_TABLE = /^\[\[hooks\.PreToolUse\.[^\]]+\]\](?:\r?\n|$)/;
|
|
9
|
+
const HOOK_TABLE = /^\[\[hooks\.(PreToolUse|Stop|SubagentStart|SubagentStop)\]\](?:\r?\n|$)/;
|
|
11
10
|
const ZAIP_HOOK_SIGNATURES = [
|
|
12
11
|
".codex/hooks/zaip-pre-tool-use.mjs",
|
|
12
|
+
".codex/hooks/zaip-conversation-lifecycle.mjs",
|
|
13
|
+
".codex/hooks/zaip-subagent-lifecycle.mjs",
|
|
13
14
|
'statusMessage = "Applying ZAIP workspace safety policy"',
|
|
15
|
+
'statusMessage = "Reconciling ZAIP task closure and telemetry"',
|
|
16
|
+
'statusMessage = "Attributing ZAIP subagent Run"',
|
|
17
|
+
'statusMessage = "Finalizing ZAIP subagent Run"',
|
|
14
18
|
];
|
|
15
19
|
/**
|
|
16
20
|
* Removes only catalog-declared legacy Codex identity aliases and installs the
|
|
@@ -59,7 +63,7 @@ export async function reconcileGlobalCodexConfig(codexHome = process.env.CODEX_H
|
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
export function installSecurityHook(config) {
|
|
62
|
-
const zaipHookSpans =
|
|
66
|
+
const zaipHookSpans = zaipOwnedHookSpans(config);
|
|
63
67
|
if (zaipHookSpans.length === 1 && normalizeNewlines(config).includes(CODEX_PRE_TOOL_USE_HOOK)) {
|
|
64
68
|
return config;
|
|
65
69
|
}
|
|
@@ -100,7 +104,7 @@ function legacyAgentTableSpans(config, legacyAgentNames) {
|
|
|
100
104
|
}
|
|
101
105
|
return tables.flatMap((table, index) => table.legacy ? [{ start: table.start, end: tables[index + 1]?.start ?? config.length }] : []);
|
|
102
106
|
}
|
|
103
|
-
function
|
|
107
|
+
function zaipOwnedHookSpans(config) {
|
|
104
108
|
const tables = [];
|
|
105
109
|
let offset = 0;
|
|
106
110
|
let inMultilineBasic = false;
|
|
@@ -121,16 +125,26 @@ function zaipSecurityHookSpans(config) {
|
|
|
121
125
|
offset += text.length;
|
|
122
126
|
}
|
|
123
127
|
return tables.flatMap((table, index) => {
|
|
124
|
-
|
|
128
|
+
const eventName = HOOK_TABLE.exec(table.text)?.[1];
|
|
129
|
+
if (eventName === undefined)
|
|
125
130
|
return [];
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
: []
|
|
131
|
+
const childTable = new RegExp(`^\\[\\[hooks\\.${eventName}\\.[^\\]]+\\]\\]`);
|
|
132
|
+
let boundary = index + 1;
|
|
133
|
+
while (boundary < tables.length && childTable.test(tables[boundary].text))
|
|
134
|
+
boundary += 1;
|
|
135
|
+
const end = tables[boundary]?.start ?? config.length;
|
|
136
|
+
const children = tables.slice(index + 1, boundary).map((child, childIndex, siblings) => ({
|
|
137
|
+
start: child.start,
|
|
138
|
+
end: siblings[childIndex + 1]?.start ?? end,
|
|
139
|
+
}));
|
|
140
|
+
const isZaip = (span) => ZAIP_HOOK_SIGNATURES.some((signature) => config.slice(span.start, span.end).includes(signature));
|
|
141
|
+
if (children.length === 0)
|
|
142
|
+
return isZaip({ start: table.start, end }) ? [{ start: table.start, end }] : [];
|
|
143
|
+
const owned = children.filter(isZaip);
|
|
144
|
+
if (owned.length === children.length)
|
|
145
|
+
return [{ start: table.start, end }];
|
|
146
|
+
// An event can contain user and ZAIP hooks. Keep the event matcher and every user child intact.
|
|
147
|
+
return owned;
|
|
134
148
|
});
|
|
135
149
|
}
|
|
136
150
|
async function catalogedCodexAliases(sourcePath, filesystem) {
|