@inbrowser/agent 0.0.0-placeholder → 0.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 (267) hide show
  1. package/AGENTS.md +270 -0
  2. package/LICENSE +21 -0
  3. package/README.md +117 -2
  4. package/bin/agent.ts +10 -0
  5. package/dist/cli/commands/describe.d.ts +14 -0
  6. package/dist/cli/commands/describe.d.ts.map +1 -0
  7. package/dist/cli/commands/describe.js +179 -0
  8. package/dist/cli/commands/describe.js.map +1 -0
  9. package/dist/cli/commands/events.d.ts +21 -0
  10. package/dist/cli/commands/events.d.ts.map +1 -0
  11. package/dist/cli/commands/events.js +59 -0
  12. package/dist/cli/commands/events.js.map +1 -0
  13. package/dist/cli/commands/fleet.d.ts +15 -0
  14. package/dist/cli/commands/fleet.d.ts.map +1 -0
  15. package/dist/cli/commands/fleet.js +149 -0
  16. package/dist/cli/commands/fleet.js.map +1 -0
  17. package/dist/cli/commands/help.d.ts +15 -0
  18. package/dist/cli/commands/help.d.ts.map +1 -0
  19. package/dist/cli/commands/help.js +93 -0
  20. package/dist/cli/commands/help.js.map +1 -0
  21. package/dist/cli/commands/migrate.d.ts +27 -0
  22. package/dist/cli/commands/migrate.d.ts.map +1 -0
  23. package/dist/cli/commands/migrate.js +109 -0
  24. package/dist/cli/commands/migrate.js.map +1 -0
  25. package/dist/cli/commands/run.d.ts +38 -0
  26. package/dist/cli/commands/run.d.ts.map +1 -0
  27. package/dist/cli/commands/run.js +535 -0
  28. package/dist/cli/commands/run.js.map +1 -0
  29. package/dist/cli/commands/schema.d.ts +8 -0
  30. package/dist/cli/commands/schema.d.ts.map +1 -0
  31. package/dist/cli/commands/schema.js +12 -0
  32. package/dist/cli/commands/schema.js.map +1 -0
  33. package/dist/cli/commands/serve.d.ts +39 -0
  34. package/dist/cli/commands/serve.d.ts.map +1 -0
  35. package/dist/cli/commands/serve.js +65 -0
  36. package/dist/cli/commands/serve.js.map +1 -0
  37. package/dist/cli/commands/undo.d.ts +36 -0
  38. package/dist/cli/commands/undo.d.ts.map +1 -0
  39. package/dist/cli/commands/undo.js +132 -0
  40. package/dist/cli/commands/undo.js.map +1 -0
  41. package/dist/cli/fixtures.d.ts +17 -0
  42. package/dist/cli/fixtures.d.ts.map +1 -0
  43. package/dist/cli/fixtures.js +107 -0
  44. package/dist/cli/fixtures.js.map +1 -0
  45. package/dist/cli/hardening.d.ts +39 -0
  46. package/dist/cli/hardening.d.ts.map +1 -0
  47. package/dist/cli/hardening.js +68 -0
  48. package/dist/cli/hardening.js.map +1 -0
  49. package/dist/cli/index.d.ts +28 -0
  50. package/dist/cli/index.d.ts.map +1 -0
  51. package/dist/cli/index.js +19 -0
  52. package/dist/cli/index.js.map +1 -0
  53. package/dist/cli/llm/openrouter.d.ts +33 -0
  54. package/dist/cli/llm/openrouter.d.ts.map +1 -0
  55. package/dist/cli/llm/openrouter.js +285 -0
  56. package/dist/cli/llm/openrouter.js.map +1 -0
  57. package/dist/cli/main.d.ts +32 -0
  58. package/dist/cli/main.d.ts.map +1 -0
  59. package/dist/cli/main.js +106 -0
  60. package/dist/cli/main.js.map +1 -0
  61. package/dist/cli/output.d.ts +36 -0
  62. package/dist/cli/output.d.ts.map +1 -0
  63. package/dist/cli/output.js +95 -0
  64. package/dist/cli/output.js.map +1 -0
  65. package/dist/cli/parse.d.ts +26 -0
  66. package/dist/cli/parse.d.ts.map +1 -0
  67. package/dist/cli/parse.js +160 -0
  68. package/dist/cli/parse.js.map +1 -0
  69. package/dist/cli/session-log.d.ts +34 -0
  70. package/dist/cli/session-log.d.ts.map +1 -0
  71. package/dist/cli/session-log.js +52 -0
  72. package/dist/cli/session-log.js.map +1 -0
  73. package/dist/cli/spec.d.ts +62 -0
  74. package/dist/cli/spec.d.ts.map +1 -0
  75. package/dist/cli/spec.js +510 -0
  76. package/dist/cli/spec.js.map +1 -0
  77. package/dist/cli/ui/RunView.d.ts +134 -0
  78. package/dist/cli/ui/RunView.d.ts.map +1 -0
  79. package/dist/cli/ui/RunView.js +341 -0
  80. package/dist/cli/ui/RunView.js.map +1 -0
  81. package/dist/diagnostics/index.d.ts +5 -0
  82. package/dist/diagnostics/index.d.ts.map +1 -0
  83. package/dist/diagnostics/index.js +3 -0
  84. package/dist/diagnostics/index.js.map +1 -0
  85. package/dist/diagnostics/timing.d.ts +48 -0
  86. package/dist/diagnostics/timing.d.ts.map +1 -0
  87. package/dist/diagnostics/timing.js +85 -0
  88. package/dist/diagnostics/timing.js.map +1 -0
  89. package/dist/diagnostics/truthfulness.d.ts +36 -0
  90. package/dist/diagnostics/truthfulness.d.ts.map +1 -0
  91. package/dist/diagnostics/truthfulness.js +180 -0
  92. package/dist/diagnostics/truthfulness.js.map +1 -0
  93. package/dist/dispatch-memoization.d.ts +84 -0
  94. package/dist/dispatch-memoization.d.ts.map +1 -0
  95. package/dist/dispatch-memoization.js +197 -0
  96. package/dist/dispatch-memoization.js.map +1 -0
  97. package/dist/eval/comparison-report.d.ts +164 -0
  98. package/dist/eval/comparison-report.d.ts.map +1 -0
  99. package/dist/eval/comparison-report.js +316 -0
  100. package/dist/eval/comparison-report.js.map +1 -0
  101. package/dist/eval/fixture.d.ts +74 -0
  102. package/dist/eval/fixture.d.ts.map +1 -0
  103. package/dist/eval/fixture.js +217 -0
  104. package/dist/eval/fixture.js.map +1 -0
  105. package/dist/eval/index.d.ts +13 -0
  106. package/dist/eval/index.d.ts.map +1 -0
  107. package/dist/eval/index.js +7 -0
  108. package/dist/eval/index.js.map +1 -0
  109. package/dist/eval/load-node.d.ts +16 -0
  110. package/dist/eval/load-node.d.ts.map +1 -0
  111. package/dist/eval/load-node.js +58 -0
  112. package/dist/eval/load-node.js.map +1 -0
  113. package/dist/eval/metric-collector.d.ts +209 -0
  114. package/dist/eval/metric-collector.d.ts.map +1 -0
  115. package/dist/eval/metric-collector.js +293 -0
  116. package/dist/eval/metric-collector.js.map +1 -0
  117. package/dist/eval/run-record.d.ts +76 -0
  118. package/dist/eval/run-record.d.ts.map +1 -0
  119. package/dist/eval/run-record.js +32 -0
  120. package/dist/eval/run-record.js.map +1 -0
  121. package/dist/eval/runner.d.ts +140 -0
  122. package/dist/eval/runner.d.ts.map +1 -0
  123. package/dist/eval/runner.js +310 -0
  124. package/dist/eval/runner.js.map +1 -0
  125. package/dist/eval/spec-framework.d.ts +113 -0
  126. package/dist/eval/spec-framework.d.ts.map +1 -0
  127. package/dist/eval/spec-framework.js +100 -0
  128. package/dist/eval/spec-framework.js.map +1 -0
  129. package/dist/eval/spec-helpers.d.ts +245 -0
  130. package/dist/eval/spec-helpers.d.ts.map +1 -0
  131. package/dist/eval/spec-helpers.js +605 -0
  132. package/dist/eval/spec-helpers.js.map +1 -0
  133. package/dist/events/codec.d.ts +79 -0
  134. package/dist/events/codec.d.ts.map +1 -0
  135. package/dist/events/codec.js +142 -0
  136. package/dist/events/codec.js.map +1 -0
  137. package/dist/events/log-core.d.ts +76 -0
  138. package/dist/events/log-core.d.ts.map +1 -0
  139. package/dist/events/log-core.js +73 -0
  140. package/dist/events/log-core.js.map +1 -0
  141. package/dist/events/log.d.ts +60 -0
  142. package/dist/events/log.d.ts.map +1 -0
  143. package/dist/events/log.js +193 -0
  144. package/dist/events/log.js.map +1 -0
  145. package/dist/events/replay.d.ts +106 -0
  146. package/dist/events/replay.d.ts.map +1 -0
  147. package/dist/events/replay.js +137 -0
  148. package/dist/events/replay.js.map +1 -0
  149. package/dist/events/wrap.d.ts +100 -0
  150. package/dist/events/wrap.d.ts.map +1 -0
  151. package/dist/events/wrap.js +141 -0
  152. package/dist/events/wrap.js.map +1 -0
  153. package/dist/index.d.ts +73 -0
  154. package/dist/index.d.ts.map +1 -0
  155. package/dist/index.js +47 -0
  156. package/dist/index.js.map +1 -0
  157. package/dist/llm-adapter.d.ts +96 -0
  158. package/dist/llm-adapter.d.ts.map +1 -0
  159. package/dist/llm-adapter.js +132 -0
  160. package/dist/llm-adapter.js.map +1 -0
  161. package/dist/mcp/serve.d.ts +70 -0
  162. package/dist/mcp/serve.d.ts.map +1 -0
  163. package/dist/mcp/serve.js +154 -0
  164. package/dist/mcp/serve.js.map +1 -0
  165. package/dist/metrics/runs.d.ts +58 -0
  166. package/dist/metrics/runs.d.ts.map +1 -0
  167. package/dist/metrics/runs.js +99 -0
  168. package/dist/metrics/runs.js.map +1 -0
  169. package/dist/metrics.d.ts +38 -0
  170. package/dist/metrics.d.ts.map +1 -0
  171. package/dist/metrics.js +123 -0
  172. package/dist/metrics.js.map +1 -0
  173. package/dist/node.d.ts +23 -0
  174. package/dist/node.d.ts.map +1 -0
  175. package/dist/node.js +23 -0
  176. package/dist/node.js.map +1 -0
  177. package/dist/planner-executor.d.ts +132 -0
  178. package/dist/planner-executor.d.ts.map +1 -0
  179. package/dist/planner-executor.js +274 -0
  180. package/dist/planner-executor.js.map +1 -0
  181. package/dist/session.d.ts +10 -0
  182. package/dist/session.d.ts.map +1 -0
  183. package/dist/session.js +179 -0
  184. package/dist/session.js.map +1 -0
  185. package/dist/skill-catalog.d.ts +81 -0
  186. package/dist/skill-catalog.d.ts.map +1 -0
  187. package/dist/skill-catalog.js +388 -0
  188. package/dist/skill-catalog.js.map +1 -0
  189. package/dist/skill-router.d.ts +95 -0
  190. package/dist/skill-router.d.ts.map +1 -0
  191. package/dist/skill-router.js +130 -0
  192. package/dist/skill-router.js.map +1 -0
  193. package/dist/storage.d.ts +14 -0
  194. package/dist/storage.d.ts.map +1 -0
  195. package/dist/storage.js +58 -0
  196. package/dist/storage.js.map +1 -0
  197. package/dist/strategy.d.ts +45 -0
  198. package/dist/strategy.d.ts.map +1 -0
  199. package/dist/strategy.js +520 -0
  200. package/dist/strategy.js.map +1 -0
  201. package/dist/tools.d.ts +40 -0
  202. package/dist/tools.d.ts.map +1 -0
  203. package/dist/tools.js +147 -0
  204. package/dist/tools.js.map +1 -0
  205. package/dist/types/agent.d.ts +94 -0
  206. package/dist/types/agent.d.ts.map +1 -0
  207. package/dist/types/agent.js +17 -0
  208. package/dist/types/agent.js.map +1 -0
  209. package/dist/types/capabilities.d.ts +17 -0
  210. package/dist/types/capabilities.d.ts.map +1 -0
  211. package/dist/types/capabilities.js +13 -0
  212. package/dist/types/capabilities.js.map +1 -0
  213. package/dist/types/chat.d.ts +74 -0
  214. package/dist/types/chat.d.ts.map +1 -0
  215. package/dist/types/chat.js +10 -0
  216. package/dist/types/chat.js.map +1 -0
  217. package/dist/types/events.d.ts +115 -0
  218. package/dist/types/events.d.ts.map +1 -0
  219. package/dist/types/events.js +30 -0
  220. package/dist/types/events.js.map +1 -0
  221. package/dist/types/llm.d.ts +89 -0
  222. package/dist/types/llm.d.ts.map +1 -0
  223. package/dist/types/llm.js +12 -0
  224. package/dist/types/llm.js.map +1 -0
  225. package/dist/types/metrics.d.ts +34 -0
  226. package/dist/types/metrics.d.ts.map +1 -0
  227. package/dist/types/metrics.js +10 -0
  228. package/dist/types/metrics.js.map +1 -0
  229. package/dist/types/observer.d.ts +41 -0
  230. package/dist/types/observer.d.ts.map +1 -0
  231. package/dist/types/observer.js +41 -0
  232. package/dist/types/observer.js.map +1 -0
  233. package/dist/types/project-context.d.ts +18 -0
  234. package/dist/types/project-context.d.ts.map +1 -0
  235. package/dist/types/project-context.js +11 -0
  236. package/dist/types/project-context.js.map +1 -0
  237. package/dist/types/runtime.d.ts +71 -0
  238. package/dist/types/runtime.d.ts.map +1 -0
  239. package/dist/types/runtime.js +21 -0
  240. package/dist/types/runtime.js.map +1 -0
  241. package/dist/types/session.d.ts +103 -0
  242. package/dist/types/session.d.ts.map +1 -0
  243. package/dist/types/session.js +11 -0
  244. package/dist/types/session.js.map +1 -0
  245. package/dist/types/storage.d.ts +20 -0
  246. package/dist/types/storage.d.ts.map +1 -0
  247. package/dist/types/storage.js +41 -0
  248. package/dist/types/storage.js.map +1 -0
  249. package/dist/types/strategy.d.ts +124 -0
  250. package/dist/types/strategy.d.ts.map +1 -0
  251. package/dist/types/strategy.js +10 -0
  252. package/dist/types/strategy.js.map +1 -0
  253. package/dist/types/tools.d.ts +154 -0
  254. package/dist/types/tools.d.ts.map +1 -0
  255. package/dist/types/tools.js +11 -0
  256. package/dist/types/tools.js.map +1 -0
  257. package/dist/types/trace.d.ts +175 -0
  258. package/dist/types/trace.d.ts.map +1 -0
  259. package/dist/types/trace.js +26 -0
  260. package/dist/types/trace.js.map +1 -0
  261. package/dist/types/workspace.d.ts +29 -0
  262. package/dist/types/workspace.d.ts.map +1 -0
  263. package/dist/types/workspace.js +18 -0
  264. package/dist/types/workspace.js.map +1 -0
  265. package/package.json +45 -14
  266. package/skills/agent-cli.md +218 -0
  267. package/index.js +0 -2
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Event value codec — round-trip non-JSON-safe values through the log.
3
+ *
4
+ * The naive approach (`JSON.stringify` everything that lands in
5
+ * `args`, `before`, `after`) is lossy for the exact types real
6
+ * Firebase code uses:
7
+ *
8
+ * - `Date` → ISO string. Replay writes `string` where `Date` was.
9
+ * - `Timestamp` (Firestore) → `{ seconds, nanoseconds }` map. Replay
10
+ * writes a MAP, not a Timestamp. Range queries break silently.
11
+ * - `FieldValue.serverTimestamp()` → `{}`. Sentinel never fires.
12
+ * - `Uint8Array` → array of numbers. Bytes corrupted.
13
+ * - `bigint` → throws (JSON.stringify can't serialize bigint).
14
+ *
15
+ * This module provides a small, extensible codec layer. The default
16
+ * codec handles the universal cases (Date / Uint8Array / bigint) via
17
+ * tagged envelopes. Hosts with domain-specific types (Firestore
18
+ * Timestamp, FieldValue, DocumentReference) compose their own codec
19
+ * on top — see `composeCodecs` + the AGENTS.md recipe.
20
+ *
21
+ * Not handled: `undefined`. Firestore doesn't write `undefined` to
22
+ * docs (it throws), and JSON.stringify drops `undefined`-valued
23
+ * object properties before we ever see them. Encoding it would
24
+ * require a "no-transform" sentinel that the walker collides with;
25
+ * not worth the complexity for a value real Firebase code never
26
+ * produces.
27
+ *
28
+ * Tagged envelope shape: `{ "__pyric": "<tag>", ...fields }`. The
29
+ * `__pyric` prefix makes encoded values self-describing and the
30
+ * round-trip lossless. Hosts using `__pyric` for their own things
31
+ * SHOULD pick a different prefix.
32
+ */
33
+ export declare const ENVELOPE_KEY: "__pyric";
34
+ export interface EventValueCodec {
35
+ /** Convert a value into a JSON-safe shape. Identity on already-safe values. */
36
+ encode(value: unknown): unknown;
37
+ /** Invert `encode`. Identity on values that have no envelope. */
38
+ decode(value: unknown): unknown;
39
+ }
40
+ /**
41
+ * Walks a value tree, applying a per-node transform. Returns a new
42
+ * tree (the input is NOT mutated). The transform returns `undefined`
43
+ * for nodes it doesn't want to transform; the walker then recurses
44
+ * into the node's children — BUT only when the node is a plain
45
+ * object or an array. Class instances (anything whose prototype is
46
+ * not `Object.prototype`) are returned as-is so composed codecs
47
+ * don't accidentally Object.entries() through a typed value and
48
+ * rebuild it as a bag-of-fields.
49
+ *
50
+ * Exported so codec authors can build their own codecs correctly —
51
+ * see `codec.ts` header for the pattern.
52
+ */
53
+ export declare function walkValue(value: unknown, transform: (v: unknown) => unknown): unknown;
54
+ /**
55
+ * Default codec — handles universal non-JSON types every consumer
56
+ * needs. Hosts compose Firestore-specific codecs on top via
57
+ * `composeCodecs`.
58
+ */
59
+ export declare const defaultEventValueCodec: EventValueCodec;
60
+ /**
61
+ * Identity codec — pass-through. Use when the host serializes args
62
+ * itself before passing to a wrapped tool (e.g. tool args are
63
+ * already JSON-safe by contract). Cheaper than `defaultEventValueCodec`
64
+ * because it skips the walk.
65
+ */
66
+ export declare const identityCodec: EventValueCodec;
67
+ /**
68
+ * Compose two codecs. The outer codec encodes first, decodes last.
69
+ *
70
+ * composeCodecs(outer, inner)
71
+ * encode(v) → outer.encode(inner.encode(v))
72
+ * decode(v) → inner.decode(outer.decode(v))
73
+ *
74
+ * Typical usage: layer a Firestore codec over the default.
75
+ *
76
+ * const codec = composeCodecs(firestoreCodec, defaultEventValueCodec);
77
+ */
78
+ export declare function composeCodecs(outer: EventValueCodec, inner: EventValueCodec): EventValueCodec;
79
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/events/codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,eAAO,MAAM,YAAY,EAAG,SAAkB,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAChC,iEAAiE;IACjE,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAiBrF;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,eAqCpC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,eAG3B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,eAAe,CAK7F"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Event value codec — round-trip non-JSON-safe values through the log.
3
+ *
4
+ * The naive approach (`JSON.stringify` everything that lands in
5
+ * `args`, `before`, `after`) is lossy for the exact types real
6
+ * Firebase code uses:
7
+ *
8
+ * - `Date` → ISO string. Replay writes `string` where `Date` was.
9
+ * - `Timestamp` (Firestore) → `{ seconds, nanoseconds }` map. Replay
10
+ * writes a MAP, not a Timestamp. Range queries break silently.
11
+ * - `FieldValue.serverTimestamp()` → `{}`. Sentinel never fires.
12
+ * - `Uint8Array` → array of numbers. Bytes corrupted.
13
+ * - `bigint` → throws (JSON.stringify can't serialize bigint).
14
+ *
15
+ * This module provides a small, extensible codec layer. The default
16
+ * codec handles the universal cases (Date / Uint8Array / bigint) via
17
+ * tagged envelopes. Hosts with domain-specific types (Firestore
18
+ * Timestamp, FieldValue, DocumentReference) compose their own codec
19
+ * on top — see `composeCodecs` + the AGENTS.md recipe.
20
+ *
21
+ * Not handled: `undefined`. Firestore doesn't write `undefined` to
22
+ * docs (it throws), and JSON.stringify drops `undefined`-valued
23
+ * object properties before we ever see them. Encoding it would
24
+ * require a "no-transform" sentinel that the walker collides with;
25
+ * not worth the complexity for a value real Firebase code never
26
+ * produces.
27
+ *
28
+ * Tagged envelope shape: `{ "__pyric": "<tag>", ...fields }`. The
29
+ * `__pyric` prefix makes encoded values self-describing and the
30
+ * round-trip lossless. Hosts using `__pyric` for their own things
31
+ * SHOULD pick a different prefix.
32
+ */
33
+ export const ENVELOPE_KEY = '__pyric';
34
+ /**
35
+ * Walks a value tree, applying a per-node transform. Returns a new
36
+ * tree (the input is NOT mutated). The transform returns `undefined`
37
+ * for nodes it doesn't want to transform; the walker then recurses
38
+ * into the node's children — BUT only when the node is a plain
39
+ * object or an array. Class instances (anything whose prototype is
40
+ * not `Object.prototype`) are returned as-is so composed codecs
41
+ * don't accidentally Object.entries() through a typed value and
42
+ * rebuild it as a bag-of-fields.
43
+ *
44
+ * Exported so codec authors can build their own codecs correctly —
45
+ * see `codec.ts` header for the pattern.
46
+ */
47
+ export function walkValue(value, transform) {
48
+ const replaced = transform(value);
49
+ if (replaced !== undefined)
50
+ return replaced;
51
+ if (value === null || typeof value !== 'object')
52
+ return value;
53
+ if (Array.isArray(value))
54
+ return value.map((v) => walkValue(v, transform));
55
+ // Only descend into plain {} objects. A class instance reaches here
56
+ // either because the transform doesn't recognize it (likely the
57
+ // caller's own type — return unchanged), or because we already
58
+ // decoded an envelope into an instance and a *later* pass shouldn't
59
+ // re-walk its fields.
60
+ const proto = Object.getPrototypeOf(value);
61
+ if (proto !== Object.prototype && proto !== null)
62
+ return value;
63
+ const out = {};
64
+ for (const [k, v] of Object.entries(value)) {
65
+ out[k] = walkValue(v, transform);
66
+ }
67
+ return out;
68
+ }
69
+ /**
70
+ * Default codec — handles universal non-JSON types every consumer
71
+ * needs. Hosts compose Firestore-specific codecs on top via
72
+ * `composeCodecs`.
73
+ */
74
+ export const defaultEventValueCodec = {
75
+ encode(value) {
76
+ return walkValue(value, (v) => {
77
+ if (v instanceof Date) {
78
+ return { [ENVELOPE_KEY]: 'Date', iso: v.toISOString() };
79
+ }
80
+ if (v instanceof Uint8Array) {
81
+ return {
82
+ [ENVELOPE_KEY]: 'Uint8Array',
83
+ b64: Buffer.from(v).toString('base64'),
84
+ };
85
+ }
86
+ if (typeof v === 'bigint') {
87
+ return { [ENVELOPE_KEY]: 'bigint', value: v.toString() };
88
+ }
89
+ return undefined;
90
+ });
91
+ },
92
+ decode(value) {
93
+ return walkValue(value, (v) => {
94
+ if (v === null || typeof v !== 'object')
95
+ return undefined;
96
+ if (Array.isArray(v))
97
+ return undefined;
98
+ const obj = v;
99
+ const tag = obj[ENVELOPE_KEY];
100
+ if (typeof tag !== 'string')
101
+ return undefined;
102
+ if (tag === 'Date' && typeof obj['iso'] === 'string') {
103
+ return new Date(obj['iso']);
104
+ }
105
+ if (tag === 'Uint8Array' && typeof obj['b64'] === 'string') {
106
+ return new Uint8Array(Buffer.from(obj['b64'], 'base64'));
107
+ }
108
+ if (tag === 'bigint' && typeof obj['value'] === 'string') {
109
+ return BigInt(obj['value']);
110
+ }
111
+ return undefined;
112
+ });
113
+ },
114
+ };
115
+ /**
116
+ * Identity codec — pass-through. Use when the host serializes args
117
+ * itself before passing to a wrapped tool (e.g. tool args are
118
+ * already JSON-safe by contract). Cheaper than `defaultEventValueCodec`
119
+ * because it skips the walk.
120
+ */
121
+ export const identityCodec = {
122
+ encode: (v) => v,
123
+ decode: (v) => v,
124
+ };
125
+ /**
126
+ * Compose two codecs. The outer codec encodes first, decodes last.
127
+ *
128
+ * composeCodecs(outer, inner)
129
+ * encode(v) → outer.encode(inner.encode(v))
130
+ * decode(v) → inner.decode(outer.decode(v))
131
+ *
132
+ * Typical usage: layer a Firestore codec over the default.
133
+ *
134
+ * const codec = composeCodecs(firestoreCodec, defaultEventValueCodec);
135
+ */
136
+ export function composeCodecs(outer, inner) {
137
+ return {
138
+ encode: (v) => outer.encode(inner.encode(v)),
139
+ decode: (v) => inner.decode(outer.decode(v)),
140
+ };
141
+ }
142
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/events/codec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Pure / browser-safe pieces of the event log surface:
3
+ *
4
+ * - `EventLog`, `AppendDraft` — types describing the writer's
5
+ * contract; consumers (wrap, replay) describe handlers without
6
+ * pulling in the writer implementation.
7
+ * - `HOST_AGENT_ID` — string constant; canonical declaration is
8
+ * `types/events.ts` (also browser-safe).
9
+ * - `generateEventId`, `buildRollbackEvent`, `EventTooLargeError`,
10
+ * `DEFAULT_MAX_EVENT_BYTES` — pure helpers used by both the
11
+ * Node-side writer (`log.ts`) and the browser-safe `wrapMutating`
12
+ * decorator.
13
+ *
14
+ * The Node-side writer (`openEventLog`, `defaultProjectLogDir`) lives
15
+ * in `./log.ts` and imports `node:fs` / `node:os`. Splitting along
16
+ * this axis lets `wrap.ts` and the universal `@inbrowser/agent` entry
17
+ * use the pure helpers without dragging Node imports into browser
18
+ * bundles.
19
+ */
20
+ import type { MutationEvent, MutationEventFilter, ReverseOp } from '../types/events.js';
21
+ export { HOST_AGENT_ID } from '../types/events.js';
22
+ /**
23
+ * Default per-event byte cap. Matches the Linux PIPE_BUF default and
24
+ * stays well inside macOS's atomic-write window. Above this, append
25
+ * atomicity isn't guaranteed and concurrent writers can interleave.
26
+ */
27
+ export declare const DEFAULT_MAX_EVENT_BYTES: number;
28
+ /**
29
+ * Time-prefixed base36 id with an optional per-log sequence so two
30
+ * appends within the same millisecond stay strictly sortable by
31
+ * emission order. Without the sequence the only tiebreaker is the
32
+ * random suffix, which can flip ordering — a real bug for
33
+ * `replayEvents`'s sinceEventId cursor.
34
+ */
35
+ export declare function generateEventId(now?: () => number, sequence?: number): string;
36
+ export declare class EventTooLargeError extends Error {
37
+ readonly bytes: number;
38
+ readonly cap: number;
39
+ readonly tool: string;
40
+ readonly name = "EventTooLargeError";
41
+ constructor(bytes: number, cap: number, tool: string);
42
+ }
43
+ export interface EventLog {
44
+ readonly path: string;
45
+ readonly projectId: string;
46
+ /**
47
+ * Append a single event. `id` + `ts` are auto-populated when absent
48
+ * so callers can pass a partial draft. Returns the full event for
49
+ * convenience (e.g. wrapMutating's plan-then-commit flow).
50
+ */
51
+ append(draft: AppendDraft): MutationEvent;
52
+ /**
53
+ * Read all events matching the filter. Returns an array, not a
54
+ * stream — the log is small (tens to thousands of events).
55
+ */
56
+ read(filter?: MutationEventFilter): MutationEvent[];
57
+ /**
58
+ * Lazily-built cache of event ids that have already been applied
59
+ * by `replayEvents` (i.e. an event with
60
+ * `metadata.type === 'migrate_applied'` referencing them exists).
61
+ * Invalidated on every `append`.
62
+ */
63
+ appliedEventIds(): Set<string>;
64
+ /** Release resources. Idempotent. */
65
+ close(): void;
66
+ }
67
+ export type AppendDraft = Omit<MutationEvent, 'id' | 'ts'> & Partial<Pick<MutationEvent, 'id' | 'ts'>>;
68
+ export declare function buildRollbackEvent(opts: {
69
+ original: MutationEvent;
70
+ reason: 'failure' | 'undo';
71
+ reverseOp?: ReverseOp;
72
+ agent: string;
73
+ sessionId: string;
74
+ now?: () => number;
75
+ }): AppendDraft;
76
+ //# sourceMappingURL=log-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-core.d.ts","sourceRoot":"","sources":["../../src/events/log-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EAEnB,SAAS,EACV,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAY,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,MAAiB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvF;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAJvB,SAAkB,IAAI,wBAAwB;gBAEnC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM;CASxB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAAC;IAC1C;;;OAGG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,aAAa,EAAE,CAAC;IACpD;;;;;OAKG;IACH,eAAe,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,qCAAqC;IACrC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC,GACxD,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;AAE5C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,GAAG,WAAW,CAiBd"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Pure / browser-safe pieces of the event log surface:
3
+ *
4
+ * - `EventLog`, `AppendDraft` — types describing the writer's
5
+ * contract; consumers (wrap, replay) describe handlers without
6
+ * pulling in the writer implementation.
7
+ * - `HOST_AGENT_ID` — string constant; canonical declaration is
8
+ * `types/events.ts` (also browser-safe).
9
+ * - `generateEventId`, `buildRollbackEvent`, `EventTooLargeError`,
10
+ * `DEFAULT_MAX_EVENT_BYTES` — pure helpers used by both the
11
+ * Node-side writer (`log.ts`) and the browser-safe `wrapMutating`
12
+ * decorator.
13
+ *
14
+ * The Node-side writer (`openEventLog`, `defaultProjectLogDir`) lives
15
+ * in `./log.ts` and imports `node:fs` / `node:os`. Splitting along
16
+ * this axis lets `wrap.ts` and the universal `@inbrowser/agent` entry
17
+ * use the pure helpers without dragging Node imports into browser
18
+ * bundles.
19
+ */
20
+ export { HOST_AGENT_ID } from '../types/events.js';
21
+ /**
22
+ * Default per-event byte cap. Matches the Linux PIPE_BUF default and
23
+ * stays well inside macOS's atomic-write window. Above this, append
24
+ * atomicity isn't guaranteed and concurrent writers can interleave.
25
+ */
26
+ export const DEFAULT_MAX_EVENT_BYTES = 64 * 1024;
27
+ /**
28
+ * Time-prefixed base36 id with an optional per-log sequence so two
29
+ * appends within the same millisecond stay strictly sortable by
30
+ * emission order. Without the sequence the only tiebreaker is the
31
+ * random suffix, which can flip ordering — a real bug for
32
+ * `replayEvents`'s sinceEventId cursor.
33
+ */
34
+ export function generateEventId(now = Date.now, sequence) {
35
+ const ts = now().toString(36).padStart(9, '0');
36
+ const seq = sequence !== undefined ? `-${sequence.toString(36).padStart(4, '0')}` : '';
37
+ const rand = Math.random().toString(36).slice(2, 6);
38
+ return `${ts}${seq}-${rand}`;
39
+ }
40
+ export class EventTooLargeError extends Error {
41
+ bytes;
42
+ cap;
43
+ tool;
44
+ name = 'EventTooLargeError';
45
+ constructor(bytes, cap, tool) {
46
+ super(`event for tool=${tool} is ${bytes} bytes, exceeds cap ${cap}. ` +
47
+ `Atomic append is not guaranteed above this size; concurrent writers can interleave. ` +
48
+ `Raise via openEventLog({ maxEventBytes }) only if you accept the loss of atomicity guarantees, ` +
49
+ `or shrink the payload (truncate before/after snapshots, omit large args).`);
50
+ this.bytes = bytes;
51
+ this.cap = cap;
52
+ this.tool = tool;
53
+ }
54
+ }
55
+ export function buildRollbackEvent(opts) {
56
+ const nowFn = opts.now ?? Date.now;
57
+ void nowFn;
58
+ return {
59
+ agent: opts.agent,
60
+ sessionId: opts.sessionId,
61
+ tool: opts.original.tool,
62
+ phase: 'rollback',
63
+ target: opts.original.target,
64
+ reversible: false,
65
+ irreversibleReason: 'rollback events are terminal',
66
+ ...(opts.reverseOp ? { reverseOp: opts.reverseOp } : {}),
67
+ metadata: {
68
+ reason: opts.reason,
69
+ originalEventId: opts.original.id,
70
+ },
71
+ };
72
+ }
73
+ //# sourceMappingURL=log-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-core.js","sourceRoot":"","sources":["../../src/events/log-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AASH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,MAAoB,IAAI,CAAC,GAAG,EAAE,QAAiB;IAC7E,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,GAAG,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAGhC;IACA;IACA;IAJO,IAAI,GAAG,oBAAoB,CAAC;IAC9C,YACW,KAAa,EACb,GAAW,EACX,IAAY;QAErB,KAAK,CACH,kBAAkB,IAAI,OAAO,KAAK,uBAAuB,GAAG,IAAI;YAC9D,sFAAsF;YACtF,iGAAiG;YACjG,2EAA2E,CAC9E,CAAC;QATO,UAAK,GAAL,KAAK,CAAQ;QACb,QAAG,GAAH,GAAG,CAAQ;QACX,SAAI,GAAJ,IAAI,CAAQ;IAQvB,CAAC;CACF;AA8BD,MAAM,UAAU,kBAAkB,CAAC,IAOlC;IACC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACnC,KAAK,KAAK,CAAC;IACX,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;QACxB,KAAK,EAAE,UAAkC;QACzC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;QAC5B,UAAU,EAAE,KAAK;QACjB,kBAAkB,EAAE,8BAA8B;QAClD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,QAAQ,EAAE;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;SAClC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Project event log — NDJSON append-only writer. Node-only.
3
+ *
4
+ * Pure helpers (`generateEventId`, `buildRollbackEvent`, `HOST_AGENT_ID`,
5
+ * `EventTooLargeError`, `DEFAULT_MAX_EVENT_BYTES`) and the `EventLog`
6
+ * + `AppendDraft` types live in `./log-core.ts` — that file is
7
+ * browser-safe and is what `wrap.ts` / `replay.ts` import.
8
+ *
9
+ * Each Firebase project gets one log at
10
+ * `~/.pyric/projects/<projectId>/events.ndjson`. Every mutating tool
11
+ * call emits at least two lines (plan + commit); failures get a
12
+ * rollback line. `agent events` reads + filters; `agent undo` consults
13
+ * the log to find the matching commit event and invoke its reverseOp.
14
+ *
15
+ * Design notes:
16
+ * - **Append-only.** Never rewrite. `agent undo` doesn't delete the
17
+ * committed event; it appends a new `rollback`-phase event that
18
+ * references the original id. This keeps the file replayable.
19
+ * - **Atomic per-event writes.** Each `append()` is one
20
+ * `appendFileSync` call so multi-process writers can't interleave
21
+ * within an event. Events have a hard byte cap (default 64KB) to
22
+ * stay inside the kernel's atomic-append window on Linux + macOS.
23
+ * - **Synchronous IO.** The log is small. A streaming reader would
24
+ * be over-engineering today.
25
+ * - **Injectable fs.** Tests pass a fake `io` object so they don't
26
+ * hit the real disk.
27
+ * - **Codec hook.** `args`, `before`, `after` are run through an
28
+ * `EventValueCodec` on append + decoded on read.
29
+ */
30
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
31
+ import { type EventValueCodec } from './codec.js';
32
+ import { type EventLog } from './log-core.js';
33
+ export { HOST_AGENT_ID, DEFAULT_MAX_EVENT_BYTES, generateEventId, EventTooLargeError, buildRollbackEvent, } from './log-core.js';
34
+ export type { EventLog, AppendDraft } from './log-core.js';
35
+ export declare function defaultProjectLogDir(): string;
36
+ export interface EventLogIO {
37
+ existsSync: typeof existsSync;
38
+ mkdirSync: typeof mkdirSync;
39
+ appendFileSync: typeof appendFileSync;
40
+ readFileSync: typeof readFileSync;
41
+ }
42
+ export interface OpenEventLogOptions {
43
+ projectId: string;
44
+ /** Absolute path to the directory containing per-project subdirs.
45
+ * Defaults to `~/.pyric/projects`. */
46
+ logDir?: string;
47
+ /** Defaults to fs primitives; injectable for tests. */
48
+ io?: EventLogIO;
49
+ /** Injectable clock; defaults to `Date.now`. */
50
+ now?: () => number;
51
+ /** Codec for `args` / `before` / `after`. Default round-trips
52
+ * Date / Uint8Array / bigint / undefined. Pass a composed codec
53
+ * for Firestore types — see `codec.ts:composeCodecs`. */
54
+ codec?: EventValueCodec;
55
+ /** Per-event byte cap. Defaults to 64KB. Exceeding throws
56
+ * `EventTooLargeError`. */
57
+ maxEventBytes?: number;
58
+ }
59
+ export declare function openEventLog(opts: OpenEventLogOptions): EventLog;
60
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/events/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG9E,OAAO,EAAE,KAAK,eAAe,EAA0B,MAAM,YAAY,CAAC;AAC1E,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,eAAe,CAAC;AAMvB,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3D,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,YAAY,EAAE,OAAO,YAAY,CAAC;CACnC;AASD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB;2CACuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;8DAE0D;IAC1D,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;gCAC4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,QAAQ,CA+GhE"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Project event log — NDJSON append-only writer. Node-only.
3
+ *
4
+ * Pure helpers (`generateEventId`, `buildRollbackEvent`, `HOST_AGENT_ID`,
5
+ * `EventTooLargeError`, `DEFAULT_MAX_EVENT_BYTES`) and the `EventLog`
6
+ * + `AppendDraft` types live in `./log-core.ts` — that file is
7
+ * browser-safe and is what `wrap.ts` / `replay.ts` import.
8
+ *
9
+ * Each Firebase project gets one log at
10
+ * `~/.pyric/projects/<projectId>/events.ndjson`. Every mutating tool
11
+ * call emits at least two lines (plan + commit); failures get a
12
+ * rollback line. `agent events` reads + filters; `agent undo` consults
13
+ * the log to find the matching commit event and invoke its reverseOp.
14
+ *
15
+ * Design notes:
16
+ * - **Append-only.** Never rewrite. `agent undo` doesn't delete the
17
+ * committed event; it appends a new `rollback`-phase event that
18
+ * references the original id. This keeps the file replayable.
19
+ * - **Atomic per-event writes.** Each `append()` is one
20
+ * `appendFileSync` call so multi-process writers can't interleave
21
+ * within an event. Events have a hard byte cap (default 64KB) to
22
+ * stay inside the kernel's atomic-append window on Linux + macOS.
23
+ * - **Synchronous IO.** The log is small. A streaming reader would
24
+ * be over-engineering today.
25
+ * - **Injectable fs.** Tests pass a fake `io` object so they don't
26
+ * hit the real disk.
27
+ * - **Codec hook.** `args`, `before`, `after` are run through an
28
+ * `EventValueCodec` on append + decoded on read.
29
+ */
30
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
31
+ import { homedir } from 'node:os';
32
+ import { defaultEventValueCodec } from './codec.js';
33
+ import { DEFAULT_MAX_EVENT_BYTES, EventTooLargeError, generateEventId, } from './log-core.js';
34
+ // Convenience re-exports — Node-side callers can grab everything
35
+ // log-related from one entry. Browser-safe callers (wrap.ts,
36
+ // replay.ts) import from `./log-core.js` directly to avoid pulling
37
+ // `node:fs` into the universal `@inbrowser/agent` entry.
38
+ export { HOST_AGENT_ID, DEFAULT_MAX_EVENT_BYTES, generateEventId, EventTooLargeError, buildRollbackEvent, } from './log-core.js';
39
+ export function defaultProjectLogDir() {
40
+ return `${homedir()}/.pyric/projects`;
41
+ }
42
+ const DEFAULT_IO = {
43
+ existsSync,
44
+ mkdirSync,
45
+ appendFileSync,
46
+ readFileSync,
47
+ };
48
+ export function openEventLog(opts) {
49
+ if (!/^[a-zA-Z0-9_.-]+$/.test(opts.projectId)) {
50
+ throw new Error(`openEventLog: projectId ${JSON.stringify(opts.projectId)} contains disallowed characters; use [a-zA-Z0-9_.-]+`);
51
+ }
52
+ const io = opts.io ?? DEFAULT_IO;
53
+ const now = opts.now ?? Date.now;
54
+ const baseDir = opts.logDir ?? defaultProjectLogDir();
55
+ const projectDir = `${baseDir.replace(/\/$/, '')}/${opts.projectId}`;
56
+ const path = `${projectDir}/events.ndjson`;
57
+ const codec = opts.codec ?? defaultEventValueCodec;
58
+ const maxBytes = opts.maxEventBytes ?? DEFAULT_MAX_EVENT_BYTES;
59
+ if (!io.existsSync(projectDir))
60
+ io.mkdirSync(projectDir, { recursive: true });
61
+ // Strictly-monotonic counter — combined with the millisecond
62
+ // timestamp, makes ids sortable in emission order even when many
63
+ // appends share a `Date.now()` value.
64
+ let sequence = 0;
65
+ let closed = false;
66
+ // Lazy-built cache of `migrate_applied` originalEventIds. Invalidated
67
+ // on every append so the next read rebuilds it.
68
+ let _appliedCache = null;
69
+ function ensureOpen() {
70
+ if (closed)
71
+ throw new Error(`event log ${path} is closed`);
72
+ }
73
+ function appendEvent(draft) {
74
+ ensureOpen();
75
+ const event = {
76
+ id: draft.id ?? generateEventId(now, sequence++),
77
+ ts: draft.ts ?? new Date(now()).toISOString(),
78
+ agent: draft.agent,
79
+ sessionId: draft.sessionId,
80
+ tool: draft.tool,
81
+ ...(draft.args !== undefined ? { args: codec.encode(draft.args) } : {}),
82
+ phase: draft.phase,
83
+ target: draft.target,
84
+ ...(draft.before !== undefined ? { before: codec.encode(draft.before) } : {}),
85
+ ...(draft.after !== undefined ? { after: codec.encode(draft.after) } : {}),
86
+ reversible: draft.reversible,
87
+ ...(draft.irreversibleReason ? { irreversibleReason: draft.irreversibleReason } : {}),
88
+ ...(draft.reverseOp ? { reverseOp: encodeReverseOp(draft.reverseOp, codec) } : {}),
89
+ ...(draft.metadata ? { metadata: draft.metadata } : {}),
90
+ };
91
+ const line = JSON.stringify(event) + '\n';
92
+ const bytes = Buffer.byteLength(line, 'utf8');
93
+ if (bytes > maxBytes) {
94
+ throw new EventTooLargeError(bytes, maxBytes, draft.tool);
95
+ }
96
+ io.appendFileSync(path, line);
97
+ _appliedCache = null;
98
+ return event;
99
+ }
100
+ function readAll(filter) {
101
+ ensureOpen();
102
+ if (!io.existsSync(path))
103
+ return [];
104
+ const raw = io.readFileSync(path, 'utf8');
105
+ if (!raw)
106
+ return [];
107
+ const out = [];
108
+ for (const line of raw.split('\n')) {
109
+ if (!line)
110
+ continue;
111
+ let parsed;
112
+ try {
113
+ parsed = JSON.parse(line);
114
+ }
115
+ catch {
116
+ // Skip malformed lines — append-only files can become corrupt
117
+ // if a writer crashes mid-write. Surfacing as a hard error
118
+ // would prevent `agent events` from ever working again.
119
+ continue;
120
+ }
121
+ const decoded = {
122
+ ...parsed,
123
+ ...(parsed.args !== undefined ? { args: codec.decode(parsed.args) } : {}),
124
+ ...(parsed.before !== undefined ? { before: codec.decode(parsed.before) } : {}),
125
+ ...(parsed.after !== undefined ? { after: codec.decode(parsed.after) } : {}),
126
+ ...(parsed.reverseOp ? { reverseOp: decodeReverseOp(parsed.reverseOp, codec) } : {}),
127
+ };
128
+ if (filter && !matches(decoded, filter))
129
+ continue;
130
+ out.push(decoded);
131
+ }
132
+ return out;
133
+ }
134
+ function appliedEventIds() {
135
+ if (_appliedCache !== null)
136
+ return _appliedCache;
137
+ const set = new Set();
138
+ for (const ev of readAll()) {
139
+ const md = ev.metadata;
140
+ if (md?.type === 'migrate_applied' && typeof md.appliedEventId === 'string') {
141
+ set.add(md.appliedEventId);
142
+ }
143
+ }
144
+ _appliedCache = set;
145
+ return set;
146
+ }
147
+ return {
148
+ path,
149
+ projectId: opts.projectId,
150
+ append: appendEvent,
151
+ read: readAll,
152
+ appliedEventIds,
153
+ close() {
154
+ if (closed)
155
+ return;
156
+ closed = true;
157
+ },
158
+ };
159
+ }
160
+ function encodeReverseOp(op, codec) {
161
+ return {
162
+ tool: op.tool,
163
+ args: codec.encode(op.args),
164
+ ...(op.description ? { description: op.description } : {}),
165
+ };
166
+ }
167
+ function decodeReverseOp(op, codec) {
168
+ return {
169
+ tool: op.tool,
170
+ args: codec.decode(op.args),
171
+ ...(op.description ? { description: op.description } : {}),
172
+ };
173
+ }
174
+ function matches(event, filter) {
175
+ if (filter.id && event.id !== filter.id)
176
+ return false;
177
+ if (filter.sessionId && event.sessionId !== filter.sessionId)
178
+ return false;
179
+ if (filter.tool && event.tool !== filter.tool)
180
+ return false;
181
+ if (filter.agent && event.agent !== filter.agent)
182
+ return false;
183
+ if (filter.phase && event.phase !== filter.phase)
184
+ return false;
185
+ if (filter.targetKind && event.target.kind !== filter.targetKind)
186
+ return false;
187
+ if (filter.since && event.ts < filter.since)
188
+ return false;
189
+ if (filter.until && event.ts >= filter.until)
190
+ return false;
191
+ return true;
192
+ }
193
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/events/log.ts"],"names":[],"mappings":"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"}