@senpi/runtime 3.0.129 → 3.0.130

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/README.md +12 -4
  2. package/dist/actions/action-events.d.ts +21 -7
  3. package/dist/actions/action-events.d.ts.map +1 -1
  4. package/dist/actions/action-events.js +54 -26
  5. package/dist/actions/action-events.js.map +1 -1
  6. package/dist/actions/action-runtime-module.d.ts.map +1 -1
  7. package/dist/actions/action-runtime-module.js +38 -7
  8. package/dist/actions/action-runtime-module.js.map +1 -1
  9. package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
  10. package/dist/actions/close-position/close-position.action.js +122 -15
  11. package/dist/actions/close-position/close-position.action.js.map +1 -1
  12. package/dist/actions/decision-engine.d.ts.map +1 -1
  13. package/dist/actions/decision-engine.js +15 -2
  14. package/dist/actions/decision-engine.js.map +1 -1
  15. package/dist/actions/event-derivation.d.ts +71 -2
  16. package/dist/actions/event-derivation.d.ts.map +1 -1
  17. package/dist/actions/event-derivation.js +251 -8
  18. package/dist/actions/event-derivation.js.map +1 -1
  19. package/dist/actions/open-position/open-position.action.d.ts +12 -2
  20. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  21. package/dist/actions/open-position/open-position.action.js +144 -41
  22. package/dist/actions/open-position/open-position.action.js.map +1 -1
  23. package/dist/actions/position-tracker/position-tracker.action.d.ts +2 -1
  24. package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
  25. package/dist/actions/position-tracker/position-tracker.action.js +62 -17
  26. package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
  27. package/dist/actions/skipped-signal-results.d.ts +25 -0
  28. package/dist/actions/skipped-signal-results.d.ts.map +1 -0
  29. package/dist/actions/skipped-signal-results.js +71 -0
  30. package/dist/actions/skipped-signal-results.js.map +1 -0
  31. package/dist/actions/store/types.d.ts +9 -2
  32. package/dist/actions/store/types.d.ts.map +1 -1
  33. package/dist/actions/store/types.js.map +1 -1
  34. package/dist/actions/types.d.ts +13 -0
  35. package/dist/actions/types.d.ts.map +1 -1
  36. package/dist/actions/types.js +13 -0
  37. package/dist/actions/types.js.map +1 -1
  38. package/dist/cli/guide-commands.d.ts.map +1 -1
  39. package/dist/cli/guide-commands.js +7 -6
  40. package/dist/cli/guide-commands.js.map +1 -1
  41. package/dist/cli/senpi-commands.d.ts.map +1 -1
  42. package/dist/cli/senpi-commands.js +4 -11
  43. package/dist/cli/senpi-commands.js.map +1 -1
  44. package/dist/dsl/engine-client/event-mapping.d.ts.map +1 -1
  45. package/dist/dsl/engine-client/event-mapping.js +14 -0
  46. package/dist/dsl/engine-client/event-mapping.js.map +1 -1
  47. package/dist/dsl/events/build-closed-event.d.ts +16 -1
  48. package/dist/dsl/events/build-closed-event.d.ts.map +1 -1
  49. package/dist/dsl/events/build-closed-event.js +6 -0
  50. package/dist/dsl/events/build-closed-event.js.map +1 -1
  51. package/dist/dsl/events/handlers.d.ts +7 -0
  52. package/dist/dsl/events/handlers.d.ts.map +1 -1
  53. package/dist/dsl/events/handlers.js +37 -7
  54. package/dist/dsl/events/handlers.js.map +1 -1
  55. package/dist/dsl/monitor/create-monitor.d.ts +6 -2
  56. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  57. package/dist/dsl/monitor/create-monitor.js +15 -9
  58. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  59. package/dist/dsl/monitor/dsl-failure-events.d.ts +2 -0
  60. package/dist/dsl/monitor/dsl-failure-events.d.ts.map +1 -1
  61. package/dist/dsl/monitor/dsl-failure-events.js +2 -1
  62. package/dist/dsl/monitor/dsl-failure-events.js.map +1 -1
  63. package/dist/dsl/monitor/process-one-position.d.ts +1 -0
  64. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  65. package/dist/dsl/monitor/process-one-position.js +59 -25
  66. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  67. package/dist/dsl/plugin/index.d.ts +8 -2
  68. package/dist/dsl/plugin/index.d.ts.map +1 -1
  69. package/dist/dsl/plugin/index.js +8 -6
  70. package/dist/dsl/plugin/index.js.map +1 -1
  71. package/dist/health/types.d.ts +13 -0
  72. package/dist/health/types.d.ts.map +1 -1
  73. package/dist/health/types.js +12 -0
  74. package/dist/health/types.js.map +1 -1
  75. package/dist/index.d.ts +27 -4
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +251 -39
  78. package/dist/index.js.map +1 -1
  79. package/dist/runtime/action-registry.d.ts.map +1 -1
  80. package/dist/runtime/action-registry.js +4 -3
  81. package/dist/runtime/action-registry.js.map +1 -1
  82. package/dist/runtime/auto-update/coordinator.d.ts +13 -6
  83. package/dist/runtime/auto-update/coordinator.d.ts.map +1 -1
  84. package/dist/runtime/auto-update/coordinator.js +86 -18
  85. package/dist/runtime/auto-update/coordinator.js.map +1 -1
  86. package/dist/runtime/auto-update/run-update-command.d.ts.map +1 -1
  87. package/dist/runtime/auto-update/run-update-command.js +4 -3
  88. package/dist/runtime/auto-update/run-update-command.js.map +1 -1
  89. package/dist/runtime/auto-update/types.d.ts +11 -5
  90. package/dist/runtime/auto-update/types.d.ts.map +1 -1
  91. package/dist/runtime/auto-update/types.js +11 -0
  92. package/dist/runtime/auto-update/types.js.map +1 -1
  93. package/dist/runtime/domain-events.d.ts.map +1 -1
  94. package/dist/runtime/domain-events.js +7 -0
  95. package/dist/runtime/domain-events.js.map +1 -1
  96. package/dist/runtime/lifecycle-events.d.ts +9 -1
  97. package/dist/runtime/lifecycle-events.d.ts.map +1 -1
  98. package/dist/runtime/lifecycle-events.js +11 -2
  99. package/dist/runtime/lifecycle-events.js.map +1 -1
  100. package/dist/runtime/reconcile-run.d.ts +13 -3
  101. package/dist/runtime/reconcile-run.d.ts.map +1 -1
  102. package/dist/runtime/reconcile-run.js +4 -3
  103. package/dist/runtime/reconcile-run.js.map +1 -1
  104. package/dist/runtime/reconcile-state.d.ts +8 -0
  105. package/dist/runtime/reconcile-state.d.ts.map +1 -1
  106. package/dist/runtime/reconcile-state.js +4 -1
  107. package/dist/runtime/reconcile-state.js.map +1 -1
  108. package/dist/runtime/run.d.ts +1 -0
  109. package/dist/runtime/run.d.ts.map +1 -1
  110. package/dist/runtime/run.js.map +1 -1
  111. package/dist/runtime/runtime-schema.js +3 -3
  112. package/dist/runtime/runtime-schema.js.map +1 -1
  113. package/dist/runtime/runtime.d.ts +1 -0
  114. package/dist/runtime/runtime.d.ts.map +1 -1
  115. package/dist/runtime/runtime.js +27 -3
  116. package/dist/runtime/runtime.js.map +1 -1
  117. package/dist/runtime/supervisor/long-running-supervisor.d.ts +13 -0
  118. package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
  119. package/dist/runtime/supervisor/long-running-supervisor.js +1 -0
  120. package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
  121. package/dist/runtime/validate-dsl-position-tracking.d.ts.map +1 -1
  122. package/dist/runtime/validate-dsl-position-tracking.js +2 -1
  123. package/dist/runtime/validate-dsl-position-tracking.js.map +1 -1
  124. package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
  125. package/dist/runtime-api/handlers/ingest-signals.js +1 -0
  126. package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
  127. package/dist/runtime-api/handlers/types.d.ts +5 -0
  128. package/dist/runtime-api/handlers/types.d.ts.map +1 -1
  129. package/dist/runtime-api/intake/ingest-request.d.ts +17 -0
  130. package/dist/runtime-api/intake/ingest-request.d.ts.map +1 -0
  131. package/dist/runtime-api/intake/ingest-request.js +34 -0
  132. package/dist/runtime-api/intake/ingest-request.js.map +1 -0
  133. package/dist/runtime-api/intake/intake-events.d.ts +1 -1
  134. package/dist/runtime-api/intake/intake-events.d.ts.map +1 -1
  135. package/dist/runtime-api/intake/intake-events.js +9 -3
  136. package/dist/runtime-api/intake/intake-events.js.map +1 -1
  137. package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
  138. package/dist/runtime-api/intake/intake-mount.js +4 -19
  139. package/dist/runtime-api/intake/intake-mount.js.map +1 -1
  140. package/dist/runtime-api/intake/process-error-post.d.ts +6 -1
  141. package/dist/runtime-api/intake/process-error-post.d.ts.map +1 -1
  142. package/dist/runtime-api/intake/process-error-post.js +5 -1
  143. package/dist/runtime-api/intake/process-error-post.js.map +1 -1
  144. package/dist/runtime-api/intake/process-signal-post.d.ts +7 -1
  145. package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
  146. package/dist/runtime-api/intake/process-signal-post.js +5 -0
  147. package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
  148. package/dist/runtime-api/intake/scaffold-error-router.js.map +1 -1
  149. package/dist/runtime-api/intake/scaffold-tick-router.d.ts +39 -0
  150. package/dist/runtime-api/intake/scaffold-tick-router.d.ts.map +1 -0
  151. package/dist/runtime-api/intake/scaffold-tick-router.js +122 -0
  152. package/dist/runtime-api/intake/scaffold-tick-router.js.map +1 -0
  153. package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
  154. package/dist/runtime-api/intake/scanner-launcher.js +15 -0
  155. package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
  156. package/dist/runtime-api/intake/types.d.ts +55 -0
  157. package/dist/runtime-api/intake/types.d.ts.map +1 -1
  158. package/dist/runtime-api/routes/signals.d.ts +2 -0
  159. package/dist/runtime-api/routes/signals.d.ts.map +1 -1
  160. package/dist/runtime-api/routes/signals.js +5 -1
  161. package/dist/runtime-api/routes/signals.js.map +1 -1
  162. package/dist/runtime-api/routes/signals.schema.d.ts +43 -0
  163. package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
  164. package/dist/runtime-api/routes/signals.schema.js +43 -0
  165. package/dist/runtime-api/routes/signals.schema.js.map +1 -1
  166. package/dist/runtime-api/server.d.ts +7 -1
  167. package/dist/runtime-api/server.d.ts.map +1 -1
  168. package/dist/runtime-api/server.js +1 -0
  169. package/dist/runtime-api/server.js.map +1 -1
  170. package/dist/scanners/engine/engine.d.ts +22 -1
  171. package/dist/scanners/engine/engine.d.ts.map +1 -1
  172. package/dist/scanners/engine/engine.js +78 -11
  173. package/dist/scanners/engine/engine.js.map +1 -1
  174. package/dist/scanners/engine/lifecycle.d.ts +7 -1
  175. package/dist/scanners/engine/lifecycle.d.ts.map +1 -1
  176. package/dist/scanners/events.d.ts +4 -0
  177. package/dist/scanners/events.d.ts.map +1 -1
  178. package/dist/scanners/events.js +2 -0
  179. package/dist/scanners/events.js.map +1 -1
  180. package/dist/scanners/external/scaffold/delivery.py +194 -25
  181. package/dist/scanners/external/scaffold/scaffold.py +172 -31
  182. package/dist/scanners/external/scaffold/senpi_mcp.py +150 -8
  183. package/dist/scanners/external/scaffold/tick_facts.py +130 -0
  184. package/dist/scanners/external/scaffold/ulid.py +58 -0
  185. package/dist/scanners/external-scanner-receiver.d.ts +17 -0
  186. package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
  187. package/dist/scanners/external-scanner-receiver.js +8 -0
  188. package/dist/scanners/external-scanner-receiver.js.map +1 -1
  189. package/dist/scanners/runtime-module.d.ts +1 -0
  190. package/dist/scanners/runtime-module.d.ts.map +1 -1
  191. package/dist/scanners/runtime-module.js +66 -9
  192. package/dist/scanners/runtime-module.js.map +1 -1
  193. package/dist/telemetry/attributes.d.ts +20 -0
  194. package/dist/telemetry/attributes.d.ts.map +1 -1
  195. package/dist/telemetry/attributes.js +24 -0
  196. package/dist/telemetry/attributes.js.map +1 -1
  197. package/dist/telemetry/event-builders.d.ts +81 -6
  198. package/dist/telemetry/event-builders.d.ts.map +1 -1
  199. package/dist/telemetry/event-builders.js +141 -17
  200. package/dist/telemetry/event-builders.js.map +1 -1
  201. package/dist/telemetry/event-store.d.ts +6 -0
  202. package/dist/telemetry/event-store.d.ts.map +1 -1
  203. package/dist/telemetry/event-store.js +12 -8
  204. package/dist/telemetry/event-store.js.map +1 -1
  205. package/dist/telemetry/live-telemetry.d.ts +238 -0
  206. package/dist/telemetry/live-telemetry.d.ts.map +1 -0
  207. package/dist/telemetry/live-telemetry.js +853 -0
  208. package/dist/telemetry/live-telemetry.js.map +1 -0
  209. package/dist/telemetry/metrics.d.ts +14 -2
  210. package/dist/telemetry/metrics.d.ts.map +1 -1
  211. package/dist/telemetry/metrics.js +19 -4
  212. package/dist/telemetry/metrics.js.map +1 -1
  213. package/dist/telemetry/scanner-stats.d.ts +143 -0
  214. package/dist/telemetry/scanner-stats.d.ts.map +1 -0
  215. package/dist/telemetry/scanner-stats.js +426 -0
  216. package/dist/telemetry/scanner-stats.js.map +1 -0
  217. package/dist/telemetry/scanner-tick-feed.d.ts +87 -0
  218. package/dist/telemetry/scanner-tick-feed.d.ts.map +1 -0
  219. package/dist/telemetry/scanner-tick-feed.js +48 -0
  220. package/dist/telemetry/scanner-tick-feed.js.map +1 -0
  221. package/dist/telemetry/spans/redact-pii.d.ts.map +1 -1
  222. package/dist/telemetry/spans/redact-pii.js +18 -2
  223. package/dist/telemetry/spans/redact-pii.js.map +1 -1
  224. package/dist/telemetry/strategy-topology.d.ts +99 -0
  225. package/dist/telemetry/strategy-topology.d.ts.map +1 -0
  226. package/dist/telemetry/strategy-topology.js +93 -0
  227. package/dist/telemetry/strategy-topology.js.map +1 -0
  228. package/dist/telemetry/telemetry-publisher.d.ts +76 -0
  229. package/dist/telemetry/telemetry-publisher.d.ts.map +1 -0
  230. package/dist/telemetry/telemetry-publisher.js +247 -0
  231. package/dist/telemetry/telemetry-publisher.js.map +1 -0
  232. package/dist/telemetry/tick-frame.d.ts +212 -0
  233. package/dist/telemetry/tick-frame.d.ts.map +1 -0
  234. package/dist/telemetry/tick-frame.js +421 -0
  235. package/dist/telemetry/tick-frame.js.map +1 -0
  236. package/dist/telemetry/timeline-buffer.d.ts +95 -0
  237. package/dist/telemetry/timeline-buffer.d.ts.map +1 -0
  238. package/dist/telemetry/timeline-buffer.js +237 -0
  239. package/dist/telemetry/timeline-buffer.js.map +1 -0
  240. package/dist/telemetry/tracing.d.ts +9 -0
  241. package/dist/telemetry/tracing.d.ts.map +1 -1
  242. package/dist/telemetry/tracing.js +36 -0
  243. package/dist/telemetry/tracing.js.map +1 -1
  244. package/dist/types/dsl/index.d.ts +11 -0
  245. package/dist/types/dsl/index.d.ts.map +1 -1
  246. package/dist/types/scanner.d.ts +15 -0
  247. package/dist/types/scanner.d.ts.map +1 -1
  248. package/dist/utils/event-catalog.d.ts +166 -0
  249. package/dist/utils/event-catalog.d.ts.map +1 -1
  250. package/dist/utils/event-catalog.js +18 -0
  251. package/dist/utils/event-catalog.js.map +1 -1
  252. package/dist/utils/logger.d.ts +4 -1
  253. package/dist/utils/logger.d.ts.map +1 -1
  254. package/dist/utils/logger.js.map +1 -1
  255. package/dist/utils/telemetry-required-log.d.ts +60 -0
  256. package/dist/utils/telemetry-required-log.d.ts.map +1 -0
  257. package/dist/utils/telemetry-required-log.js +105 -0
  258. package/dist/utils/telemetry-required-log.js.map +1 -0
  259. package/dist/utils/ulid.d.ts +9 -0
  260. package/dist/utils/ulid.d.ts.map +1 -0
  261. package/dist/utils/ulid.js +43 -0
  262. package/dist/utils/ulid.js.map +1 -0
  263. package/dist/validate/recipe-checks.d.ts.map +1 -1
  264. package/dist/validate/recipe-checks.js +2 -2
  265. package/dist/validate/recipe-checks.js.map +1 -1
  266. package/openclaw.plugin.json +8 -4
  267. package/package.json +1 -1
@@ -0,0 +1,212 @@
1
+ /**
2
+ * The compact `plugin.senpi.tick` frame: the wire shape, the two detail dials that gate it, and the
3
+ * byte budget it is built under.
4
+ *
5
+ * Shape, and why it is compact. A frame carries the latest finished run of every scanner on the box,
6
+ * so the same 42-character wallet, the same scanner name and the same handful of tool names repeat on
7
+ * every entry. A per-frame dictionary interns them once and each entry references them by index; the
8
+ * timestamps are deltas from one frame-level `t0`; and the keys are one or two characters. Two hundred
9
+ * runtimes at full detail land under a tenth of the frame budget this way, where the long-key shape
10
+ * would not.
11
+ *
12
+ * Short keys stop at this boundary. A client's store expands them once at the reducer and its
13
+ * components keep reading `scannedCount`, never `n`.
14
+ *
15
+ * Two dials, not one. `mcp` gates what the MCP boundary reports (`sw`, `mms`, `c`, `cms`) and `state`
16
+ * gates the author's own state projection (`stc`, `st`), because the two cost very different numbers
17
+ * of bytes and an operator watching a slow venue does not also want every author key on the wire. The
18
+ * tick's own summary facts (`q`, `lag`, `jp`, `cm`) belong to neither, so they ride whenever either
19
+ * dial is up: with both off the frame is the always-keys only, which is the shape a box publishes when
20
+ * it wants nothing but proof of life.
21
+ *
22
+ * Nothing here reaches `logger.event` or `appendDomainEvent`. A tick is a LEVEL — see
23
+ * {@link ../utils/telemetry-required-log.js} for why these facts must not become catalogued events.
24
+ */
25
+ /** How much of one source a frame carries. */
26
+ export type TickDetail = "off" | "summary" | "verbose";
27
+ /** The plugin-config shape: one level for both sources, or a level per source. */
28
+ export type TickTelemetryConfig = TickDetail | {
29
+ mcp?: TickDetail;
30
+ state?: TickDetail;
31
+ };
32
+ /** The resolved dials. `enabled` is false only for a bare `"off"`, which publishes no frame at all. */
33
+ export interface TickTelemetrySettings {
34
+ readonly enabled: boolean;
35
+ readonly mcp: TickDetail;
36
+ readonly state: TickDetail;
37
+ }
38
+ /**
39
+ * The level a source takes when the configuration does not name it.
40
+ *
41
+ * Verbose, not summary: a box is watched by exactly one client over that client's own socket, the
42
+ * frame budget holds two hundred runtimes at this level, and an operator who has to change a setting
43
+ * before the screen can answer why a scanner is slow will not have changed it yet when it matters.
44
+ */
45
+ export declare const DEFAULT_TICK_DETAIL: TickDetail;
46
+ /**
47
+ * Character ceiling for one scanner-authored string inside a tick — an outcome, a state value, a
48
+ * tool argument. Matches the cap the stats payload's free text takes, for the same reason: these
49
+ * carry a stringified throwable or an author's own value, and nothing upstream bounds either.
50
+ */
51
+ export declare const MAX_TICK_TEXT_CHARS = 1024;
52
+ /**
53
+ * Calls recorded for one tick. A scanner that calls a tool in a loop would otherwise put an unbounded
54
+ * list on the wire; past this many the tally still counts them (`c` at summary and `cms` stay whole,
55
+ * because they are read off the scaffold's own totals), and only the per-call detail is cut.
56
+ */
57
+ export declare const MAX_TICK_CALLS = 64;
58
+ /**
59
+ * Bounds for one list-valued argument, mirroring the producer's own per-list bounds: at most this
60
+ * many elements, and no more characters across the whole list than a single string argument is
61
+ * allowed. The frame is a second, independent gate on values the scaffold already bounded, so it
62
+ * must not admit a longer list than the scaffold can send — and a list from any other producer is
63
+ * held to the same terms here.
64
+ *
65
+ * The frame's byte budget is not a substitute. That budget drops a whole ENTRY that does not fit,
66
+ * so without these one scanner's long list would cost that scanner's entire tick rather than the
67
+ * tail of the list. The character bound is counted AFTER the scrub, for the reason `scrubText`
68
+ * gives: a redaction can be longer than the text it replaced, so a bound taken first would bound
69
+ * the input and not what leaves.
70
+ */
71
+ export declare const MAX_TICK_CALL_ARG_LIST_ITEMS = 16;
72
+ export declare const MAX_TICK_CALL_ARG_LIST_CHARS = 1024;
73
+ /**
74
+ * `cm` — the state commit outcome, as a RAW STRING and not a dictionary index. Only `a` `s` `m` `o`
75
+ * `x` are interned; these are a small closed set a client reads directly.
76
+ *
77
+ * A tick that committed normally sends nothing at all: the key exists to make the abnormal endings
78
+ * visible, and the common case is not one of them.
79
+ *
80
+ * - `rolled_back` — the tick was not `ok`, so the scaffold discarded the tick's state mutations.
81
+ * - `persist_failed` — the commit was attempted, the write failed, and the tick was rolled back;
82
+ * state did not advance, which is the stall this key exists to make visible.
83
+ */
84
+ export declare const COMMIT_ROLLED_BACK = "rolled_back";
85
+ export declare const COMMIT_PERSIST_FAILED = "persist_failed";
86
+ /** The commit endings a producer may report. `committed` is the absent case. */
87
+ export type TickCommitOutcome = "committed" | typeof COMMIT_ROLLED_BACK | typeof COMMIT_PERSIST_FAILED;
88
+ /** One MCP tool call a tick made, as the producer's boundary timed it. */
89
+ export interface TickCall {
90
+ readonly tool: string;
91
+ /** Wall time the call took. Absent when the producer reported none; never zero as a stand-in. */
92
+ readonly ms?: number;
93
+ /** The call's arguments. Ride at `mcp: verbose` only, sanitised, scrubbed and capped. */
94
+ readonly args?: Readonly<Record<string, unknown>>;
95
+ /** Set only on a failed call — the leaf error's type, as the boundary classified it. */
96
+ readonly errorType?: string;
97
+ }
98
+ /**
99
+ * One finished run waiting for the next frame, already narrowed to what a tick carries.
100
+ *
101
+ * Every optional field means UNKNOWN when it is absent. A `scannedCount` of `0` is a scanner that
102
+ * looked at nothing; an absent one is a scanner that did not say. The distinction is held from the
103
+ * producer through this frame to the screen, so nothing here may default one to the other.
104
+ */
105
+ export interface PendingTick {
106
+ readonly address: string;
107
+ readonly scannerId: string;
108
+ /** Run status as the producer reports it. Scanner-authored text: scrubbed and capped. */
109
+ readonly outcome: string;
110
+ readonly finishedAt: number;
111
+ readonly signalCount: number;
112
+ readonly scannedCount?: number;
113
+ readonly durationMs?: number;
114
+ /** MCP failures the author's own `except` swallowed this tick. */
115
+ readonly mcpFailures?: number;
116
+ readonly mcpCalls?: readonly TickCall[];
117
+ /** Total time inside MCP this tick, as the producer totalled it. */
118
+ readonly mcpMs?: number;
119
+ /** Consecutive ticks that produced no signal, this one included. */
120
+ readonly quietTicks?: number;
121
+ /** Actual gap since the previous tick minus the configured interval. */
122
+ readonly lagMs?: number;
123
+ /** Signals still awaiting delivery in the producer's journal. */
124
+ readonly journalPending?: number;
125
+ readonly commit?: TickCommitOutcome;
126
+ /** The last COMMITTED state row, scalars only — stale by one tick by construction. */
127
+ readonly state?: Readonly<Record<string, unknown>>;
128
+ /** Fields in that row before sanitising, so `stc` can report the drop. */
129
+ readonly stateFieldCount?: number;
130
+ /** Fields in that row whose value moved since the previous committed row. */
131
+ readonly stateChangedCount?: number;
132
+ }
133
+ /** `c` at `mcp: summary` — how many times each tool was called, keyed by dictionary index. */
134
+ export type TickCallCounts = Record<number, number>;
135
+ /** `c` at `mcp: verbose` — one element per call; the error index appears only on a failed one. */
136
+ export type TickCallDetail = readonly [tool: number, ms: number, args: Record<string, unknown>] | readonly [tool: number, ms: number, args: Record<string, unknown>, err: number];
137
+ /** One tick on the wire. Every key is an index into the frame dictionary or a scalar. */
138
+ export interface TickFrameEntry {
139
+ a: number;
140
+ s: number;
141
+ t: number;
142
+ o: number;
143
+ n?: number;
144
+ g: number;
145
+ ms?: number;
146
+ mms?: number;
147
+ q?: number;
148
+ lag?: number;
149
+ sw?: number;
150
+ jp?: number;
151
+ cm?: string;
152
+ c?: TickCallCounts | TickCallDetail[];
153
+ cms?: number;
154
+ stc?: readonly [changed: number, total: number];
155
+ st?: Record<string, string | number | boolean>;
156
+ }
157
+ /** The per-frame dictionary every index in an entry refers to. */
158
+ export interface TickFrameDictionary {
159
+ /** Wallet addresses, normalised. */
160
+ a: string[];
161
+ /** Scanner ids. */
162
+ s: string[];
163
+ /** MCP tool names. */
164
+ m: string[];
165
+ /** Run outcomes. */
166
+ o: string[];
167
+ /** Error types. */
168
+ x: string[];
169
+ }
170
+ /**
171
+ * A tick frame. No `batchSeq`, and its entries carry no `seq`: this is the current state of a set of
172
+ * scanners, and a client that misses a frame is made whole by the next one rather than by a replay.
173
+ */
174
+ export interface TickFramePayload {
175
+ v: 1;
176
+ e: string;
177
+ /** The frame's time base. Every entry's `t` is a millisecond offset from it. */
178
+ t0: number;
179
+ d: TickFrameDictionary;
180
+ k: TickFrameEntry[];
181
+ }
182
+ /** Scrub one scanner-authored string. `null` means the text could not be vouched for. */
183
+ export type TickScrub = (text: string) => Promise<string | null>;
184
+ export interface TickFrameBuilderOptions {
185
+ readonly epoch: string;
186
+ readonly t0: number;
187
+ readonly settings: TickTelemetrySettings;
188
+ /** Byte ceiling for the built frame. Defaults to the caller's frame budget. */
189
+ readonly maxBytes?: number;
190
+ }
191
+ export interface TickFrameBuilder {
192
+ /**
193
+ * Take one finished run into the frame. Returns false when it did not fit, or when the dial
194
+ * publishes nothing — the frame stays publishable either way.
195
+ */
196
+ add(tick: PendingTick, scrub: TickScrub): Promise<boolean>;
197
+ /** The frame, or `null` when nothing was admitted and there is nothing to publish. */
198
+ build(): TickFramePayload | null;
199
+ }
200
+ /**
201
+ * Read the `tickTelemetry` plugin-config value.
202
+ *
203
+ * Never throws and never leaves the caller without settings: an unusable value falls back to the
204
+ * default and is reported in `invalid` so the caller can warn about it once, at startup, the way an
205
+ * unusable `logLevel` is. A configuration mistake must not be the reason a box publishes nothing.
206
+ */
207
+ export declare function resolveTickTelemetry(value: unknown): {
208
+ settings: TickTelemetrySettings;
209
+ invalid?: string;
210
+ };
211
+ export declare function createTickFrameBuilder(options: TickFrameBuilderOptions): TickFrameBuilder;
212
+ //# sourceMappingURL=tick-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tick-frame.d.ts","sourceRoot":"","sources":["../../src/telemetry/tick-frame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,421 @@
1
+ /**
2
+ * The compact `plugin.senpi.tick` frame: the wire shape, the two detail dials that gate it, and the
3
+ * byte budget it is built under.
4
+ *
5
+ * Shape, and why it is compact. A frame carries the latest finished run of every scanner on the box,
6
+ * so the same 42-character wallet, the same scanner name and the same handful of tool names repeat on
7
+ * every entry. A per-frame dictionary interns them once and each entry references them by index; the
8
+ * timestamps are deltas from one frame-level `t0`; and the keys are one or two characters. Two hundred
9
+ * runtimes at full detail land under a tenth of the frame budget this way, where the long-key shape
10
+ * would not.
11
+ *
12
+ * Short keys stop at this boundary. A client's store expands them once at the reducer and its
13
+ * components keep reading `scannedCount`, never `n`.
14
+ *
15
+ * Two dials, not one. `mcp` gates what the MCP boundary reports (`sw`, `mms`, `c`, `cms`) and `state`
16
+ * gates the author's own state projection (`stc`, `st`), because the two cost very different numbers
17
+ * of bytes and an operator watching a slow venue does not also want every author key on the wire. The
18
+ * tick's own summary facts (`q`, `lag`, `jp`, `cm`) belong to neither, so they ride whenever either
19
+ * dial is up: with both off the frame is the always-keys only, which is the shape a box publishes when
20
+ * it wants nothing but proof of life.
21
+ *
22
+ * Nothing here reaches `logger.event` or `appendDomainEvent`. A tick is a LEVEL — see
23
+ * {@link ../utils/telemetry-required-log.js} for why these facts must not become catalogued events.
24
+ */
25
+ import { capValue } from "./attributes.js";
26
+ import { sanitizeFields as sanitizeScalarFields, sanitizeFieldsWithScalarLists as sanitizeScalarListFields, } from "../utils/telemetry-required-log.js";
27
+ /**
28
+ * The level a source takes when the configuration does not name it.
29
+ *
30
+ * Verbose, not summary: a box is watched by exactly one client over that client's own socket, the
31
+ * frame budget holds two hundred runtimes at this level, and an operator who has to change a setting
32
+ * before the screen can answer why a scanner is slow will not have changed it yet when it matters.
33
+ */
34
+ export const DEFAULT_TICK_DETAIL = "verbose";
35
+ /** The levels a configured value may name; anything else falls back to the default. */
36
+ const TICK_DETAILS = ["off", "summary", "verbose"];
37
+ /**
38
+ * Character ceiling for one scanner-authored string inside a tick — an outcome, a state value, a
39
+ * tool argument. Matches the cap the stats payload's free text takes, for the same reason: these
40
+ * carry a stringified throwable or an author's own value, and nothing upstream bounds either.
41
+ */
42
+ export const MAX_TICK_TEXT_CHARS = 1_024;
43
+ /**
44
+ * Calls recorded for one tick. A scanner that calls a tool in a loop would otherwise put an unbounded
45
+ * list on the wire; past this many the tally still counts them (`c` at summary and `cms` stay whole,
46
+ * because they are read off the scaffold's own totals), and only the per-call detail is cut.
47
+ */
48
+ export const MAX_TICK_CALLS = 64;
49
+ /**
50
+ * Bounds for one list-valued argument, mirroring the producer's own per-list bounds: at most this
51
+ * many elements, and no more characters across the whole list than a single string argument is
52
+ * allowed. The frame is a second, independent gate on values the scaffold already bounded, so it
53
+ * must not admit a longer list than the scaffold can send — and a list from any other producer is
54
+ * held to the same terms here.
55
+ *
56
+ * The frame's byte budget is not a substitute. That budget drops a whole ENTRY that does not fit,
57
+ * so without these one scanner's long list would cost that scanner's entire tick rather than the
58
+ * tail of the list. The character bound is counted AFTER the scrub, for the reason `scrubText`
59
+ * gives: a redaction can be longer than the text it replaced, so a bound taken first would bound
60
+ * the input and not what leaves.
61
+ */
62
+ export const MAX_TICK_CALL_ARG_LIST_ITEMS = 16;
63
+ export const MAX_TICK_CALL_ARG_LIST_CHARS = 1_024;
64
+ /**
65
+ * `cm` — the state commit outcome, as a RAW STRING and not a dictionary index. Only `a` `s` `m` `o`
66
+ * `x` are interned; these are a small closed set a client reads directly.
67
+ *
68
+ * A tick that committed normally sends nothing at all: the key exists to make the abnormal endings
69
+ * visible, and the common case is not one of them.
70
+ *
71
+ * - `rolled_back` — the tick was not `ok`, so the scaffold discarded the tick's state mutations.
72
+ * - `persist_failed` — the commit was attempted, the write failed, and the tick was rolled back;
73
+ * state did not advance, which is the stall this key exists to make visible.
74
+ */
75
+ export const COMMIT_ROLLED_BACK = "rolled_back";
76
+ export const COMMIT_PERSIST_FAILED = "persist_failed";
77
+ /** 128 KiB, the same ceiling the timeline and stats frames are split against. */
78
+ const DEFAULT_MAX_FRAME_BYTES = 128 * 1024;
79
+ /** One comma between two members of the same JSON array. */
80
+ const SEPARATOR_BYTES = 1;
81
+ function isTickDetail(value) {
82
+ return typeof value === "string" && TICK_DETAILS.includes(value);
83
+ }
84
+ /**
85
+ * Read the `tickTelemetry` plugin-config value.
86
+ *
87
+ * Never throws and never leaves the caller without settings: an unusable value falls back to the
88
+ * default and is reported in `invalid` so the caller can warn about it once, at startup, the way an
89
+ * unusable `logLevel` is. A configuration mistake must not be the reason a box publishes nothing.
90
+ */
91
+ export function resolveTickTelemetry(value) {
92
+ const fallback = {
93
+ enabled: true,
94
+ mcp: DEFAULT_TICK_DETAIL,
95
+ state: DEFAULT_TICK_DETAIL,
96
+ };
97
+ if (value === undefined || value === null)
98
+ return { settings: fallback, invalid: undefined };
99
+ if (typeof value === "string") {
100
+ if (!isTickDetail(value)) {
101
+ return { settings: fallback, invalid: `tickTelemetry="${value}"` };
102
+ }
103
+ // A bare level applies to both sources; a bare `off` is the one value that stops the frames
104
+ // themselves, rather than emptying them of everything but the always-keys.
105
+ return { settings: { enabled: value !== "off", mcp: value, state: value } };
106
+ }
107
+ if (typeof value !== "object" || Array.isArray(value)) {
108
+ return { settings: fallback, invalid: `tickTelemetry=${JSON.stringify(value) ?? typeof value}` };
109
+ }
110
+ const raw = value;
111
+ const bad = [];
112
+ const read = (key) => {
113
+ const level = raw[key];
114
+ if (level === undefined)
115
+ return DEFAULT_TICK_DETAIL;
116
+ if (isTickDetail(level))
117
+ return level;
118
+ bad.push(`tickTelemetry.${key}="${String(level)}"`);
119
+ return DEFAULT_TICK_DETAIL;
120
+ };
121
+ const mcp = read("mcp");
122
+ const state = read("state");
123
+ return {
124
+ // The object form never turns the frames off: `{mcp:"off",state:"off"}` is an operator asking
125
+ // for proof of life and nothing else, which is a frame of always-keys — not silence.
126
+ settings: { enabled: true, mcp, state },
127
+ ...(bad.length > 0 ? { invalid: bad.join(", ") } : {}),
128
+ };
129
+ }
130
+ /** Whether a source is at `summary` or better. */
131
+ function atLeastSummary(level) {
132
+ return level !== "off";
133
+ }
134
+ /** A finite, non-negative count, or `undefined` for a value that means nothing. */
135
+ function count(value) {
136
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
137
+ }
138
+ /**
139
+ * Scrub, then cap, one scanner-authored string. The cap is taken AFTER the scrub because a redaction
140
+ * can be longer than the text it replaced, so a cut taken first would bound the input and not what
141
+ * leaves. A string the scrub could not vouch for is dropped rather than passed through.
142
+ */
143
+ async function scrubText(text, scrub) {
144
+ if (text === "")
145
+ return "";
146
+ try {
147
+ const scrubbed = await scrub(text);
148
+ return scrubbed === null ? null : capValue(scrubbed, MAX_TICK_TEXT_CHARS);
149
+ }
150
+ catch {
151
+ // The caller's scrub already reports its own failures; a throw here costs the one string.
152
+ return null;
153
+ }
154
+ }
155
+ /** Every scalar in a bag, scrubbed. Non-scalars are dropped exactly as the required log drops them. */
156
+ async function scrubScalarBag(bag, scrub) {
157
+ const { attributes } = sanitizeScalarFields(bag);
158
+ const out = {};
159
+ for (const key of Object.keys(attributes)) {
160
+ const value = attributes[key];
161
+ if (typeof value !== "string") {
162
+ out[key] = value;
163
+ continue;
164
+ }
165
+ const scrubbed = await scrubText(value, scrub);
166
+ if (scrubbed !== null)
167
+ out[key] = scrubbed;
168
+ }
169
+ return out;
170
+ }
171
+ /**
172
+ * One list argument, scrubbed and bounded — or `null` when the list is not carried at all.
173
+ *
174
+ * Every string element goes through the same scrub a bare string value does, because a list that
175
+ * bypassed redaction would put on the wire exactly what the scrub exists to keep off it. An element
176
+ * the scrub could not vouch for refuses the whole list: at bag level an unvouchable value costs its
177
+ * key, and this list IS one key's value.
178
+ *
179
+ * Elements cut by either bound are replaced by a trailing count, so a shortened list reads as
180
+ * shortened rather than as a shorter call. The marker is a plain string element because a consumer
181
+ * expands dictionary indexes and scalars, and a nested object would not survive that.
182
+ */
183
+ async function scrubScalarList(items, scrub) {
184
+ const kept = [];
185
+ let chars = 0;
186
+ for (const item of items.slice(0, MAX_TICK_CALL_ARG_LIST_ITEMS)) {
187
+ const rendered = typeof item === "string" ? await scrubText(item, scrub) : String(item);
188
+ if (rendered === null)
189
+ return null;
190
+ if (chars + rendered.length > MAX_TICK_CALL_ARG_LIST_CHARS)
191
+ break;
192
+ chars += rendered.length;
193
+ kept.push(typeof item === "string" ? rendered : item);
194
+ }
195
+ if (kept.length < items.length)
196
+ kept.push(`+${items.length - kept.length} more`);
197
+ return kept;
198
+ }
199
+ /**
200
+ * One call's arguments: every scalar as the state projection keeps them, and additionally a list
201
+ * whose every element is a scalar.
202
+ *
203
+ * Which assets a scanner priced is the argument an operator reads first, and it arrives as a list —
204
+ * so an argument bag is the one bag on this frame that needs the wider rule. It is asked for HERE
205
+ * and not in the shared sanitiser: the narrow rule is a contract the required log's consumer and the
206
+ * author's state projection both depend on, and neither may gain lists because an argument bag
207
+ * wanted them.
208
+ */
209
+ async function scrubCallArgs(bag, scrub) {
210
+ const { attributes } = sanitizeScalarListFields(bag);
211
+ const out = {};
212
+ for (const key of Object.keys(attributes)) {
213
+ const value = attributes[key];
214
+ if (Array.isArray(value)) {
215
+ const list = await scrubScalarList(value, scrub);
216
+ if (list !== null)
217
+ out[key] = list;
218
+ continue;
219
+ }
220
+ if (typeof value !== "string") {
221
+ out[key] = value;
222
+ continue;
223
+ }
224
+ const scrubbed = await scrubText(value, scrub);
225
+ if (scrubbed !== null)
226
+ out[key] = scrubbed;
227
+ }
228
+ return out;
229
+ }
230
+ export function createTickFrameBuilder(options) {
231
+ const { epoch, t0, settings } = options;
232
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_FRAME_BYTES;
233
+ const dictionary = { a: [], s: [], m: [], o: [], x: [] };
234
+ const entries = [];
235
+ // What the frame costs before it holds anything. Counted rather than estimated, so the running
236
+ // total below is the size of the frame that goes out and not a sum of approximations.
237
+ let bytes = Buffer.byteLength(JSON.stringify({ v: 1, e: epoch, t0, d: dictionary, k: [] }));
238
+ /**
239
+ * The index of `text` in a dictionary slot, interning it when it is new.
240
+ *
241
+ * `added` accumulates what the new strings cost, so an entry that turns out not to fit can have
242
+ * them taken back out again: a dropped entry must not leave its wallet in the dictionary of a
243
+ * frame that never mentions it.
244
+ */
245
+ function intern(slot, text, added) {
246
+ const list = dictionary[slot];
247
+ const found = list.indexOf(text);
248
+ if (found !== -1)
249
+ return found;
250
+ added.bytes += Buffer.byteLength(JSON.stringify(text)) + (list.length > 0 ? SEPARATOR_BYTES : 0);
251
+ list.push(text);
252
+ return list.length - 1;
253
+ }
254
+ /** Every slot's length, so interning can be undone wholesale. */
255
+ function marks() {
256
+ return {
257
+ a: dictionary.a.length,
258
+ s: dictionary.s.length,
259
+ m: dictionary.m.length,
260
+ o: dictionary.o.length,
261
+ x: dictionary.x.length,
262
+ };
263
+ }
264
+ function restore(mark) {
265
+ dictionary.a.length = mark.a;
266
+ dictionary.s.length = mark.s;
267
+ dictionary.m.length = mark.m;
268
+ dictionary.o.length = mark.o;
269
+ dictionary.x.length = mark.x;
270
+ }
271
+ /**
272
+ * `c` and its two companions, in whichever of the two shapes the MCP dial asks for.
273
+ *
274
+ * Summary is a count per tool: what the scanner did, in the fewest bytes that can say it. Verbose
275
+ * is one element per call with its duration and its arguments, which is what answers where the time
276
+ * went — and `cms` is dropped there because the per-call durations already carry the total.
277
+ */
278
+ async function mcpKeys(tick, scrub, added) {
279
+ if (settings.mcp === "off")
280
+ return {};
281
+ const out = {};
282
+ // A producer that reported no call information at all — an in-process scanner — is not a
283
+ // producer that made no calls. The first leaves `c` off entirely; the second sends it empty.
284
+ const calls = tick.mcpCalls;
285
+ if (calls === undefined) {
286
+ const swallowedOnly = count(tick.mcpFailures);
287
+ if (swallowedOnly !== undefined && swallowedOnly > 0)
288
+ out.sw = swallowedOnly;
289
+ return out;
290
+ }
291
+ // The time split rides with the MCP source and is absent when the tick called no tool at all —
292
+ // a zero would read as "MCP was instant" rather than "MCP was not used".
293
+ const mcpMs = count(tick.mcpMs);
294
+ if (mcpMs !== undefined && calls.length > 0)
295
+ out.mms = mcpMs;
296
+ const swallowed = count(tick.mcpFailures);
297
+ if (swallowed !== undefined && swallowed > 0)
298
+ out.sw = swallowed;
299
+ if (settings.mcp === "summary") {
300
+ const counts = {};
301
+ for (const call of calls) {
302
+ const index = intern("m", capValue(call.tool, MAX_TICK_TEXT_CHARS), added);
303
+ counts[index] = (counts[index] ?? 0) + 1;
304
+ }
305
+ out.c = counts;
306
+ return out;
307
+ }
308
+ const detail = [];
309
+ for (const call of calls.slice(0, MAX_TICK_CALLS)) {
310
+ const tool = intern("m", capValue(call.tool, MAX_TICK_TEXT_CHARS), added);
311
+ const ms = count(call.ms) ?? 0;
312
+ const args = call.args === undefined ? {} : await scrubCallArgs(call.args, scrub);
313
+ if (call.errorType === undefined) {
314
+ detail.push([tool, ms, args]);
315
+ continue;
316
+ }
317
+ const err = intern("x", capValue(call.errorType, MAX_TICK_TEXT_CHARS), added);
318
+ detail.push([tool, ms, args, err]);
319
+ }
320
+ out.c = detail;
321
+ return out;
322
+ }
323
+ /**
324
+ * `cms` rides at BOTH levels, the one number the frame repeats. A client could sum the per-call
325
+ * durations at verbose, but two implementations of the same total disagree eventually, so the box
326
+ * states it and neither side derives it.
327
+ */
328
+ function totalCallMs(tick) {
329
+ return settings.mcp === "off" ? undefined : count(tick.mcpMs);
330
+ }
331
+ /**
332
+ * `stc` at summary, `st` at verbose, nothing at off — exactly one of the two, never both.
333
+ *
334
+ * The projection is the last COMMITTED row, so it is stale by one tick whenever the current tick
335
+ * failed. That is the point: a tick that could not commit is precisely when an operator wants to
336
+ * see what the scanner last agreed on.
337
+ */
338
+ async function stateKeys(tick, scrub) {
339
+ if (settings.state === "off")
340
+ return {};
341
+ if (settings.state === "summary") {
342
+ const changed = count(tick.stateChangedCount);
343
+ const total = count(tick.stateFieldCount);
344
+ if (changed === undefined || total === undefined)
345
+ return {};
346
+ return { stc: [changed, total] };
347
+ }
348
+ if (tick.state === undefined)
349
+ return {};
350
+ return { st: await scrubScalarBag(tick.state, scrub) };
351
+ }
352
+ async function add(tick, scrub) {
353
+ if (!settings.enabled)
354
+ return false;
355
+ const mark = marks();
356
+ const added = { bytes: 0 };
357
+ try {
358
+ const outcome = (await scrubText(tick.outcome, scrub)) ?? "";
359
+ const scanned = count(tick.scannedCount);
360
+ const duration = count(tick.durationMs);
361
+ const summary = atLeastSummary(settings.mcp) || atLeastSummary(settings.state);
362
+ const quiet = summary ? count(tick.quietTicks) : undefined;
363
+ const lag = summary ? count(tick.lagMs) : undefined;
364
+ const journal = summary ? count(tick.journalPending) : undefined;
365
+ const commit = summary && tick.commit !== undefined && tick.commit !== "committed"
366
+ ? tick.commit
367
+ : undefined;
368
+ // The two indexes are taken before the spread below so the dictionary is interned in a fixed
369
+ // order, then the entry is assembled in the CONTRACT's own key order: a frame then reads the
370
+ // way its table does, and two frames of the same shape serialise to the same bytes.
371
+ const a = intern("a", tick.address, added);
372
+ const s = intern("s", tick.scannerId, added);
373
+ const o = intern("o", outcome, added);
374
+ const mcp = await mcpKeys(tick, scrub, added);
375
+ const cms = totalCallMs(tick);
376
+ const state = await stateKeys(tick, scrub);
377
+ const entry = {
378
+ a,
379
+ s,
380
+ t: tick.finishedAt - t0,
381
+ o,
382
+ ...(scanned === undefined ? {} : { n: scanned }),
383
+ g: count(tick.signalCount) ?? 0,
384
+ ...(duration === undefined ? {} : { ms: duration }),
385
+ ...(mcp.mms === undefined ? {} : { mms: mcp.mms }),
386
+ ...(quiet !== undefined && quiet > 0 ? { q: quiet } : {}),
387
+ ...(lag !== undefined && lag > 0 ? { lag } : {}),
388
+ ...(mcp.sw === undefined ? {} : { sw: mcp.sw }),
389
+ ...(journal !== undefined && journal > 0 ? { jp: journal } : {}),
390
+ ...(commit === undefined ? {} : { cm: commit }),
391
+ ...(mcp.c === undefined ? {} : { c: mcp.c }),
392
+ ...(cms === undefined ? {} : { cms }),
393
+ ...(state.stc === undefined ? {} : { stc: state.stc }),
394
+ ...(state.st === undefined ? {} : { st: state.st }),
395
+ };
396
+ // Bytes, not entry count: one non-ASCII character in a scanner-authored string costs up to
397
+ // three of them, and the read limit at the far end counts bytes. The separator is counted with
398
+ // the member it precedes, so the running total is the frame's own size and not a sum under it.
399
+ const cost = added.bytes +
400
+ Buffer.byteLength(JSON.stringify(entry)) +
401
+ (entries.length > 0 ? SEPARATOR_BYTES : 0);
402
+ if (bytes + cost > maxBytes) {
403
+ restore(mark);
404
+ return false;
405
+ }
406
+ entries.push(entry);
407
+ bytes += cost;
408
+ return true;
409
+ }
410
+ catch {
411
+ // A malformed producer value must cost its own tick and nothing else.
412
+ restore(mark);
413
+ return false;
414
+ }
415
+ }
416
+ return {
417
+ add,
418
+ build: () => entries.length === 0 ? null : { v: 1, e: epoch, t0, d: dictionary, k: entries },
419
+ };
420
+ }
421
+ //# sourceMappingURL=tick-frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tick-frame.js","sourceRoot":"","sources":["../../src/telemetry/tick-frame.ts"],"names":[],"mappings":"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"}