@ironbee-ai/cli 0.5.2 → 0.6.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 (159) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/analysis/cross-session.d.ts +1 -1
  4. package/dist/analysis/cross-session.js +1 -1
  5. package/dist/analysis/cross-session.js.map +1 -1
  6. package/dist/analysis/time-analysis.js +3 -3
  7. package/dist/analysis/time-analysis.js.map +1 -1
  8. package/dist/analysis/verdict-details.d.ts +1 -1
  9. package/dist/clients/claude/hooks/clear-verdict.d.ts.map +1 -1
  10. package/dist/clients/claude/hooks/clear-verdict.js +17 -9
  11. package/dist/clients/claude/hooks/clear-verdict.js.map +1 -1
  12. package/dist/clients/claude/hooks/require-verification.d.ts.map +1 -1
  13. package/dist/clients/claude/hooks/require-verification.js +31 -4
  14. package/dist/clients/claude/hooks/require-verification.js.map +1 -1
  15. package/dist/clients/claude/hooks/session-end.d.ts.map +1 -1
  16. package/dist/clients/claude/hooks/session-end.js +6 -1
  17. package/dist/clients/claude/hooks/session-end.js.map +1 -1
  18. package/dist/clients/claude/hooks/session-start.d.ts.map +1 -1
  19. package/dist/clients/claude/hooks/session-start.js +9 -3
  20. package/dist/clients/claude/hooks/session-start.js.map +1 -1
  21. package/dist/clients/claude/hooks/track-action.d.ts +25 -4
  22. package/dist/clients/claude/hooks/track-action.d.ts.map +1 -1
  23. package/dist/clients/claude/hooks/track-action.js +160 -29
  24. package/dist/clients/claude/hooks/track-action.js.map +1 -1
  25. package/dist/clients/claude/hooks/verify-gate.d.ts.map +1 -1
  26. package/dist/clients/claude/hooks/verify-gate.js +5 -0
  27. package/dist/clients/claude/hooks/verify-gate.js.map +1 -1
  28. package/dist/clients/claude/index.d.ts.map +1 -1
  29. package/dist/clients/claude/index.js +18 -1
  30. package/dist/clients/claude/index.js.map +1 -1
  31. package/dist/clients/claude/util.d.ts +74 -0
  32. package/dist/clients/claude/util.d.ts.map +1 -0
  33. package/dist/clients/claude/util.js +352 -0
  34. package/dist/clients/claude/util.js.map +1 -0
  35. package/dist/clients/cursor/hooks/clear-verdict.d.ts.map +1 -1
  36. package/dist/clients/cursor/hooks/clear-verdict.js +19 -10
  37. package/dist/clients/cursor/hooks/clear-verdict.js.map +1 -1
  38. package/dist/clients/cursor/hooks/require-verification.d.ts.map +1 -1
  39. package/dist/clients/cursor/hooks/require-verification.js +28 -4
  40. package/dist/clients/cursor/hooks/require-verification.js.map +1 -1
  41. package/dist/clients/cursor/hooks/session-end.d.ts.map +1 -1
  42. package/dist/clients/cursor/hooks/session-end.js +6 -1
  43. package/dist/clients/cursor/hooks/session-end.js.map +1 -1
  44. package/dist/clients/cursor/hooks/session-start.d.ts.map +1 -1
  45. package/dist/clients/cursor/hooks/session-start.js +7 -2
  46. package/dist/clients/cursor/hooks/session-start.js.map +1 -1
  47. package/dist/clients/cursor/hooks/track-action.d.ts +30 -8
  48. package/dist/clients/cursor/hooks/track-action.d.ts.map +1 -1
  49. package/dist/clients/cursor/hooks/track-action.js +192 -54
  50. package/dist/clients/cursor/hooks/track-action.js.map +1 -1
  51. package/dist/clients/cursor/hooks/verify-gate.d.ts.map +1 -1
  52. package/dist/clients/cursor/hooks/verify-gate.js +4 -0
  53. package/dist/clients/cursor/hooks/verify-gate.js.map +1 -1
  54. package/dist/clients/cursor/index.d.ts.map +1 -1
  55. package/dist/clients/cursor/index.js +13 -2
  56. package/dist/clients/cursor/index.js.map +1 -1
  57. package/dist/clients/cursor/util.d.ts +52 -0
  58. package/dist/clients/cursor/util.d.ts.map +1 -0
  59. package/dist/clients/cursor/util.js +264 -0
  60. package/dist/clients/cursor/util.js.map +1 -0
  61. package/dist/commands/analyze.js +3 -3
  62. package/dist/commands/analyze.js.map +1 -1
  63. package/dist/commands/hook.js +1 -2
  64. package/dist/commands/hook.js.map +1 -1
  65. package/dist/commands/process-job-file.d.ts +10 -0
  66. package/dist/commands/process-job-file.d.ts.map +1 -0
  67. package/dist/commands/process-job-file.js +19 -0
  68. package/dist/commands/process-job-file.js.map +1 -0
  69. package/dist/commands/queue.d.ts +12 -0
  70. package/dist/commands/queue.d.ts.map +1 -0
  71. package/dist/commands/queue.js +495 -0
  72. package/dist/commands/queue.js.map +1 -0
  73. package/dist/hooks/core/actions.d.ts +168 -27
  74. package/dist/hooks/core/actions.d.ts.map +1 -1
  75. package/dist/hooks/core/actions.js +81 -4
  76. package/dist/hooks/core/actions.js.map +1 -1
  77. package/dist/hooks/core/activity.d.ts.map +1 -1
  78. package/dist/hooks/core/activity.js +13 -6
  79. package/dist/hooks/core/activity.js.map +1 -1
  80. package/dist/hooks/core/session-state.d.ts +19 -7
  81. package/dist/hooks/core/session-state.d.ts.map +1 -1
  82. package/dist/hooks/core/session-state.js +66 -12
  83. package/dist/hooks/core/session-state.js.map +1 -1
  84. package/dist/hooks/core/submit-verdict.d.ts.map +1 -1
  85. package/dist/hooks/core/submit-verdict.js +13 -4
  86. package/dist/hooks/core/submit-verdict.js.map +1 -1
  87. package/dist/hooks/core/verification-lifecycle.d.ts.map +1 -1
  88. package/dist/hooks/core/verification-lifecycle.js +14 -4
  89. package/dist/hooks/core/verification-lifecycle.js.map +1 -1
  90. package/dist/hooks/core/verify-gate.d.ts.map +1 -1
  91. package/dist/hooks/core/verify-gate.js +31 -19
  92. package/dist/hooks/core/verify-gate.js.map +1 -1
  93. package/dist/index.js +12 -3
  94. package/dist/index.js.map +1 -1
  95. package/dist/lib/collector.d.ts +64 -5
  96. package/dist/lib/collector.d.ts.map +1 -1
  97. package/dist/lib/collector.js +107 -44
  98. package/dist/lib/collector.js.map +1 -1
  99. package/dist/lib/config.d.ts +72 -8
  100. package/dist/lib/config.d.ts.map +1 -1
  101. package/dist/lib/config.js +40 -0
  102. package/dist/lib/config.js.map +1 -1
  103. package/dist/queue/dead-letter.d.ts +26 -0
  104. package/dist/queue/dead-letter.d.ts.map +1 -0
  105. package/dist/queue/dead-letter.js +233 -0
  106. package/dist/queue/dead-letter.js.map +1 -0
  107. package/dist/queue/drain.d.ts +36 -0
  108. package/dist/queue/drain.d.ts.map +1 -0
  109. package/dist/queue/drain.js +170 -0
  110. package/dist/queue/drain.js.map +1 -0
  111. package/dist/queue/flush.d.ts +64 -0
  112. package/dist/queue/flush.d.ts.map +1 -0
  113. package/dist/queue/flush.js +119 -0
  114. package/dist/queue/flush.js.map +1 -0
  115. package/dist/queue/handlers/send-event.d.ts +23 -0
  116. package/dist/queue/handlers/send-event.d.ts.map +1 -0
  117. package/dist/queue/handlers/send-event.js +131 -0
  118. package/dist/queue/handlers/send-event.js.map +1 -0
  119. package/dist/queue/index.d.ts +30 -0
  120. package/dist/queue/index.d.ts.map +1 -0
  121. package/dist/queue/index.js +71 -0
  122. package/dist/queue/index.js.map +1 -0
  123. package/dist/queue/paths.d.ts +40 -0
  124. package/dist/queue/paths.d.ts.map +1 -0
  125. package/dist/queue/paths.js +107 -0
  126. package/dist/queue/paths.js.map +1 -0
  127. package/dist/queue/process-file.d.ts +22 -0
  128. package/dist/queue/process-file.d.ts.map +1 -0
  129. package/dist/queue/process-file.js +257 -0
  130. package/dist/queue/process-file.js.map +1 -0
  131. package/dist/queue/register-handlers.d.ts +26 -0
  132. package/dist/queue/register-handlers.d.ts.map +1 -0
  133. package/dist/queue/register-handlers.js +36 -0
  134. package/dist/queue/register-handlers.js.map +1 -0
  135. package/dist/queue/registry.d.ts +42 -0
  136. package/dist/queue/registry.d.ts.map +1 -0
  137. package/dist/queue/registry.js +36 -0
  138. package/dist/queue/registry.js.map +1 -0
  139. package/dist/queue/snapshot.d.ts +16 -0
  140. package/dist/queue/snapshot.d.ts.map +1 -0
  141. package/dist/queue/snapshot.js +39 -0
  142. package/dist/queue/snapshot.js.map +1 -0
  143. package/dist/queue/spawn.d.ts +15 -0
  144. package/dist/queue/spawn.d.ts.map +1 -0
  145. package/dist/queue/spawn.js +45 -0
  146. package/dist/queue/spawn.js.map +1 -0
  147. package/dist/queue/submit.d.ts +19 -0
  148. package/dist/queue/submit.d.ts.map +1 -0
  149. package/dist/queue/submit.js +94 -0
  150. package/dist/queue/submit.js.map +1 -0
  151. package/dist/queue/types.d.ts +77 -0
  152. package/dist/queue/types.d.ts.map +1 -0
  153. package/dist/queue/types.js +83 -0
  154. package/dist/queue/types.js.map +1 -0
  155. package/dist/queue/worker-log.d.ts +21 -0
  156. package/dist/queue/worker-log.d.ts.map +1 -0
  157. package/dist/queue/worker-log.js +140 -0
  158. package/dist/queue/worker-log.js.map +1 -0
  159. package/package.json +1 -1
@@ -0,0 +1,23 @@
1
+ /**
2
+ * IronBee CLI — send_event Handler
3
+ *
4
+ * Queue handler for `type: "send_event"` jobs. Batches event payloads from
5
+ * `job.data` and POSTs them to the IronBee Collector via the shared
6
+ * transport + target resolver in `src/lib/collector.ts`.
7
+ *
8
+ * HTTP status → queue error classification (spec §6):
9
+ * - 2xx → success (jobs marked delivered)
10
+ * - 401 / 403 → AuthError (worker leaves the file; operator fixes creds)
11
+ * - 5xx / 429 → TransientError (worker leaves the file; next drain retries)
12
+ * - timeout / net → TransientError
13
+ * - 400 (batch) → BadRequestBatchError (worker falls back to dispatchSingle)
14
+ * - 400 (single) → BadRequestError (worker dead-letters that one job)
15
+ * - other 4xx → BadRequestBatchError / BadRequestError (permanent)
16
+ *
17
+ * When no collector is configured (or `IRONBEE_COLLECTOR=false`), dispatch
18
+ * is a no-op — jobs are silently "delivered" so the queue doesn't accumulate
19
+ * indefinitely in local-only mode.
20
+ */
21
+ import { Handler } from "../registry";
22
+ export declare const sendEventHandler: Handler;
23
+ //# sourceMappingURL=send-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-event.d.ts","sourceRoot":"","sources":["../../../src/queue/handlers/send-event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAoEtC,eAAO,MAAM,gBAAgB,EAAE,OAgD9B,CAAC"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * IronBee CLI — send_event Handler
4
+ *
5
+ * Queue handler for `type: "send_event"` jobs. Batches event payloads from
6
+ * `job.data` and POSTs them to the IronBee Collector via the shared
7
+ * transport + target resolver in `src/lib/collector.ts`.
8
+ *
9
+ * HTTP status → queue error classification (spec §6):
10
+ * - 2xx → success (jobs marked delivered)
11
+ * - 401 / 403 → AuthError (worker leaves the file; operator fixes creds)
12
+ * - 5xx / 429 → TransientError (worker leaves the file; next drain retries)
13
+ * - timeout / net → TransientError
14
+ * - 400 (batch) → BadRequestBatchError (worker falls back to dispatchSingle)
15
+ * - 400 (single) → BadRequestError (worker dead-letters that one job)
16
+ * - other 4xx → BadRequestBatchError / BadRequestError (permanent)
17
+ *
18
+ * When no collector is configured (or `IRONBEE_COLLECTOR=false`), dispatch
19
+ * is a no-op — jobs are silently "delivered" so the queue doesn't accumulate
20
+ * indefinitely in local-only mode.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.sendEventHandler = void 0;
24
+ const collector_1 = require("../../lib/collector");
25
+ const logger_1 = require("../../lib/logger");
26
+ const paths_1 = require("../paths");
27
+ const types_1 = require("../types");
28
+ const SEND_TIMEOUT_MS = 10000;
29
+ /**
30
+ * Default max events per POST. Collectors sometimes reject bodies above ~1 MB
31
+ * (Spring Boot default). With tool_call envelopes capped at 4 KB each, 100
32
+ * events ≈ 400 KB worst case — comfortably under typical limits.
33
+ * Override via `collector.batchSize` in config.json.
34
+ */
35
+ const DEFAULT_BATCH_SIZE = 100;
36
+ function resolveBatchSize(target) {
37
+ if (typeof target.batchSize === "number" && target.batchSize >= 1) {
38
+ return Math.floor(target.batchSize);
39
+ }
40
+ return DEFAULT_BATCH_SIZE;
41
+ }
42
+ function classifyBatch(result) {
43
+ const { status, body } = result;
44
+ if (status >= 200 && status < 300) {
45
+ return;
46
+ }
47
+ if (status === 401 || status === 403) {
48
+ throw new types_1.AuthError(`collector auth failed: HTTP ${status} ${truncate(body, 200)}`);
49
+ }
50
+ if (status === 429 || status >= 500) {
51
+ throw new types_1.TransientError(`collector transient: HTTP ${status} ${truncate(body, 200)}`);
52
+ }
53
+ if (status === 400) {
54
+ throw new types_1.BadRequestBatchError(`collector rejected batch: HTTP 400 ${truncate(body, 200)}`);
55
+ }
56
+ // other 4xx — treat as permanent per-batch; fallback will dead-letter each
57
+ throw new types_1.BadRequestBatchError(`collector error: HTTP ${status} ${truncate(body, 200)}`);
58
+ }
59
+ function classifySingle(result) {
60
+ const { status, body } = result;
61
+ if (status >= 200 && status < 300) {
62
+ return;
63
+ }
64
+ if (status === 401 || status === 403) {
65
+ throw new types_1.AuthError(`collector auth failed: HTTP ${status} ${truncate(body, 200)}`);
66
+ }
67
+ if (status === 429 || status >= 500) {
68
+ throw new types_1.TransientError(`collector transient: HTTP ${status} ${truncate(body, 200)}`);
69
+ }
70
+ if (status === 400) {
71
+ throw new types_1.BadRequestError(`400: ${truncate(body, 200)}`);
72
+ }
73
+ throw new types_1.BadRequestError(`HTTP ${status}: ${truncate(body, 200)}`);
74
+ }
75
+ function truncate(s, max) {
76
+ if (s.length <= max) {
77
+ return s;
78
+ }
79
+ return s.slice(0, max) + "…";
80
+ }
81
+ exports.sendEventHandler = {
82
+ /**
83
+ * Chunk the jobs into `batchSize`-sized slices and POST each. The first
84
+ * failed chunk throws — if `TransientError`/`AuthError`, the worker
85
+ * leaves the snapshot for retry (which re-sends already-delivered chunks;
86
+ * downstream dedupes on `job.id`). A 400 throws `BadRequestBatchError`,
87
+ * triggering per-job fallback across the WHOLE snapshot (spec §5.3),
88
+ * again relying on id-dedup for chunks that already succeeded.
89
+ */
90
+ async dispatch(jobs) {
91
+ const target = (0, collector_1.getCollectorTarget)((0, paths_1.resolveProjectDir)());
92
+ if (!target) {
93
+ logger_1.logger.debug(`send_event: no collector configured, skipping ${jobs.length} job(s)`);
94
+ return;
95
+ }
96
+ if (jobs.length === 0) {
97
+ return;
98
+ }
99
+ const batchSize = resolveBatchSize(target);
100
+ const events = jobs.map((j) => j.data);
101
+ for (let i = 0; i < events.length; i += batchSize) {
102
+ const chunk = events.slice(i, i + batchSize);
103
+ let result;
104
+ try {
105
+ result = await (0, collector_1.postEventsBatch)(chunk, target, { timeoutMs: SEND_TIMEOUT_MS });
106
+ }
107
+ catch (e) {
108
+ throw new types_1.TransientError(`collector network error: ${e instanceof Error ? e.message : String(e)}`);
109
+ }
110
+ classifyBatch(result);
111
+ }
112
+ // Note: worker stdio is "ignore" + no setLogFile — `processFile` writes
113
+ // a `BATCH_OK type=send_event count=N` line to `worker.log` per spec
114
+ // §5.3 which already covers per-batch observability.
115
+ },
116
+ async dispatchSingle(job) {
117
+ const target = (0, collector_1.getCollectorTarget)((0, paths_1.resolveProjectDir)());
118
+ if (!target) {
119
+ return;
120
+ }
121
+ let result;
122
+ try {
123
+ result = await (0, collector_1.postEventsBatch)([job.data], target, { timeoutMs: SEND_TIMEOUT_MS });
124
+ }
125
+ catch (e) {
126
+ throw new types_1.TransientError(`collector network error: ${e instanceof Error ? e.message : String(e)}`);
127
+ }
128
+ classifySingle(result);
129
+ },
130
+ };
131
+ //# sourceMappingURL=send-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-event.js","sourceRoot":"","sources":["../../../src/queue/handlers/send-event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * IronBee CLI — Queue Module
3
+ *
4
+ * File-backed, crash-safe, concurrency-safe background job queue.
5
+ * Canonical spec: docs/job-queue.md.
6
+ *
7
+ * Public API:
8
+ * - submit(projectDir, sessionId, type, data, opts?) → job_id
9
+ * - snapshot(projectDir, sessionId) → snapshot_path | null
10
+ * - processFile(path, opts?) → void
11
+ * - drain(projectDir, sessionId, opts?) → DrainResult
12
+ * - register(type, handler) / unregister(type)
13
+ * - spawnDetachedWorker(snapshotPath)
14
+ *
15
+ * Error classes:
16
+ * InvalidSessionIdError, JobTooLargeError, IOError,
17
+ * TransientError, AuthError, BadRequestError, BadRequestBatchError
18
+ */
19
+ export { submit, SubmitOptions } from "./submit";
20
+ export { snapshot } from "./snapshot";
21
+ export { processFile, ProcessFileOptions } from "./process-file";
22
+ export { drain, DrainOptions, DrainResult } from "./drain";
23
+ export { spawnDetachedWorker } from "./spawn";
24
+ export { flushInBackground, flushSynchronously, maybeAutoFlush, DEFAULT_AUTO_FLUSH_SIZE_BYTES } from "./flush";
25
+ export { registerQueueHandlers, SEND_EVENT_TYPE } from "./register-handlers";
26
+ export { Handler, HandlerRegistry, register, unregister, clear as clearRegistry, get as getHandler, snapshotRegistry, } from "./registry";
27
+ export { InvalidSessionIdError, JobTooLargeError, IOError, TransientError, AuthError, BadRequestError, BadRequestBatchError, Job, DeadLetterEntry, DeadLetterParsed, DeadLetterParseError, MAX_LINE_BYTES, } from "./types";
28
+ export { resolveProjectDir, validateSessionId, sessionsRoot, sessionDir, queueDir, liveQueueFile, snapshotFile, deadLetterFile, workerLogFile, parseSnapshotPath, SNAPSHOT_FILENAME_REGEX, DEAD_LETTER_ROTATED_REGEX, WORKER_LOG_ROTATED_REGEX, } from "./paths";
29
+ export { readDeadLetterEntries } from "./dead-letter";
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/queue/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,cAAc,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAC/G,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EACH,OAAO,EACP,eAAe,EACf,QAAQ,EACR,UAAU,EACV,KAAK,IAAI,aAAa,EACtB,GAAG,IAAI,UAAU,EACjB,gBAAgB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EACH,qBAAqB,EACrB,gBAAgB,EAChB,OAAO,EACP,cAAc,EACd,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,GAAG,EACH,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACH,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,GAC3B,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * IronBee CLI — Queue Module
4
+ *
5
+ * File-backed, crash-safe, concurrency-safe background job queue.
6
+ * Canonical spec: docs/job-queue.md.
7
+ *
8
+ * Public API:
9
+ * - submit(projectDir, sessionId, type, data, opts?) → job_id
10
+ * - snapshot(projectDir, sessionId) → snapshot_path | null
11
+ * - processFile(path, opts?) → void
12
+ * - drain(projectDir, sessionId, opts?) → DrainResult
13
+ * - register(type, handler) / unregister(type)
14
+ * - spawnDetachedWorker(snapshotPath)
15
+ *
16
+ * Error classes:
17
+ * InvalidSessionIdError, JobTooLargeError, IOError,
18
+ * TransientError, AuthError, BadRequestError, BadRequestBatchError
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.readDeadLetterEntries = exports.WORKER_LOG_ROTATED_REGEX = exports.DEAD_LETTER_ROTATED_REGEX = exports.SNAPSHOT_FILENAME_REGEX = exports.parseSnapshotPath = exports.workerLogFile = exports.deadLetterFile = exports.snapshotFile = exports.liveQueueFile = exports.queueDir = exports.sessionDir = exports.sessionsRoot = exports.validateSessionId = exports.resolveProjectDir = exports.MAX_LINE_BYTES = exports.BadRequestBatchError = exports.BadRequestError = exports.AuthError = exports.TransientError = exports.IOError = exports.JobTooLargeError = exports.InvalidSessionIdError = exports.snapshotRegistry = exports.getHandler = exports.clearRegistry = exports.unregister = exports.register = exports.SEND_EVENT_TYPE = exports.registerQueueHandlers = exports.DEFAULT_AUTO_FLUSH_SIZE_BYTES = exports.maybeAutoFlush = exports.flushSynchronously = exports.flushInBackground = exports.spawnDetachedWorker = exports.drain = exports.processFile = exports.snapshot = exports.submit = void 0;
22
+ var submit_1 = require("./submit");
23
+ Object.defineProperty(exports, "submit", { enumerable: true, get: function () { return submit_1.submit; } });
24
+ var snapshot_1 = require("./snapshot");
25
+ Object.defineProperty(exports, "snapshot", { enumerable: true, get: function () { return snapshot_1.snapshot; } });
26
+ var process_file_1 = require("./process-file");
27
+ Object.defineProperty(exports, "processFile", { enumerable: true, get: function () { return process_file_1.processFile; } });
28
+ var drain_1 = require("./drain");
29
+ Object.defineProperty(exports, "drain", { enumerable: true, get: function () { return drain_1.drain; } });
30
+ var spawn_1 = require("./spawn");
31
+ Object.defineProperty(exports, "spawnDetachedWorker", { enumerable: true, get: function () { return spawn_1.spawnDetachedWorker; } });
32
+ var flush_1 = require("./flush");
33
+ Object.defineProperty(exports, "flushInBackground", { enumerable: true, get: function () { return flush_1.flushInBackground; } });
34
+ Object.defineProperty(exports, "flushSynchronously", { enumerable: true, get: function () { return flush_1.flushSynchronously; } });
35
+ Object.defineProperty(exports, "maybeAutoFlush", { enumerable: true, get: function () { return flush_1.maybeAutoFlush; } });
36
+ Object.defineProperty(exports, "DEFAULT_AUTO_FLUSH_SIZE_BYTES", { enumerable: true, get: function () { return flush_1.DEFAULT_AUTO_FLUSH_SIZE_BYTES; } });
37
+ var register_handlers_1 = require("./register-handlers");
38
+ Object.defineProperty(exports, "registerQueueHandlers", { enumerable: true, get: function () { return register_handlers_1.registerQueueHandlers; } });
39
+ Object.defineProperty(exports, "SEND_EVENT_TYPE", { enumerable: true, get: function () { return register_handlers_1.SEND_EVENT_TYPE; } });
40
+ var registry_1 = require("./registry");
41
+ Object.defineProperty(exports, "register", { enumerable: true, get: function () { return registry_1.register; } });
42
+ Object.defineProperty(exports, "unregister", { enumerable: true, get: function () { return registry_1.unregister; } });
43
+ Object.defineProperty(exports, "clearRegistry", { enumerable: true, get: function () { return registry_1.clear; } });
44
+ Object.defineProperty(exports, "getHandler", { enumerable: true, get: function () { return registry_1.get; } });
45
+ Object.defineProperty(exports, "snapshotRegistry", { enumerable: true, get: function () { return registry_1.snapshotRegistry; } });
46
+ var types_1 = require("./types");
47
+ Object.defineProperty(exports, "InvalidSessionIdError", { enumerable: true, get: function () { return types_1.InvalidSessionIdError; } });
48
+ Object.defineProperty(exports, "JobTooLargeError", { enumerable: true, get: function () { return types_1.JobTooLargeError; } });
49
+ Object.defineProperty(exports, "IOError", { enumerable: true, get: function () { return types_1.IOError; } });
50
+ Object.defineProperty(exports, "TransientError", { enumerable: true, get: function () { return types_1.TransientError; } });
51
+ Object.defineProperty(exports, "AuthError", { enumerable: true, get: function () { return types_1.AuthError; } });
52
+ Object.defineProperty(exports, "BadRequestError", { enumerable: true, get: function () { return types_1.BadRequestError; } });
53
+ Object.defineProperty(exports, "BadRequestBatchError", { enumerable: true, get: function () { return types_1.BadRequestBatchError; } });
54
+ Object.defineProperty(exports, "MAX_LINE_BYTES", { enumerable: true, get: function () { return types_1.MAX_LINE_BYTES; } });
55
+ var paths_1 = require("./paths");
56
+ Object.defineProperty(exports, "resolveProjectDir", { enumerable: true, get: function () { return paths_1.resolveProjectDir; } });
57
+ Object.defineProperty(exports, "validateSessionId", { enumerable: true, get: function () { return paths_1.validateSessionId; } });
58
+ Object.defineProperty(exports, "sessionsRoot", { enumerable: true, get: function () { return paths_1.sessionsRoot; } });
59
+ Object.defineProperty(exports, "sessionDir", { enumerable: true, get: function () { return paths_1.sessionDir; } });
60
+ Object.defineProperty(exports, "queueDir", { enumerable: true, get: function () { return paths_1.queueDir; } });
61
+ Object.defineProperty(exports, "liveQueueFile", { enumerable: true, get: function () { return paths_1.liveQueueFile; } });
62
+ Object.defineProperty(exports, "snapshotFile", { enumerable: true, get: function () { return paths_1.snapshotFile; } });
63
+ Object.defineProperty(exports, "deadLetterFile", { enumerable: true, get: function () { return paths_1.deadLetterFile; } });
64
+ Object.defineProperty(exports, "workerLogFile", { enumerable: true, get: function () { return paths_1.workerLogFile; } });
65
+ Object.defineProperty(exports, "parseSnapshotPath", { enumerable: true, get: function () { return paths_1.parseSnapshotPath; } });
66
+ Object.defineProperty(exports, "SNAPSHOT_FILENAME_REGEX", { enumerable: true, get: function () { return paths_1.SNAPSHOT_FILENAME_REGEX; } });
67
+ Object.defineProperty(exports, "DEAD_LETTER_ROTATED_REGEX", { enumerable: true, get: function () { return paths_1.DEAD_LETTER_ROTATED_REGEX; } });
68
+ Object.defineProperty(exports, "WORKER_LOG_ROTATED_REGEX", { enumerable: true, get: function () { return paths_1.WORKER_LOG_ROTATED_REGEX; } });
69
+ var dead_letter_1 = require("./dead-letter");
70
+ Object.defineProperty(exports, "readDeadLetterEntries", { enumerable: true, get: function () { return dead_letter_1.readDeadLetterEntries; } });
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/queue/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAEH,mCAAiD;AAAxC,gGAAA,MAAM,OAAA;AACf,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AACjB,+CAAiE;AAAxD,2GAAA,WAAW,OAAA;AACpB,iCAA2D;AAAlD,8FAAA,KAAK,OAAA;AACd,iCAA8C;AAArC,4GAAA,mBAAmB,OAAA;AAC5B,iCAA+G;AAAtG,0GAAA,iBAAiB,OAAA;AAAE,2GAAA,kBAAkB,OAAA;AAAE,uGAAA,cAAc,OAAA;AAAE,sHAAA,6BAA6B,OAAA;AAC7F,yDAA6E;AAApE,0HAAA,qBAAqB,OAAA;AAAE,oHAAA,eAAe,OAAA;AAC/C,uCAQoB;AALhB,oGAAA,QAAQ,OAAA;AACR,sGAAA,UAAU,OAAA;AACV,yGAAA,KAAK,OAAiB;AACtB,sGAAA,GAAG,OAAc;AACjB,4GAAA,gBAAgB,OAAA;AAEpB,iCAaiB;AAZb,8GAAA,qBAAqB,OAAA;AACrB,yGAAA,gBAAgB,OAAA;AAChB,gGAAA,OAAO,OAAA;AACP,uGAAA,cAAc,OAAA;AACd,kGAAA,SAAS,OAAA;AACT,wGAAA,eAAe,OAAA;AACf,6GAAA,oBAAoB,OAAA;AAKpB,uGAAA,cAAc,OAAA;AAElB,iCAciB;AAbb,0GAAA,iBAAiB,OAAA;AACjB,0GAAA,iBAAiB,OAAA;AACjB,qGAAA,YAAY,OAAA;AACZ,mGAAA,UAAU,OAAA;AACV,iGAAA,QAAQ,OAAA;AACR,sGAAA,aAAa,OAAA;AACb,qGAAA,YAAY,OAAA;AACZ,uGAAA,cAAc,OAAA;AACd,sGAAA,aAAa,OAAA;AACb,0GAAA,iBAAiB,OAAA;AACjB,gHAAA,uBAAuB,OAAA;AACvB,kHAAA,yBAAyB,OAAA;AACzB,iHAAA,wBAAwB,OAAA;AAE5B,6CAAsD;AAA7C,oHAAA,qBAAqB,OAAA"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * IronBee CLI — Queue Path Resolution & Session Validation
3
+ *
4
+ * See docs/job-queue.md §2.1 (session dir), §5.1 step 1 (sessionId rules),
5
+ * §5.5 (snapshot filename regex), §9.4 (project dir resolution).
6
+ */
7
+ export declare const SNAPSHOT_FILENAME_REGEX: RegExp;
8
+ export declare const DEAD_LETTER_ROTATED_REGEX: RegExp;
9
+ export declare const WORKER_LOG_ROTATED_REGEX: RegExp;
10
+ export declare const SESSION_ID_MAX_LEN: number;
11
+ /**
12
+ * Resolve the project directory using the same convention as the CLI's
13
+ * existing hooks: env-var overrides → cwd().
14
+ */
15
+ export declare function resolveProjectDir(override?: string): string;
16
+ /**
17
+ * Validate a session identifier per §5.1 step 1. Throws InvalidSessionIdError
18
+ * on any rule violation to prevent path-escape attacks.
19
+ */
20
+ export declare function validateSessionId(sessionId: string): void;
21
+ export declare function sessionsRoot(projectDir: string): string;
22
+ export declare function sessionDir(projectDir: string, sessionId: string): string;
23
+ export declare function queueDir(projectDir: string, sessionId: string): string;
24
+ export declare function liveQueueFile(projectDir: string, sessionId: string): string;
25
+ export declare function snapshotFile(projectDir: string, sessionId: string, snapshotId: string): string;
26
+ export declare function deadLetterFile(projectDir: string, sessionId: string): string;
27
+ export declare function workerLogFile(projectDir: string, sessionId: string): string;
28
+ /**
29
+ * Given an absolute snapshot path, derive (projectDir, sessionId, filename).
30
+ * Path shape: `<projectDir>/.ironbee/sessions/<sessionId>/queue/jobs-<UUID>.jsonl`.
31
+ *
32
+ * Uses `path.dirname` so both POSIX ("/a/b") and Windows ("C:\a\b")
33
+ * separators round-trip cleanly without mangling into forward-slashes.
34
+ */
35
+ export declare function parseSnapshotPath(snapshotPath: string): {
36
+ projectDir: string;
37
+ sessionId: string;
38
+ filename: string;
39
+ };
40
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/queue/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,eAAO,MAAM,uBAAuB,EAAE,MAA4F,CAAC;AACnI,eAAO,MAAM,yBAAyB,EAAE,MAAmG,CAAC;AAC5I,eAAO,MAAM,wBAAwB,EAAE,MAA4F,CAAC;AACpI,eAAO,MAAM,kBAAkB,EAAE,MAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAmBzD;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9F;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAoBnH"}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * IronBee CLI — Queue Path Resolution & Session Validation
4
+ *
5
+ * See docs/job-queue.md §2.1 (session dir), §5.1 step 1 (sessionId rules),
6
+ * §5.5 (snapshot filename regex), §9.4 (project dir resolution).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.SESSION_ID_MAX_LEN = exports.WORKER_LOG_ROTATED_REGEX = exports.DEAD_LETTER_ROTATED_REGEX = exports.SNAPSHOT_FILENAME_REGEX = void 0;
10
+ exports.resolveProjectDir = resolveProjectDir;
11
+ exports.validateSessionId = validateSessionId;
12
+ exports.sessionsRoot = sessionsRoot;
13
+ exports.sessionDir = sessionDir;
14
+ exports.queueDir = queueDir;
15
+ exports.liveQueueFile = liveQueueFile;
16
+ exports.snapshotFile = snapshotFile;
17
+ exports.deadLetterFile = deadLetterFile;
18
+ exports.workerLogFile = workerLogFile;
19
+ exports.parseSnapshotPath = parseSnapshotPath;
20
+ const path_1 = require("path");
21
+ const types_1 = require("./types");
22
+ exports.SNAPSHOT_FILENAME_REGEX = /^jobs-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.jsonl$/;
23
+ exports.DEAD_LETTER_ROTATED_REGEX = /^dead-letter-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.jsonl$/;
24
+ exports.WORKER_LOG_ROTATED_REGEX = /^worker-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.log$/;
25
+ exports.SESSION_ID_MAX_LEN = 128;
26
+ /**
27
+ * Resolve the project directory using the same convention as the CLI's
28
+ * existing hooks: env-var overrides → cwd().
29
+ */
30
+ function resolveProjectDir(override) {
31
+ return override
32
+ ?? process.env.IRONBEE_PROJECT_DIR
33
+ ?? process.env.CLAUDE_PROJECT_DIR
34
+ ?? process.env.CURSOR_PROJECT_DIR
35
+ ?? process.cwd();
36
+ }
37
+ /**
38
+ * Validate a session identifier per §5.1 step 1. Throws InvalidSessionIdError
39
+ * on any rule violation to prevent path-escape attacks.
40
+ */
41
+ function validateSessionId(sessionId) {
42
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
43
+ throw new types_1.InvalidSessionIdError("session id is empty");
44
+ }
45
+ if (sessionId.length > exports.SESSION_ID_MAX_LEN) {
46
+ throw new types_1.InvalidSessionIdError(`session id exceeds ${exports.SESSION_ID_MAX_LEN} chars`);
47
+ }
48
+ if (sessionId === "." || sessionId === "..") {
49
+ throw new types_1.InvalidSessionIdError("session id is a reserved path component");
50
+ }
51
+ for (let i = 0; i < sessionId.length; i++) {
52
+ const code = sessionId.charCodeAt(i);
53
+ if (code < 0x20 || code === 0x7f) {
54
+ throw new types_1.InvalidSessionIdError("session id contains ASCII control character");
55
+ }
56
+ }
57
+ if (sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("\0")) {
58
+ throw new types_1.InvalidSessionIdError("session id contains path separator or null byte");
59
+ }
60
+ }
61
+ function sessionsRoot(projectDir) {
62
+ return (0, path_1.join)(projectDir, ".ironbee", "sessions");
63
+ }
64
+ function sessionDir(projectDir, sessionId) {
65
+ return (0, path_1.join)(sessionsRoot(projectDir), sessionId);
66
+ }
67
+ function queueDir(projectDir, sessionId) {
68
+ return (0, path_1.join)(sessionDir(projectDir, sessionId), "queue");
69
+ }
70
+ function liveQueueFile(projectDir, sessionId) {
71
+ return (0, path_1.join)(queueDir(projectDir, sessionId), "jobs.jsonl");
72
+ }
73
+ function snapshotFile(projectDir, sessionId, snapshotId) {
74
+ return (0, path_1.join)(queueDir(projectDir, sessionId), `jobs-${snapshotId}.jsonl`);
75
+ }
76
+ function deadLetterFile(projectDir, sessionId) {
77
+ return (0, path_1.join)(queueDir(projectDir, sessionId), "dead-letter.jsonl");
78
+ }
79
+ function workerLogFile(projectDir, sessionId) {
80
+ return (0, path_1.join)(queueDir(projectDir, sessionId), "worker.log");
81
+ }
82
+ /**
83
+ * Given an absolute snapshot path, derive (projectDir, sessionId, filename).
84
+ * Path shape: `<projectDir>/.ironbee/sessions/<sessionId>/queue/jobs-<UUID>.jsonl`.
85
+ *
86
+ * Uses `path.dirname` so both POSIX ("/a/b") and Windows ("C:\a\b")
87
+ * separators round-trip cleanly without mangling into forward-slashes.
88
+ */
89
+ function parseSnapshotPath(snapshotPath) {
90
+ const filename = (0, path_1.basename)(snapshotPath);
91
+ const queueSegmentDir = (0, path_1.dirname)(snapshotPath);
92
+ const sessionSegmentDir = (0, path_1.dirname)(queueSegmentDir);
93
+ const sessionsSegmentDir = (0, path_1.dirname)(sessionSegmentDir);
94
+ const ironbeeSegmentDir = (0, path_1.dirname)(sessionsSegmentDir);
95
+ const projectDir = (0, path_1.dirname)(ironbeeSegmentDir);
96
+ if ((0, path_1.basename)(queueSegmentDir) !== "queue"
97
+ || (0, path_1.basename)(sessionsSegmentDir) !== "sessions"
98
+ || (0, path_1.basename)(ironbeeSegmentDir) !== ".ironbee") {
99
+ throw new Error(`snapshot path is not under a valid session queue dir: ${snapshotPath}`);
100
+ }
101
+ const sessionId = (0, path_1.basename)(sessionSegmentDir);
102
+ if (sessionId.length === 0 || sessionId === ".") {
103
+ throw new Error(`snapshot path is not under a valid session queue dir: ${snapshotPath}`);
104
+ }
105
+ return { projectDir, sessionId, filename };
106
+ }
107
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/queue/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * IronBee CLI — Queue processFile() worker
3
+ *
4
+ * See docs/job-queue.md §5.3.
5
+ */
6
+ import { HandlerRegistry } from "./registry";
7
+ export interface ProcessFileOptions {
8
+ /** Override the registry for tests. Falls back to the global snapshot. */
9
+ registry?: HandlerRegistry;
10
+ }
11
+ /**
12
+ * Process one snapshot file end-to-end.
13
+ *
14
+ * Deletes the file only when every line has reached a terminal state
15
+ * (delivered OR dead-lettered). On transient/auth failure or a transient
16
+ * during per-job fallback, the file is left on disk for later retry.
17
+ *
18
+ * Never throws — all errors are logged to worker.log and classified
19
+ * per §5.3.
20
+ */
21
+ export declare function processFile(path: string, opts?: ProcessFileOptions): Promise<void>;
22
+ //# sourceMappingURL=process-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-file.d.ts","sourceRoot":"","sources":["../../src/queue/process-file.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,OAAO,EAAW,eAAe,EAAoB,MAAM,YAAY,CAAC;AASxE,MAAM,WAAW,kBAAkB;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8JxF"}