@pinta-ai/pinta-codex 1.2.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.
Files changed (61) hide show
  1. package/.codex-plugin/plugin.json +40 -0
  2. package/CHANGELOG.md +50 -0
  3. package/LICENSE +136 -0
  4. package/README.md +214 -0
  5. package/dist/core/config.d.ts +10 -0
  6. package/dist/core/config.js +100 -0
  7. package/dist/core/config.js.map +1 -0
  8. package/dist/core/identity.d.ts +1 -0
  9. package/dist/core/identity.js +3 -0
  10. package/dist/core/identity.js.map +1 -0
  11. package/dist/core/otlp.d.ts +57 -0
  12. package/dist/core/otlp.js +182 -0
  13. package/dist/core/otlp.js.map +1 -0
  14. package/dist/core/redact.d.ts +57 -0
  15. package/dist/core/redact.js +149 -0
  16. package/dist/core/redact.js.map +1 -0
  17. package/dist/core/retry-queue.d.ts +26 -0
  18. package/dist/core/retry-queue.js +127 -0
  19. package/dist/core/retry-queue.js.map +1 -0
  20. package/dist/core/trace.d.ts +10 -0
  21. package/dist/core/trace.js +61 -0
  22. package/dist/core/trace.js.map +1 -0
  23. package/dist/core/transport.d.ts +10 -0
  24. package/dist/core/transport.js +77 -0
  25. package/dist/core/transport.js.map +1 -0
  26. package/dist/core/types.d.ts +48 -0
  27. package/dist/core/types.js +45 -0
  28. package/dist/core/types.js.map +1 -0
  29. package/dist/handlers/default.d.ts +6 -0
  30. package/dist/handlers/default.js +11 -0
  31. package/dist/handlers/default.js.map +1 -0
  32. package/dist/handlers/post-tool-use.d.ts +3 -0
  33. package/dist/handlers/post-tool-use.js +15 -0
  34. package/dist/handlers/post-tool-use.js.map +1 -0
  35. package/dist/handlers/pre-tool-use.d.ts +3 -0
  36. package/dist/handlers/pre-tool-use.js +15 -0
  37. package/dist/handlers/pre-tool-use.js.map +1 -0
  38. package/dist/handlers/session.d.ts +3 -0
  39. package/dist/handlers/session.js +15 -0
  40. package/dist/handlers/session.js.map +1 -0
  41. package/dist/handlers/stop.d.ts +3 -0
  42. package/dist/handlers/stop.js +15 -0
  43. package/dist/handlers/stop.js.map +1 -0
  44. package/dist/handlers/user-prompt.d.ts +3 -0
  45. package/dist/handlers/user-prompt.js +15 -0
  46. package/dist/handlers/user-prompt.js.map +1 -0
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.js +53 -0
  49. package/dist/index.js.map +1 -0
  50. package/hooks.json +54 -0
  51. package/package.json +43 -0
  52. package/tools/.data/events.json +1585 -0
  53. package/tools/_lib.ts +274 -0
  54. package/tools/doctor.ts +250 -0
  55. package/tools/install-hooks.ts +71 -0
  56. package/tools/mock-server.ts +436 -0
  57. package/tools/setup.ts +288 -0
  58. package/tools/test-otlp.ts +58 -0
  59. package/tools/test-redact.ts +286 -0
  60. package/tools/tsconfig.json +13 -0
  61. package/tools/uninstall-hooks.ts +39 -0
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transport = void 0;
4
+ const otlp_js_1 = require("./otlp.js");
5
+ const retry_queue_js_1 = require("./retry-queue.js");
6
+ const TIMEOUT_MS = 5000;
7
+ function hintFor(status) {
8
+ if (status === 401 || status === 403)
9
+ return " — check OTEL_EXPORTER_OTLP_HEADERS";
10
+ if (status === 404)
11
+ return " — check OTEL_EXPORTER_OTLP_ENDPOINT path";
12
+ if (status >= 500)
13
+ return " — collector may be down";
14
+ return "";
15
+ }
16
+ class Transport {
17
+ config;
18
+ queue;
19
+ constructor(config) {
20
+ this.config = config;
21
+ this.queue = new retry_queue_js_1.RetryQueue(config.pluginData);
22
+ }
23
+ async send(payload) {
24
+ if (!this.config.endpoint)
25
+ return; // Silent disable
26
+ const ok = await this.post(payload);
27
+ if (!ok)
28
+ this.queue.enqueue(payload);
29
+ }
30
+ async flush() {
31
+ if (!this.config.endpoint)
32
+ return;
33
+ if (!this.queue.tryAcquireLock())
34
+ return;
35
+ try {
36
+ const entries = this.queue.readAll();
37
+ if (entries.length === 0)
38
+ return;
39
+ const merged = (0, otlp_js_1.mergeBatch)(entries.map((e) => e.payload));
40
+ const ok = await this.post(merged);
41
+ if (ok)
42
+ this.queue.rewrite([]);
43
+ }
44
+ finally {
45
+ this.queue.release();
46
+ }
47
+ }
48
+ async post(payload) {
49
+ const ctrl = new AbortController();
50
+ const timer = setTimeout(() => ctrl.abort(), TIMEOUT_MS);
51
+ try {
52
+ const res = await fetch(`${this.config.endpoint}/traces`, {
53
+ method: "POST",
54
+ headers: {
55
+ "Content-Type": "application/json",
56
+ ...this.config.headers,
57
+ },
58
+ body: JSON.stringify(payload),
59
+ signal: ctrl.signal,
60
+ });
61
+ if (!res.ok) {
62
+ process.stderr.write(`[pinta-codex] OTLP ${res.status}${hintFor(res.status)}\n`);
63
+ return false;
64
+ }
65
+ return true;
66
+ }
67
+ catch (err) {
68
+ process.stderr.write(`[pinta-codex] OTLP failed: ${err.message ?? String(err)}\n`);
69
+ return false;
70
+ }
71
+ finally {
72
+ clearTimeout(timer);
73
+ }
74
+ }
75
+ }
76
+ exports.Transport = Transport;
77
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/core/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export interface BaseEvent {
2
+ session_id: string;
3
+ transcript_path: string;
4
+ cwd: string;
5
+ hook_event_name: string;
6
+ turn_id?: string;
7
+ model?: string;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface PreToolUseEvent extends BaseEvent {
11
+ hook_event_name: "PreToolUse";
12
+ tool_name: string;
13
+ tool_input: Record<string, unknown>;
14
+ tool_use_id: string;
15
+ }
16
+ export interface PostToolUseEvent extends BaseEvent {
17
+ hook_event_name: "PostToolUse";
18
+ tool_name: string;
19
+ tool_input: Record<string, unknown>;
20
+ tool_response?: unknown;
21
+ tool_use_id: string;
22
+ }
23
+ export interface UserPromptSubmitEvent extends BaseEvent {
24
+ hook_event_name: "UserPromptSubmit";
25
+ prompt: string;
26
+ }
27
+ export interface SessionEvent extends BaseEvent {
28
+ hook_event_name: "SessionStart";
29
+ source?: "startup" | "resume" | string;
30
+ }
31
+ export interface StopEvent extends BaseEvent {
32
+ hook_event_name: "Stop";
33
+ stop_hook_active?: boolean;
34
+ last_assistant_message?: string;
35
+ }
36
+ export declare function isPreToolUseEvent(event: BaseEvent): event is PreToolUseEvent;
37
+ export declare function isPostToolUseEvent(event: BaseEvent): event is PostToolUseEvent;
38
+ export declare function isUserPromptSubmitEvent(event: BaseEvent): event is UserPromptSubmitEvent;
39
+ export declare function isSessionEvent(event: BaseEvent): event is SessionEvent;
40
+ export declare function isStopEvent(event: BaseEvent): event is StopEvent;
41
+ export declare function isSkippedHook(event: BaseEvent): boolean;
42
+ export interface HookBlockOutput {
43
+ hookSpecificOutput: {
44
+ hookEventName: "PreToolUse";
45
+ permissionDecision: "deny";
46
+ permissionDecisionReason: string;
47
+ };
48
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ // --- Codex hook event types ---
3
+ //
4
+ // Codex fires PascalCase event names identical to Claude Code's hook contract:
5
+ // SessionStart, PreToolUse, PostToolUse, UserPromptSubmit, Stop.
6
+ // PreToolUse / PostToolUse currently fire only for the Bash tool.
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.isPreToolUseEvent = isPreToolUseEvent;
9
+ exports.isPostToolUseEvent = isPostToolUseEvent;
10
+ exports.isUserPromptSubmitEvent = isUserPromptSubmitEvent;
11
+ exports.isSessionEvent = isSessionEvent;
12
+ exports.isStopEvent = isStopEvent;
13
+ exports.isSkippedHook = isSkippedHook;
14
+ // --- Type guards ---
15
+ function isPreToolUseEvent(event) {
16
+ return event.hook_event_name === "PreToolUse";
17
+ }
18
+ function isPostToolUseEvent(event) {
19
+ return event.hook_event_name === "PostToolUse";
20
+ }
21
+ function isUserPromptSubmitEvent(event) {
22
+ return event.hook_event_name === "UserPromptSubmit";
23
+ }
24
+ function isSessionEvent(event) {
25
+ return event.hook_event_name === "SessionStart";
26
+ }
27
+ function isStopEvent(event) {
28
+ return event.hook_event_name === "Stop";
29
+ }
30
+ // --- Skip-list (route to default no-op handler) ---
31
+ //
32
+ // Codex's current hook surface is limited to the five events above. Any other
33
+ // hook name reaches the default handler and exits 0 so unknown/future hooks
34
+ // stay fail-open.
35
+ const KNOWN_HOOKS = new Set([
36
+ "PreToolUse",
37
+ "PostToolUse",
38
+ "SessionStart",
39
+ "UserPromptSubmit",
40
+ "Stop",
41
+ ]);
42
+ function isSkippedHook(event) {
43
+ return !KNOWN_HOOKS.has(event.hook_event_name);
44
+ }
45
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":";AAAA,iCAAiC;AACjC,EAAE;AACF,+EAA+E;AAC/E,iEAAiE;AACjE,kEAAkE;;AA8ClE,8CAEC;AAED,gDAEC;AAED,0DAEC;AAED,wCAEC;AAED,kCAEC;AAeD,sCAEC;AArCD,sBAAsB;AAEtB,SAAgB,iBAAiB,CAAC,KAAgB;IAChD,OAAO,KAAK,CAAC,eAAe,KAAK,YAAY,CAAC;AAChD,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAgB;IACjD,OAAO,KAAK,CAAC,eAAe,KAAK,aAAa,CAAC;AACjD,CAAC;AAED,SAAgB,uBAAuB,CAAC,KAAgB;IACtD,OAAO,KAAK,CAAC,eAAe,KAAK,kBAAkB,CAAC;AACtD,CAAC;AAED,SAAgB,cAAc,CAAC,KAAgB;IAC7C,OAAO,KAAK,CAAC,eAAe,KAAK,cAAc,CAAC;AAClD,CAAC;AAED,SAAgB,WAAW,CAAC,KAAgB;IAC1C,OAAO,KAAK,CAAC,eAAe,KAAK,MAAM,CAAC;AAC1C,CAAC;AAED,qDAAqD;AACrD,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,kBAAkB;AAElB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS;IAClC,YAAY;IACZ,aAAa;IACb,cAAc;IACd,kBAAkB;IAClB,MAAM;CACP,CAAC,CAAC;AACH,SAAgB,aAAa,CAAC,KAAgB;IAC5C,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { BaseEvent } from "../core/types.js";
2
+ /**
3
+ * Catch-all for hooks Codex may add in the future that we do not route yet.
4
+ * Exits 0 silently so unknown hooks stay fail-open.
5
+ */
6
+ export declare function handleDefault(_event: BaseEvent): Promise<number>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleDefault = handleDefault;
4
+ /**
5
+ * Catch-all for hooks Codex may add in the future that we do not route yet.
6
+ * Exits 0 silently so unknown hooks stay fail-open.
7
+ */
8
+ async function handleDefault(_event) {
9
+ return 0;
10
+ }
11
+ //# sourceMappingURL=default.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.js","sourceRoot":"","sources":["../../src/handlers/default.ts"],"names":[],"mappings":";;AAMA,sCAEC;AAND;;;GAGG;AACI,KAAK,UAAU,aAAa,CAAC,MAAiB;IACnD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PintaCodexConfig } from "../core/config.js";
2
+ import type { PostToolUseEvent } from "../core/types.js";
3
+ export declare function handlePostToolUse(event: PostToolUseEvent, config: PintaCodexConfig): Promise<number>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlePostToolUse = handlePostToolUse;
4
+ const transport_js_1 = require("../core/transport.js");
5
+ const trace_js_1 = require("../core/trace.js");
6
+ const otlp_js_1 = require("../core/otlp.js");
7
+ async function handlePostToolUse(event, config) {
8
+ const transport = new transport_js_1.Transport(config);
9
+ await transport.flush();
10
+ const traceId = new trace_js_1.TraceManager(config).currentTrace();
11
+ const payload = (0, otlp_js_1.buildOtlpPayload)({ event, traceId });
12
+ await transport.send(payload);
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=post-tool-use.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-tool-use.js","sourceRoot":"","sources":["../../src/handlers/post-tool-use.ts"],"names":[],"mappings":";;AAMA,8CAUC;AAdD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AAE5C,KAAK,UAAU,iBAAiB,CACrC,KAAuB,EACvB,MAAwB;IAExB,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PintaCodexConfig } from "../core/config.js";
2
+ import type { PreToolUseEvent } from "../core/types.js";
3
+ export declare function handlePreToolUse(event: PreToolUseEvent, config: PintaCodexConfig): Promise<number>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlePreToolUse = handlePreToolUse;
4
+ const transport_js_1 = require("../core/transport.js");
5
+ const trace_js_1 = require("../core/trace.js");
6
+ const otlp_js_1 = require("../core/otlp.js");
7
+ async function handlePreToolUse(event, config) {
8
+ const transport = new transport_js_1.Transport(config);
9
+ await transport.flush();
10
+ const traceId = new trace_js_1.TraceManager(config).currentTrace();
11
+ const payload = (0, otlp_js_1.buildOtlpPayload)({ event, traceId });
12
+ await transport.send(payload);
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=pre-tool-use.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-tool-use.js","sourceRoot":"","sources":["../../src/handlers/pre-tool-use.ts"],"names":[],"mappings":";;AAMA,4CAUC;AAdD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AAE5C,KAAK,UAAU,gBAAgB,CACpC,KAAsB,EACtB,MAAwB;IAExB,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PintaCodexConfig } from "../core/config.js";
2
+ import type { SessionEvent } from "../core/types.js";
3
+ export declare function handleSession(event: SessionEvent, config: PintaCodexConfig): Promise<number>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleSession = handleSession;
4
+ const transport_js_1 = require("../core/transport.js");
5
+ const trace_js_1 = require("../core/trace.js");
6
+ const otlp_js_1 = require("../core/otlp.js");
7
+ async function handleSession(event, config) {
8
+ const transport = new transport_js_1.Transport(config);
9
+ await transport.flush();
10
+ const traceId = new trace_js_1.TraceManager(config).currentTrace();
11
+ const payload = (0, otlp_js_1.buildOtlpPayload)({ event, traceId });
12
+ await transport.send(payload);
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":";;AAMA,sCAUC;AAdD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AAE5C,KAAK,UAAU,aAAa,CACjC,KAAmB,EACnB,MAAwB;IAExB,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PintaCodexConfig } from "../core/config.js";
2
+ import type { StopEvent } from "../core/types.js";
3
+ export declare function handleStop(event: StopEvent, config: PintaCodexConfig): Promise<number>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleStop = handleStop;
4
+ const transport_js_1 = require("../core/transport.js");
5
+ const trace_js_1 = require("../core/trace.js");
6
+ const otlp_js_1 = require("../core/otlp.js");
7
+ async function handleStop(event, config) {
8
+ const transport = new transport_js_1.Transport(config);
9
+ await transport.flush();
10
+ const traceId = new trace_js_1.TraceManager(config).currentTrace();
11
+ const payload = (0, otlp_js_1.buildOtlpPayload)({ event, traceId });
12
+ await transport.send(payload);
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/handlers/stop.ts"],"names":[],"mappings":";;AAMA,gCAUC;AAdD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AAE5C,KAAK,UAAU,UAAU,CAC9B,KAAgB,EAChB,MAAwB;IAExB,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PintaCodexConfig } from "../core/config.js";
2
+ import type { UserPromptSubmitEvent } from "../core/types.js";
3
+ export declare function handleUserPrompt(event: UserPromptSubmitEvent, config: PintaCodexConfig): Promise<number>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleUserPrompt = handleUserPrompt;
4
+ const transport_js_1 = require("../core/transport.js");
5
+ const trace_js_1 = require("../core/trace.js");
6
+ const otlp_js_1 = require("../core/otlp.js");
7
+ async function handleUserPrompt(event, config) {
8
+ const transport = new transport_js_1.Transport(config);
9
+ await transport.flush();
10
+ const traceId = new trace_js_1.TraceManager(config).newTrace(); // NEW trace per user turn
11
+ const payload = (0, otlp_js_1.buildOtlpPayload)({ event, traceId });
12
+ await transport.send(payload);
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=user-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prompt.js","sourceRoot":"","sources":["../../src/handlers/user-prompt.ts"],"names":[],"mappings":";;AAMA,4CAUC;AAdD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AAE5C,KAAK,UAAU,gBAAgB,CACpC,KAA4B,EAC5B,MAAwB;IAExB,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,0BAA0B;IAC/E,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_js_1 = require("./core/config.js");
4
+ const types_js_1 = require("./core/types.js");
5
+ const pre_tool_use_js_1 = require("./handlers/pre-tool-use.js");
6
+ const post_tool_use_js_1 = require("./handlers/post-tool-use.js");
7
+ const user_prompt_js_1 = require("./handlers/user-prompt.js");
8
+ const session_js_1 = require("./handlers/session.js");
9
+ const stop_js_1 = require("./handlers/stop.js");
10
+ const default_js_1 = require("./handlers/default.js");
11
+ async function readStdin() {
12
+ const chunks = [];
13
+ for await (const chunk of process.stdin) {
14
+ chunks.push(chunk);
15
+ }
16
+ return Buffer.concat(chunks).toString("utf-8");
17
+ }
18
+ async function main() {
19
+ let exitCode = 0;
20
+ try {
21
+ const config = (0, config_js_1.loadConfig)();
22
+ const raw = await readStdin();
23
+ const event = JSON.parse(raw);
24
+ if ((0, types_js_1.isSkippedHook)(event)) {
25
+ exitCode = await (0, default_js_1.handleDefault)(event);
26
+ }
27
+ else if ((0, types_js_1.isPreToolUseEvent)(event)) {
28
+ exitCode = await (0, pre_tool_use_js_1.handlePreToolUse)(event, config);
29
+ }
30
+ else if ((0, types_js_1.isPostToolUseEvent)(event)) {
31
+ exitCode = await (0, post_tool_use_js_1.handlePostToolUse)(event, config);
32
+ }
33
+ else if ((0, types_js_1.isUserPromptSubmitEvent)(event)) {
34
+ exitCode = await (0, user_prompt_js_1.handleUserPrompt)(event, config);
35
+ }
36
+ else if ((0, types_js_1.isSessionEvent)(event)) {
37
+ exitCode = await (0, session_js_1.handleSession)(event, config);
38
+ }
39
+ else if ((0, types_js_1.isStopEvent)(event)) {
40
+ exitCode = await (0, stop_js_1.handleStop)(event, config);
41
+ }
42
+ else {
43
+ exitCode = await (0, default_js_1.handleDefault)(event);
44
+ }
45
+ }
46
+ catch (err) {
47
+ process.stderr.write(`[pinta-codex] error: ${err}\n`);
48
+ exitCode = 0; // top-level catch-all stays fail-open per spec §6
49
+ }
50
+ process.exit(exitCode);
51
+ }
52
+ main();
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,gDAA8C;AAC9C,8CAOyB;AAEzB,gEAA8D;AAC9D,kEAAgE;AAChE,8DAA6D;AAC7D,sDAAsD;AACtD,gDAAgD;AAChD,sDAAsD;AAEtD,KAAK,UAAU,SAAS;IACtB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,sBAAU,GAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAc,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEzC,IAAI,IAAA,wBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;YACzB,QAAQ,GAAG,MAAM,IAAA,0BAAa,EAAC,KAAK,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,IAAA,4BAAiB,EAAC,KAAK,CAAC,EAAE,CAAC;YACpC,QAAQ,GAAG,MAAM,IAAA,kCAAgB,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,IAAA,6BAAkB,EAAC,KAAK,CAAC,EAAE,CAAC;YACrC,QAAQ,GAAG,MAAM,IAAA,oCAAiB,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,IAAA,kCAAuB,EAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,QAAQ,GAAG,MAAM,IAAA,iCAAgB,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,IAAA,yBAAc,EAAC,KAAK,CAAC,EAAE,CAAC;YACjC,QAAQ,GAAG,MAAM,IAAA,0BAAa,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,IAAA,sBAAW,EAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,QAAQ,GAAG,MAAM,IAAA,oBAAU,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,MAAM,IAAA,0BAAa,EAAC,KAAK,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAAC;QACtD,QAAQ,GAAG,CAAC,CAAC,CAAC,kDAAkD;IAClE,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED,IAAI,EAAE,CAAC"}
package/hooks.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "node ${CODEX_PLUGIN_ROOT}/dist/index.js"
9
+ }
10
+ ]
11
+ }
12
+ ],
13
+ "UserPromptSubmit": [
14
+ {
15
+ "hooks": [
16
+ {
17
+ "type": "command",
18
+ "command": "node ${CODEX_PLUGIN_ROOT}/dist/index.js"
19
+ }
20
+ ]
21
+ }
22
+ ],
23
+ "PreToolUse": [
24
+ {
25
+ "hooks": [
26
+ {
27
+ "type": "command",
28
+ "command": "node ${CODEX_PLUGIN_ROOT}/dist/index.js"
29
+ }
30
+ ]
31
+ }
32
+ ],
33
+ "PostToolUse": [
34
+ {
35
+ "hooks": [
36
+ {
37
+ "type": "command",
38
+ "command": "node ${CODEX_PLUGIN_ROOT}/dist/index.js"
39
+ }
40
+ ]
41
+ }
42
+ ],
43
+ "Stop": [
44
+ {
45
+ "hooks": [
46
+ {
47
+ "type": "command",
48
+ "command": "node ${CODEX_PLUGIN_ROOT}/dist/index.js"
49
+ }
50
+ ]
51
+ }
52
+ ]
53
+ }
54
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@pinta-ai/pinta-codex",
3
+ "version": "1.2.0",
4
+ "description": "Generic OTLP forwarder for Codex hook events",
5
+ "main": "dist/index.js",
6
+ "license": "SEE LICENSE IN ./LICENSE",
7
+ "author": "Pinta AI (https://pinta.sh)",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/awarecorp/pinta-codex.git"
11
+ },
12
+ "homepage": "https://github.com/awarecorp/pinta-codex",
13
+ "bugs": {
14
+ "url": "https://github.com/awarecorp/pinta-codex/issues"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ ".codex-plugin",
19
+ "hooks.json",
20
+ "tools",
21
+ "LICENSE",
22
+ "README.md",
23
+ "CHANGELOG.md"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "dev": "tsc --watch",
28
+ "setup": "npx tsx tools/setup.ts",
29
+ "doctor": "npx tsx tools/doctor.ts",
30
+ "install-hooks": "npx tsx tools/install-hooks.ts",
31
+ "uninstall-hooks": "npx tsx tools/uninstall-hooks.ts",
32
+ "mock-server": "npx tsx tools/mock-server.ts",
33
+ "test:otlp": "npx tsx tools/test-otlp.ts",
34
+ "test:redact": "npx tsx tools/test-redact.ts",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.0.0",
40
+ "typescript": "^5.7.0",
41
+ "vitest": "^2.1.0"
42
+ }
43
+ }