@cleocode/adapters 2026.10.8 → 2026.10.9

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.
Files changed (32) hide show
  1. package/dist/heavy-command-hook.js +13 -12
  2. package/dist/heavy-command-hook.js.map +1 -1
  3. package/dist/index.js +60 -133
  4. package/dist/index.js.map +2 -2
  5. package/dist/project-hook-delivery.d.ts +6 -0
  6. package/dist/project-hook-delivery.d.ts.map +1 -0
  7. package/dist/project-hook-delivery.js +527 -0
  8. package/dist/project-hook-delivery.js.map +6 -0
  9. package/dist/project-hook-native.d.ts +7 -0
  10. package/dist/project-hook-native.d.ts.map +1 -0
  11. package/dist/project-hook-native.js +84 -0
  12. package/dist/project-hook-native.js.map +6 -0
  13. package/dist/providers/claude-code/hooks.d.ts.map +1 -1
  14. package/dist/providers/codex/hooks.d.ts +5 -4
  15. package/dist/providers/codex/hooks.d.ts.map +1 -1
  16. package/dist/providers/cursor/hooks.d.ts.map +1 -1
  17. package/dist/providers/gemini-cli/hooks.d.ts.map +1 -1
  18. package/dist/providers/opencode/hooks.d.ts.map +1 -1
  19. package/dist/providers/pi/hooks.d.ts.map +1 -1
  20. package/dist/providers/shared/heavy-command-hook-install.d.ts +2 -1
  21. package/dist/providers/shared/heavy-command-hook-install.d.ts.map +1 -1
  22. package/package.json +14 -5
  23. package/src/__tests__/project-hook-delivery.test.ts +319 -0
  24. package/src/project-hook-delivery.ts +532 -0
  25. package/src/project-hook-native.ts +128 -0
  26. package/src/providers/claude-code/hooks.ts +2 -30
  27. package/src/providers/codex/hooks.ts +7 -9
  28. package/src/providers/cursor/hooks.ts +2 -22
  29. package/src/providers/gemini-cli/hooks.ts +2 -12
  30. package/src/providers/opencode/hooks.ts +2 -22
  31. package/src/providers/pi/hooks.ts +2 -26
  32. package/src/providers/shared/heavy-command-hook-install.ts +21 -10
@@ -0,0 +1,6 @@
1
+ import { type ProjectHookDeliveryOptions, type ProjectHookDeliveryResult } from '@cleocode/contracts/project-hook-delivery.js';
2
+ /** Report unsupported bindings even when the same provider delivered other eligible events. */
3
+ export declare function hasUnsupportedProjectHookDelivery(results: readonly ProjectHookDeliveryResult[]): boolean;
4
+ /** Inspect or sync only project-local entries; no provider trust settings are written. */
5
+ export declare function syncProjectHookProviders(options: ProjectHookDeliveryOptions): Promise<ProjectHookDeliveryResult[]>;
6
+ //# sourceMappingURL=project-hook-delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-hook-delivery.d.ts","sourceRoot":"","sources":["../src/project-hook-delivery.ts"],"names":[],"mappings":"AAeA,OAAO,EAGL,KAAK,0BAA0B,EAG/B,KAAK,yBAAyB,EAG/B,MAAM,8CAA8C,CAAC;AAwZtD,+FAA+F;AAC/F,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,SAAS,yBAAyB,EAAE,GAC5C,OAAO,CAUT;AAqCD,0FAA0F;AAC1F,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,EAAE,CAAC,CA8CtC"}
@@ -0,0 +1,527 @@
1
+ // packages/adapters/src/project-hook-delivery.ts
2
+ import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
3
+ import { createHash } from "node:crypto";
4
+ import { existsSync as existsSync2 } from "node:fs";
5
+ import { lstat, realpath, unlink } from "node:fs/promises";
6
+ import { homedir } from "node:os";
7
+ import { dirname as dirname2, isAbsolute as isAbsolute2, join as join2, relative, resolve as resolve2, sep } from "node:path";
8
+ import {
9
+ editJsonConfigFile,
10
+ readManagedJsonConfigFile,
11
+ withFileLock,
12
+ writeFileAtomic
13
+ } from "@cleocode/caamp/atomic";
14
+ import { GENERATED_PROVIDER_HOOK_PROFILES } from "@cleocode/caamp/hooks";
15
+ import {
16
+ ProjectHookDeliveryReceiptSchema
17
+ } from "@cleocode/contracts/project-hook-delivery.js";
18
+
19
+ // packages/adapters/src/providers/shared/heavy-command-hook-install.ts
20
+ import { execFileSync } from "node:child_process";
21
+ import {
22
+ existsSync,
23
+ mkdirSync,
24
+ readdirSync,
25
+ readFileSync,
26
+ realpathSync,
27
+ rmSync,
28
+ statSync,
29
+ writeFileSync
30
+ } from "node:fs";
31
+ import { dirname, isAbsolute, join, resolve } from "node:path";
32
+ import { updateJsonConfigFile } from "@cleocode/caamp";
33
+ var OPENCODE_HEAVY_COMMAND_PLUGIN = "cleo-heavy-command.js";
34
+ var HEAVY_TOOL_WORDS = Object.freeze([
35
+ "vitest",
36
+ "jest",
37
+ "mocha",
38
+ "ava",
39
+ "tap",
40
+ "playwright",
41
+ "pytest",
42
+ "rspec",
43
+ "phpunit",
44
+ "tsc",
45
+ "tsup",
46
+ "turbo",
47
+ "vite",
48
+ "esbuild",
49
+ "webpack",
50
+ "rollup",
51
+ "next",
52
+ "nx",
53
+ "biome",
54
+ "eslint",
55
+ "svelte-check",
56
+ "npm",
57
+ "pnpm",
58
+ "yarn",
59
+ "bun",
60
+ "npx",
61
+ "pnpx",
62
+ "bunx",
63
+ "cargo",
64
+ "go"
65
+ ]);
66
+ var OLDER_CLEO_HOOK_ANSWER = JSON.stringify({
67
+ hookSpecificOutput: {
68
+ hookEventName: "PreToolUse",
69
+ additionalContext: "[cleo] This may be a heavy command, but the cleo on PATH predates cleo hook and cleo run, so it runs outside the machine-wide resource budget. Upgrade CLEO to govern it."
70
+ }
71
+ });
72
+ var HOOK_FILE_EXCLUDE_MARKER = "# cleo-hook: keep a per-machine heavy-command hook file out of git (T13124)";
73
+ var OPENCODE_PLUGIN_FILE = `.opencode/plugins/${OPENCODE_HEAVY_COMMAND_PLUGIN}`;
74
+ function gitOutput(projectDir, args, env = process.env) {
75
+ try {
76
+ return execFileSync("git", ["-C", projectDir, ...args], {
77
+ encoding: "utf-8",
78
+ stdio: ["ignore", "pipe", "ignore"],
79
+ timeout: 5e3,
80
+ env
81
+ }).trim();
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
86
+ function excludeFile(projectDir, env = process.env) {
87
+ if (gitOutput(projectDir, ["rev-parse", "--is-inside-work-tree"], env) !== "true") return null;
88
+ const path = gitOutput(projectDir, ["rev-parse", "--git-path", "info/exclude"], env);
89
+ if (path === null || path === "") return null;
90
+ return isAbsolute(path) ? path : join(projectDir, path);
91
+ }
92
+ function excludeLine(projectDir, relPath, env = process.env) {
93
+ const prefix = gitOutput(projectDir, ["rev-parse", "--show-prefix"], env) ?? "";
94
+ return `/${prefix}${relPath}`;
95
+ }
96
+ function excludeHookFileFromGit(projectDir, relPath, marker = HOOK_FILE_EXCLUDE_MARKER, env = process.env) {
97
+ const exclude = excludeFile(projectDir, env);
98
+ if (exclude === null) return false;
99
+ if (gitOutput(projectDir, ["check-ignore", relPath], env) !== null) return false;
100
+ if (gitOutput(projectDir, ["ls-files", "--error-unmatch", relPath], env) !== null) return false;
101
+ const line = excludeLine(projectDir, relPath, env);
102
+ const text = existsSync(exclude) ? readFileSync(exclude, "utf-8") : "";
103
+ if (text.split("\n").includes(line)) return false;
104
+ const block = `${marker}
105
+ ${line}
106
+ `;
107
+ mkdirSync(dirname(exclude), { recursive: true });
108
+ writeFileSync(exclude, text === "" || text.endsWith("\n") ? text + block : `${text}
109
+ ${block}`);
110
+ return true;
111
+ }
112
+
113
+ // packages/adapters/src/project-hook-delivery.ts
114
+ var MARKER = "# cleo-project-hook:v1";
115
+ var BINARIES = {
116
+ "claude-code": "claude",
117
+ codex: "codex",
118
+ opencode: "opencode",
119
+ kimi: "kimi"
120
+ };
121
+ var hash = (value) => createHash("sha256").update(value).digest("hex");
122
+ var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
123
+ function probeVersion(provider) {
124
+ const binary = BINARIES[provider];
125
+ if (!binary) return void 0;
126
+ try {
127
+ return execFileSync2(binary, ["--version"], {
128
+ encoding: "utf8",
129
+ timeout: 2e3,
130
+ maxBuffer: 8192,
131
+ stdio: ["ignore", "pipe", "ignore"]
132
+ }).match(/\d+\.\d+\.\d+/)?.[0];
133
+ } catch {
134
+ return void 0;
135
+ }
136
+ }
137
+ async function localTarget(root, path) {
138
+ if (await realpath(root) === await realpath(homedir()))
139
+ throw new Error("HOOK_GLOBAL_CONFIG_FORBIDDEN");
140
+ if (isAbsolute2(path) || path.split(/[\\/]/).includes(".."))
141
+ throw new Error("HOOK_CONFIG_PATH_ESCAPE");
142
+ const target = resolve2(root, path);
143
+ let ancestor = target;
144
+ while (!existsSync2(ancestor)) ancestor = dirname2(ancestor);
145
+ const resolved = await realpath(ancestor);
146
+ const rel = relative(await realpath(root), resolved);
147
+ if (rel === ".." || rel.startsWith(".." + sep) || isAbsolute2(rel))
148
+ throw new Error("HOOK_CONFIG_PATH_ESCAPE");
149
+ if (existsSync2(target) && (await lstat(target)).isSymbolicLink())
150
+ throw new Error("HOOK_CONFIG_SYMLINK");
151
+ return target;
152
+ }
153
+ function command(provider, event) {
154
+ const invocation = "cleo hook run --source agent --provider " + provider + " --event " + event;
155
+ return 'if command -v cleo >/dev/null 2>&1 && [ "$(cleo hook run --probe </dev/null 2>/dev/null)" = "CLEO_PROJECT_HOOK_V1" ]; then ' + invocation + '; else printf "%s\\n" "[cleo hook] project runner unavailable; operation allowed. Run cleo doctor hooks." >&2; fi # cleo-hook ' + MARKER;
156
+ }
157
+ function desiredEntries(provider, events) {
158
+ const profile = GENERATED_PROVIDER_HOOK_PROFILES[provider];
159
+ const result = [];
160
+ for (const canonical of new Set(events)) {
161
+ const mapping = Object.entries(profile?.mappings ?? {}).find(
162
+ ([event]) => event === canonical
163
+ )?.[1];
164
+ if (!mapping?.supported || !mapping.nativeName || !/^[A-Za-z][A-Za-z0-9]*$/.test(canonical))
165
+ continue;
166
+ const cmd = command(provider, canonical);
167
+ result.push({
168
+ event: mapping.nativeName,
169
+ command: cmd,
170
+ hash: hash(JSON.stringify(entry(cmd)))
171
+ });
172
+ }
173
+ return result;
174
+ }
175
+ function entry(cmd, timeout = 130) {
176
+ return {
177
+ matcher: "",
178
+ hooks: [{ type: "command", command: cmd, ...timeout === null ? {} : { timeout } }]
179
+ };
180
+ }
181
+ async function receiptAt(path, services) {
182
+ try {
183
+ const info = await lstat(path);
184
+ if (!info.isFile() || info.isSymbolicLink() || info.size > 262144)
185
+ throw new Error("HOOK_RECEIPT_UNSAFE");
186
+ return ProjectHookDeliveryReceiptSchema.parse(
187
+ JSON.parse(await services.readTextFile(path, 262144))
188
+ );
189
+ } catch (error) {
190
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
191
+ throw new Error("HOOK_RECEIPT_INVALID");
192
+ }
193
+ }
194
+ function entryCommand(value) {
195
+ if (!object(value) || !Array.isArray(value.hooks) || value.hooks.length !== 1) return void 0;
196
+ const hook = value.hooks[0];
197
+ return object(hook) && typeof hook.command === "string" ? hook.command : void 0;
198
+ }
199
+ function inspectEntries(config, receipt) {
200
+ const result = [];
201
+ if (!object(config.hooks)) return result;
202
+ for (const [event, entries] of Object.entries(config.hooks)) {
203
+ if (!Array.isArray(entries)) continue;
204
+ for (const [index, value] of entries.entries()) {
205
+ const digest = hash(JSON.stringify(value));
206
+ const owned = receipt?.entries.some((item) => item.event === event && item.hash === digest);
207
+ result.push({
208
+ event,
209
+ index,
210
+ hash: digest,
211
+ owner: owned ? "project" : "unknown",
212
+ provenance: owned ? "cleo-receipt" : "unknown",
213
+ ...owned ? { source: ".cleo/hooks.json" } : {}
214
+ });
215
+ }
216
+ }
217
+ return result;
218
+ }
219
+ function configEdits(config, prior, desired) {
220
+ if (config.hooks !== void 0 && !object(config.hooks))
221
+ throw new Error("HOOK_CONFIG_HOOKS_SHAPE");
222
+ const hooks = object(config.hooks) ? config.hooks : {};
223
+ const edits = [];
224
+ const found = /* @__PURE__ */ new Set();
225
+ const retained = /* @__PURE__ */ new Set();
226
+ for (const [event, entries] of Object.entries(hooks)) {
227
+ if (!Array.isArray(entries)) throw new Error("HOOK_CONFIG_EVENT_SHAPE");
228
+ for (let index = entries.length - 1; index >= 0; index--) {
229
+ const value = entries[index];
230
+ if (value === void 0) continue;
231
+ const cmd = entryCommand(value);
232
+ const owns = prior?.entries.find((old) => old.event === event && old.command === cmd);
233
+ const hasMarker = JSON.stringify(value).includes(MARKER);
234
+ if (!owns && hasMarker) throw new Error("HOOK_CONFIG_UNATTRIBUTED_ENTRY");
235
+ if (!owns) continue;
236
+ if (hash(JSON.stringify(value)) !== owns.hash || found.has(event + ":" + cmd))
237
+ throw new Error("HOOK_CONFIG_MANAGED_DRIFT");
238
+ found.add(event + ":" + cmd);
239
+ if (desired.some((next) => next.event === event && next.hash === owns.hash))
240
+ retained.add(event + ":" + cmd);
241
+ else edits.push({ path: ["hooks", event, index] });
242
+ }
243
+ }
244
+ for (const next of desired) {
245
+ const entries = hooks[next.event];
246
+ if (entries !== void 0 && !Array.isArray(entries))
247
+ throw new Error("HOOK_CONFIG_EVENT_SHAPE");
248
+ if (retained.has(next.event + ":" + next.command)) continue;
249
+ const removals = edits.filter((change) => change.path[1] === next.event).length;
250
+ edits.push(
251
+ Array.isArray(entries) ? {
252
+ path: ["hooks", next.event, entries.length - removals],
253
+ value: entry(next.command),
254
+ insert: true
255
+ } : { path: ["hooks", next.event], value: [entry(next.command)] }
256
+ );
257
+ }
258
+ return edits;
259
+ }
260
+ function pluginSource(events) {
261
+ if (!events.includes("PreToolUse"))
262
+ return "// CLEO project hooks v1; no supported bindings.\nexport default async () => ({});\n";
263
+ return [
264
+ "// CLEO project hooks v1; managed by a local hash receipt.",
265
+ 'import { execFile } from "node:child_process";',
266
+ "export const CleoProjectHooks = async ({directory}) => {",
267
+ " const contexts = new Map();",
268
+ " return {",
269
+ ' "tool.execute.before": async (input, output) => {',
270
+ " const context = await new Promise(done => {",
271
+ ' const child = execFile("cleo", ["hook","run","--source","agent","--provider","opencode","--event","PreToolUse"], {cwd:directory, timeout:130000, maxBuffer:32768}, (error, stdout, stderr) => {',
272
+ ' if(error) {done("CLEO project hook unavailable; operation allowed. Run cleo doctor hooks."); return}',
273
+ ' try {const answer=JSON.parse(stdout || "{}"); done(typeof answer.context === "string" ? answer.context : stderr ? "CLEO project hook infrastructure warning; operation allowed. Run cleo doctor hooks." : "")} catch {done("CLEO project hook response unavailable; operation allowed. Run cleo doctor hooks.")}',
274
+ " });",
275
+ ' child.on("error", () => done("CLEO project hook unavailable; operation allowed. Run cleo doctor hooks."));',
276
+ ' child.stdin?.on("error", () => {}); child.stdin?.end(JSON.stringify({tool_name:input.tool,tool_input:output.args,cwd:directory}));',
277
+ " });",
278
+ " if(context && input.callID) {if(contexts.size >= 128) contexts.delete(contexts.keys().next().value); contexts.set(input.callID, context.slice(0,8192))}",
279
+ " },",
280
+ ' "tool.execute.after": async (input, output) => {',
281
+ " const context=contexts.get(input.callID); contexts.delete(input.callID);",
282
+ ' if(context && typeof output.output === "string") output.output += "\\n\\n" + context;',
283
+ " },",
284
+ " };",
285
+ "};",
286
+ ""
287
+ ].join("\n");
288
+ }
289
+ async function deliverProvider(options, provider) {
290
+ const profile = GENERATED_PROVIDER_HOOK_PROFILES[provider];
291
+ const capability = profile?.projectDelivery;
292
+ const version = probeVersion(provider);
293
+ const result = {
294
+ provider,
295
+ version,
296
+ state: "unsupported",
297
+ capability: version && capability?.verifiedVersions.includes(version) ? "verified" : version && capability?.documentedVersions.includes(version) ? "documented" : "unverified",
298
+ nativeTrust: "unverified",
299
+ provenance: "unknown",
300
+ diagnostics: []
301
+ };
302
+ if (result.capability !== "verified") result.diagnostics.push("HOOK_LIVE_DELIVERY_UNVERIFIED");
303
+ if (!capability?.configPath) {
304
+ result.diagnostics.push("HOOK_PROJECT_LOCAL_UNSUPPORTED");
305
+ return result;
306
+ }
307
+ const configPath = capability.configPath;
308
+ const target = await localTarget(options.projectRoot, configPath);
309
+ result.configPath = target;
310
+ const receiptPath = join2(options.stateDir, "provider-" + provider + ".json");
311
+ const prior = await receiptAt(receiptPath, options.services);
312
+ if (prior && (prior.provider !== provider || prior.configPath !== target))
313
+ throw new Error("HOOK_RECEIPT_PATH_MISMATCH");
314
+ if (prior) {
315
+ const allowed = desiredEntries(provider, Object.keys(profile.mappings));
316
+ for (const [canonical, mapping] of Object.entries(profile.mappings)) {
317
+ if (!mapping?.supported || !mapping.nativeName) continue;
318
+ const former = "cleo hook run --source agent --provider " + provider + " --event " + canonical + " # cleo-hook " + MARKER;
319
+ for (const generated of [former, command(provider, canonical)]) {
320
+ allowed.push({
321
+ event: mapping.nativeName,
322
+ command: generated,
323
+ hash: hash(JSON.stringify(entry(generated, null)))
324
+ });
325
+ }
326
+ }
327
+ const valid = profile.hookSystem === "plugin" ? prior.entries.length === 1 && prior.entries[0]?.event === "plugin" && prior.entries[0]?.command === "cleo hook run" && [pluginSource([]), pluginSource(["PreToolUse"])].some(
328
+ (body) => hash(body) === prior.entries[0]?.hash
329
+ ) : prior.entries.every(
330
+ (item) => allowed.some(
331
+ (candidate) => candidate.event === item.event && candidate.command === item.command && candidate.hash === item.hash
332
+ )
333
+ );
334
+ if (!valid) throw new Error("HOOK_RECEIPT_OWNERSHIP_INVALID");
335
+ result.provenance = "cleo-receipt";
336
+ }
337
+ if (options.events.length === 0 && !prior && !options.rollback) {
338
+ result.state = "unsupported";
339
+ result.diagnostics.push("HOOK_NO_AGENT_BINDINGS");
340
+ return result;
341
+ }
342
+ if (!options.enabled && !options.rollback) {
343
+ result.state = "disabled";
344
+ return result;
345
+ }
346
+ const desired = options.rollback ? [] : desiredEntries(provider, options.events);
347
+ const tracking = spawnSync(
348
+ "git",
349
+ ["-C", options.projectRoot, "ls-files", "--error-unmatch", "--", capability.configPath],
350
+ { timeout: 2e3, stdio: "ignore", env: options.services.gitEnvironment }
351
+ );
352
+ if (tracking.status === 0) {
353
+ result.state = "conflict";
354
+ result.diagnostics.push("HOOK_CONFIG_TRACKED_REVIEW_REQUIRED");
355
+ result.integrationSnippet = JSON.stringify(
356
+ { hooks: Object.fromEntries(desired.map((item) => [item.event, [entry(item.command)]])) },
357
+ null,
358
+ 2
359
+ );
360
+ return result;
361
+ }
362
+ if (tracking.error || tracking.signal || tracking.status !== 1)
363
+ throw new Error("HOOK_GIT_TRACKING_UNVERIFIED");
364
+ for (const event of options.events) {
365
+ if (!desired.some((item) => item.command === command(provider, event)))
366
+ result.diagnostics.push("HOOK_EVENT_UNSUPPORTED:" + event);
367
+ }
368
+ if (profile.hookSystem === "plugin") {
369
+ for (const event of options.events.filter((event2) => event2 !== "PreToolUse"))
370
+ result.diagnostics.push("HOOK_PLUGIN_EVENT_UNSUPPORTED:" + event);
371
+ if (!options.rollback && !options.events.includes("PreToolUse")) {
372
+ result.state = "unsupported";
373
+ return result;
374
+ }
375
+ const body = pluginSource(options.events);
376
+ const existing = existsSync2(target) ? await options.services.readTextFile(target, 262144) : void 0;
377
+ if (existing !== void 0 && (!prior || prior.entries[0]?.hash !== hash(existing))) {
378
+ result.state = "conflict";
379
+ result.diagnostics.push("HOOK_CONFIG_MANAGED_DRIFT");
380
+ return result;
381
+ }
382
+ if (options.rollback) {
383
+ if (existing !== void 0 && !options.dryRun)
384
+ await withFileLock(target, async () => {
385
+ await localTarget(options.projectRoot, configPath);
386
+ const current = existsSync2(target) ? await options.services.readTextFile(target, 262144) : void 0;
387
+ if (current !== existing) throw new Error("HOOK_CONFIG_CONCURRENT_EDIT");
388
+ await unlink(target);
389
+ });
390
+ result.state = "disabled";
391
+ return result;
392
+ }
393
+ result.state = existing === body ? "current" : "planned";
394
+ if (!options.dryRun && existing !== body) {
395
+ if (existing === void 0)
396
+ excludeHookFileFromGit(
397
+ options.projectRoot,
398
+ capability.configPath,
399
+ void 0,
400
+ options.services.gitEnvironment
401
+ );
402
+ await withFileLock(target, async () => {
403
+ await localTarget(options.projectRoot, configPath);
404
+ const current = existsSync2(target) ? await options.services.readTextFile(target, 262144) : void 0;
405
+ if (current !== existing) throw new Error("HOOK_CONFIG_CONCURRENT_EDIT");
406
+ await writeFileAtomic({ path: target, content: body });
407
+ });
408
+ await writeFileAtomic({
409
+ path: receiptPath,
410
+ content: JSON.stringify({
411
+ schemaVersion: 1,
412
+ provider,
413
+ configPath: target,
414
+ entries: [{ event: "plugin", command: "cleo hook run", hash: hash(body) }],
415
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString()
416
+ }) + "\n"
417
+ });
418
+ result.state = "installed";
419
+ result.provenance = "cleo-receipt";
420
+ }
421
+ return result;
422
+ }
423
+ const config = await readManagedJsonConfigFile(target);
424
+ result.entries = inspectEntries(config, prior);
425
+ const edits = configEdits(config, prior, desired);
426
+ result.state = edits.length ? "planned" : "current";
427
+ if (!options.dryRun) {
428
+ if (!existsSync2(target))
429
+ excludeHookFileFromGit(
430
+ options.projectRoot,
431
+ capability.configPath,
432
+ void 0,
433
+ options.services.gitEnvironment
434
+ );
435
+ await editJsonConfigFile(target, (current) => configEdits(current, prior, desired));
436
+ await writeFileAtomic({
437
+ path: receiptPath,
438
+ content: JSON.stringify({
439
+ schemaVersion: 1,
440
+ provider,
441
+ configPath: target,
442
+ entries: desired,
443
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString()
444
+ }) + "\n"
445
+ });
446
+ result.state = edits.length ? "installed" : "current";
447
+ result.provenance = "cleo-receipt";
448
+ result.entries = inspectEntries(
449
+ await readManagedJsonConfigFile(target),
450
+ await receiptAt(receiptPath, options.services)
451
+ );
452
+ }
453
+ return result;
454
+ }
455
+ function hasUnsupportedProjectHookDelivery(results) {
456
+ return results.some(
457
+ (result) => result.state === "unsupported" || result.diagnostics.some(
458
+ (code) => code.startsWith("HOOK_EVENT_UNSUPPORTED:") || code.startsWith("HOOK_PLUGIN_EVENT_UNSUPPORTED:")
459
+ )
460
+ );
461
+ }
462
+ async function validateStateDirectory(options) {
463
+ const gitState = resolve2(
464
+ options.projectRoot,
465
+ execFileSync2(
466
+ "git",
467
+ [
468
+ "-C",
469
+ options.projectRoot,
470
+ "rev-parse",
471
+ "--path-format=absolute",
472
+ "--git-path",
473
+ "cleo-project-hooks"
474
+ ],
475
+ {
476
+ encoding: "utf8",
477
+ timeout: 2e3,
478
+ maxBuffer: 16384,
479
+ stdio: ["ignore", "pipe", "ignore"],
480
+ env: options.services.gitEnvironment
481
+ }
482
+ ).trim()
483
+ );
484
+ const parent = await realpath(dirname2(gitState));
485
+ if (resolve2(options.stateDir) !== gitState || await realpath(dirname2(resolve2(options.stateDir))) !== parent)
486
+ throw new Error("HOOK_STATE_DIRECTORY_INVALID");
487
+ if (existsSync2(gitState) && (!(await lstat(gitState)).isDirectory() || (await lstat(gitState)).isSymbolicLink()))
488
+ throw new Error("HOOK_STATE_DIRECTORY_INVALID");
489
+ }
490
+ async function syncProjectHookProviders(options) {
491
+ const providers = options.providers ?? Object.entries(GENERATED_PROVIDER_HOOK_PROFILES).filter(
492
+ ([id, profile]) => profile.projectDelivery && (probeVersion(id) !== void 0 || profile.projectDelivery.configPath !== null && existsSync2(
493
+ join2(options.projectRoot, profile.projectDelivery.configPath.split("/")[0] ?? "")
494
+ ))
495
+ ).map(([id]) => id);
496
+ const outcomes = [];
497
+ for (const provider of providers) {
498
+ try {
499
+ if (!Object.hasOwn(GENERATED_PROVIDER_HOOK_PROFILES, provider) || !/^[a-z][a-z0-9-]*$/.test(provider))
500
+ throw new Error("HOOK_PROVIDER_INVALID");
501
+ await validateStateDirectory(options);
502
+ outcomes.push(
503
+ options.dryRun ? await deliverProvider(options, provider) : await withFileLock(
504
+ join2(options.stateDir, "provider-" + provider + ".json"),
505
+ () => deliverProvider(options, provider)
506
+ )
507
+ );
508
+ } catch (error) {
509
+ outcomes.push({
510
+ provider,
511
+ state: "conflict",
512
+ capability: "unverified",
513
+ nativeTrust: "unverified",
514
+ provenance: "unknown",
515
+ diagnostics: [
516
+ error instanceof Error && /^HOOK_[A-Z_]+$/.test(error.message) ? error.message : "HOOK_DELIVERY_FAILED"
517
+ ]
518
+ });
519
+ }
520
+ }
521
+ return outcomes;
522
+ }
523
+ export {
524
+ hasUnsupportedProjectHookDelivery,
525
+ syncProjectHookProviders
526
+ };
527
+ //# sourceMappingURL=project-hook-delivery.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/project-hook-delivery.ts", "../src/providers/shared/heavy-command-hook-install.ts"],
4
+ "mappings": "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",
5
+ "names": ["execFileSync", "existsSync", "dirname", "isAbsolute", "join", "resolve", "execFileSync", "isAbsolute", "resolve", "existsSync", "dirname", "join", "event"]
6
+ }
@@ -0,0 +1,7 @@
1
+ import type { ProjectHookNativeRequest, ProjectHookNativeResult } from '@cleocode/contracts/project-hook-delivery.js';
2
+ import type { HookOutcome } from '@cleocode/contracts/project-hooks.js';
3
+ /** Normalize actual Git ref updates or native agent JSON; no Claude environment dependency. */
4
+ export declare function normalizeNativeProjectHook(argv: readonly string[], body: string, cwd: string): ProjectHookNativeRequest;
5
+ /** Produce advisory-only native output; project blocks apply solely to Git. */
6
+ export declare function renderNativeProjectHook(request: ProjectHookNativeRequest, outcomes: HookOutcome[]): ProjectHookNativeResult;
7
+ //# sourceMappingURL=project-hook-native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-hook-native.d.ts","sourceRoot":"","sources":["../src/project-hook-native.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,sCAAsC,CAAC;AAmCvF,+FAA+F;AAC/F,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,wBAAwB,CA+B1B;AAED,+EAA+E;AAC/E,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,EACjC,QAAQ,EAAE,WAAW,EAAE,GACtB,uBAAuB,CA4CzB"}
@@ -0,0 +1,84 @@
1
+ // packages/adapters/src/project-hook-native.ts
2
+ function flag(argv, name) {
3
+ const separator = argv.indexOf("--");
4
+ const options = separator < 0 ? argv : argv.slice(0, separator);
5
+ const index = options.findIndex(
6
+ (arg) => arg === "--" + name || arg.startsWith("--" + name + "=")
7
+ );
8
+ return index < 0 ? void 0 : options[index]?.split("=").slice(1).join("=") || options[index + 1];
9
+ }
10
+ function object(value) {
11
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12
+ }
13
+ function refsFromStdin(body) {
14
+ const refs = [];
15
+ for (const line of body.split(/\r?\n/).filter((line2) => line2.trim())) {
16
+ const fields = line.trim().split(/\s+/);
17
+ const [localRef, localOid, remoteRef, remoteOid] = fields;
18
+ if (fields.length !== 4 || !localRef || !remoteRef || !localOid || !remoteOid || !/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(localOid) || !/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(remoteOid))
19
+ throw new Error("HOOK_GIT_INPUT_INVALID");
20
+ refs.push({ localRef, localOid, remoteRef, remoteOid });
21
+ }
22
+ return refs;
23
+ }
24
+ function normalizeNativeProjectHook(argv, body, cwd) {
25
+ if (Buffer.byteLength(body) > 262144) throw new Error("HOOK_INPUT_TOO_LARGE");
26
+ const source = flag(argv, "source") ?? "agent";
27
+ if (source !== "agent" && source !== "git") throw new Error("HOOK_SOURCE_INVALID");
28
+ const provider = flag(argv, "provider") ?? "claude-code";
29
+ const event = flag(argv, "event") ?? (source === "git" ? "pre-push" : "PreToolUse");
30
+ const separator = argv.indexOf("--");
31
+ if (source === "git")
32
+ return {
33
+ cwd,
34
+ provider,
35
+ input: {
36
+ schemaVersion: 1,
37
+ source,
38
+ event,
39
+ refs: refsFromStdin(body),
40
+ remote: {
41
+ name: flag(argv, "remote-name") ?? (separator < 0 ? "" : argv[separator + 1]) ?? "",
42
+ location: flag(argv, "remote-location") ?? (separator < 0 ? "" : argv[separator + 2]) ?? ""
43
+ }
44
+ }
45
+ };
46
+ const payload = JSON.parse(body || "{}");
47
+ if (!object(payload)) throw new Error("HOOK_AGENT_INPUT_INVALID");
48
+ return {
49
+ cwd: typeof payload.cwd === "string" ? payload.cwd : cwd,
50
+ provider,
51
+ nativeEvent: typeof payload.hook_event_name === "string" ? payload.hook_event_name : event,
52
+ input: { schemaVersion: 1, source, event, toolInput: payload.tool_input ?? {} }
53
+ };
54
+ }
55
+ function renderNativeProjectHook(request, outcomes) {
56
+ const message = outcomes.filter((outcome) => outcome.status !== "pass" && outcome.status !== "skip").map(
57
+ (outcome) => "CLEO project hook " + outcome.id + ": " + outcome.status + " (" + outcome.code + ")" + (outcome.message ? ": " + outcome.message : "")
58
+ ).join("\n").slice(0, 8192);
59
+ if (request.input.source === "agent")
60
+ return {
61
+ exitCode: 0,
62
+ stderr: "",
63
+ stdout: message ? JSON.stringify(
64
+ request.provider === "opencode" ? { context: message } : request.input.event === "PreToolUse" ? {
65
+ hookSpecificOutput: {
66
+ hookEventName: request.nativeEvent ?? request.input.event,
67
+ additionalContext: message
68
+ }
69
+ } : { systemMessage: message }
70
+ ) + "\n" : ""
71
+ };
72
+ return {
73
+ stdout: "",
74
+ stderr: message ? message + "\n" : "",
75
+ exitCode: outcomes.some(
76
+ (outcome) => outcome.blocks && outcome.status !== "infrastructure-error"
77
+ ) ? 1 : 0
78
+ };
79
+ }
80
+ export {
81
+ normalizeNativeProjectHook,
82
+ renderNativeProjectHook
83
+ };
84
+ //# sourceMappingURL=project-hook-native.js.map