@shipfox/api-logs-dto 2.0.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 (51) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +42 -0
  5. package/LICENSE +21 -0
  6. package/dist/events.d.ts +23 -0
  7. package/dist/events.d.ts.map +1 -0
  8. package/dist/events.js +15 -0
  9. package/dist/events.js.map +1 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +4 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/schemas/append.d.ts +29 -0
  15. package/dist/schemas/append.d.ts.map +1 -0
  16. package/dist/schemas/append.js +25 -0
  17. package/dist/schemas/append.js.map +1 -0
  18. package/dist/schemas/index.d.ts +5 -0
  19. package/dist/schemas/index.d.ts.map +1 -0
  20. package/dist/schemas/index.js +6 -0
  21. package/dist/schemas/index.js.map +1 -0
  22. package/dist/schemas/read.d.ts +34 -0
  23. package/dist/schemas/read.d.ts.map +1 -0
  24. package/dist/schemas/read.js +48 -0
  25. package/dist/schemas/read.js.map +1 -0
  26. package/dist/schemas/record.d.ts +178 -0
  27. package/dist/schemas/record.d.ts.map +1 -0
  28. package/dist/schemas/record.js +136 -0
  29. package/dist/schemas/record.js.map +1 -0
  30. package/dist/schemas/session-view.d.ts +178 -0
  31. package/dist/schemas/session-view.d.ts.map +1 -0
  32. package/dist/schemas/session-view.js +73 -0
  33. package/dist/schemas/session-view.js.map +1 -0
  34. package/dist/tsconfig.test.tsbuildinfo +1 -0
  35. package/package.json +55 -0
  36. package/src/events.ts +22 -0
  37. package/src/index.ts +46 -0
  38. package/src/schemas/append.test.ts +50 -0
  39. package/src/schemas/append.ts +55 -0
  40. package/src/schemas/index.ts +45 -0
  41. package/src/schemas/read.test.ts +69 -0
  42. package/src/schemas/read.ts +84 -0
  43. package/src/schemas/record.test.ts +275 -0
  44. package/src/schemas/record.ts +151 -0
  45. package/src/schemas/session-view.test.ts +96 -0
  46. package/src/schemas/session-view.ts +89 -0
  47. package/tsconfig.build.json +9 -0
  48. package/tsconfig.build.tsbuildinfo +1 -0
  49. package/tsconfig.json +3 -0
  50. package/tsconfig.test.json +8 -0
  51. package/vitest.config.ts +3 -0
@@ -0,0 +1,2 @@
1
+ $ shipfox-swc
2
+ Successfully compiled: 7 files with swc (54.53ms)
@@ -0,0 +1 @@
1
+ $ shipfox-tsc-emit
@@ -0,0 +1 @@
1
+ $ shipfox-tsc-check
package/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
1
+ # @shipfox/api-logs-dto
2
+
3
+ ## 2.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1b0d344: Publishes the complete API runtime closure with packed-consumer-safe internal imports and records its exact package set in application releases.
8
+
9
+ ## 0.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - a56748d: Adds ingestion-time agent session parsing with a stored canonical SessionView read endpoint and workflow harness lookup.
14
+ - f92122b: Adds the logs module foundation: a stateless monolith module with its own schema, the runner-facing offset-CAS append endpoint (job-lease authenticated, idempotent, multi-instance safe), a per-job accrual budget with a cap tombstone, and an S3-compatible client targeting Garage at startup. The NDJSON v1 record contract lives in the new `@shipfox/api-logs-dto` package, and `@shipfox/node-fastify` gains a `createRawBodyPlugin({contentType, bodyLimit})` factory for byte-exact request bodies.
15
+ - 4207772: Add the session-authenticated log read endpoint: `GET /steps/:stepId/attempts/:attempt/logs?cursor=N`. One cursor endpoint serves both the live tail and the full history of a step attempt, workspace-scoped through the stream row's denormalized `workspaceId` (a 404 covers both a missing stream and a cross-workspace step, so existence never leaks).
16
+ - Open or closed-but-uncompacted streams return inline NDJSON read from the hot Postgres chunks, walked by chunk `seq` so server-injected control tombstones (`capped`, `runner_lost`) interleave with runner bytes exactly as compaction concatenates them. The inline bytes are therefore byte-identical to the decompressed compacted object. Pages are bounded by `LOG_READ_INLINE_MAX_BYTES` (default 1 MiB), with a `has_more` flag and a `next_cursor` the client drains before it tails.
17
+ - Compacted streams (`object_key` set) return a presigned GET URL (`LOG_READ_URL_TTL_SECONDS`, default 3600) plus `total_bytes`, `expires_at`, and `truncated`, so the browser fetches the object directly and API egress is bypassed.
18
+ - `@shipfox/api-logs-dto` gains `readLogsQuerySchema` and the `readLogsResponseSchema` discriminated union (`inline` or `presigned`) so the backend, client, and E2E helpers share one contract. `@shipfox/api-logs` adds the `@aws-sdk/s3-request-presigner` dependency.
19
+
20
+ ### Patch Changes
21
+
22
+ - f104ff2: Add `@shipfox/client-logs`: the record components for the step-log read stream, composing the `@shipfox/react-ui` log primitives. This covers every process and system record (`output`, `group_start`/`group_end`, `end`, `gap`, `capped`, `runner_lost`); `agent_session` is rendered by the agent-sessions surface.
23
+ - `buildLogTree(records)` is a pure transform that reconstructs the group tree from the flat record list. `group_end` closes the matching `group_id` (so a `group_start` dropped under gap/backlog pressure does not mis-nest), record dispatch is an exhaustive switch, and each group node carries a precomputed `hasError` (a `runner_lost` in its subtree, a genuine failure; `stderr` is a channel, not an error) and subtree line count.
24
+ - `OutputLogRow` renders stdout/stderr (stderr gets a subtle left channel rule, not a background tint), `LogGroup` is a collapsible disclosure with running/duration/incomplete affordances and an inset error bar, the system markers render as timeline rows, and `LogView` is the top-level dispatcher with an empty state. Reviewed in a package-local Storybook captured by Argos (`client-logs`).
25
+ - `@shipfox/api-logs-dto` now measures UTF-8 byte length with `TextEncoder` instead of `node:buffer`, so this shared record contract is browser-safe for the client log viewer. Behavior is identical.
26
+ - `@shipfox/react-ui` gains two shared formatters in `utils`: `formatBytes` (new) and `formatDuration` (an ms-span, sub-second sibling to the existing `humanDuration`), so `client-logs` and future packages share one implementation instead of re-rolling them.
27
+
28
+ - 68e4022: Collapse the log stream `kind` into one stream per `(job, step, attempt)`. `kind` was modeled at the wrong layer: the runner already funnels every record through one spool and one offset axis, so the per-kind split (separate stream rows, identity, and ingest dispatch) was unnecessary server-side modeling. A reader now pulls every record for a step attempt and filters by the record `type` at read time, without passing a kind.
29
+ - The append request drops the `kind` query param and `LogStreamClosedEvent` drops `kind`. `streamKind`/`StreamKind` and the `agent_session` line validator (`parseSessionLine`) are removed.
30
+ - `attempt_streams` identity becomes `(job, step, attempt)`; the `kind` and now-dead `capped` columns are dropped (budget cap is signaled in-band by a `capped` tombstone and tracked in `job_accounting`). The close path injects `capped`/`runner_lost` tombstones uniformly.
31
+ - `LOG_MAX_SESSION_LINE_BYTES` is removed and `LOG_APPEND_BODY_LIMIT_BYTES` is right-sized to 1 MiB. The runner's flush-window comment is corrected to match (the server body limit is now 1 MiB, no longer 8 MiB).
32
+
33
+ Agent-session capture (its own record `type`(s) and runner producer) is deferred to the agent-sessions feature, which will emit those records into this same stream.
34
+
35
+ - d49ee4c: Forward agent step session entries into the logs module as opaque `agent_session` records: the runner tails the pi session file and forwards each verbatim entry over a shared log-stream sink, and the write path stores them with a configurable per-line size cap sized for inline base64 content.
36
+ - 2883ab4: Add a stream `kind` to the logs contract and harden the write path. Streams are now identified by `(job, step, attempt, kind)` with two kinds: `log_stream` (process output) and `agent_session` (verbatim, format-agnostic agent JSONL).
37
+ - The record envelope drops `src` to `{v, ts}`; the stdout/stderr pipe moves to `stream` on output, and control records become a flat `type` discriminator with multi-level named groups (`group_id`/`parent_group_id`, capped depth with overflow flattening).
38
+ - The append validator is split into an appendable union and a read union, so a forged server-only `capped`/`runner_lost` tombstone is rejected. `agent_session` lines are stored verbatim after a whole-line, fatal-UTF-8, JSON-well-formedness check within a configurable line cap; the budget cap never injects an in-band tombstone into a session, and close derives its `capped`/`truncated` flags out of band.
39
+ - The append request carries `kind`; the shared body limit and session line cap are configurable with a startup invariant.
40
+
41
+ - bf8319f: Re-export the schemas through a relative path so the built package loads under a plain Node ESM resolver, not only tsx or vite, which lets Playwright-run E2E suites consume it through `@shipfox/e2e-observe-logs`.
42
+ - 2933c33: Adds drain-boundary Zod validation for current outbox publisher event payloads.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shipfox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ export declare const LOG_STREAM_CLOSED: "logs.stream.closed";
3
+ export declare const logStreamClosedEventSchema: z.ZodObject<{
4
+ workspaceId: z.ZodString;
5
+ jobId: z.ZodString;
6
+ stepId: z.ZodString;
7
+ attempt: z.ZodNumber;
8
+ streamId: z.ZodString;
9
+ }, z.core.$strip>;
10
+ export type LogStreamClosedEvent = z.infer<typeof logStreamClosedEventSchema>;
11
+ export interface LogsEventMap {
12
+ [LOG_STREAM_CLOSED]: LogStreamClosedEvent;
13
+ }
14
+ export declare const logsEventSchemas: {
15
+ "logs.stream.closed": z.ZodObject<{
16
+ workspaceId: z.ZodString;
17
+ jobId: z.ZodString;
18
+ stepId: z.ZodString;
19
+ attempt: z.ZodNumber;
20
+ streamId: z.ZodString;
21
+ }, z.core.$strip>;
22
+ };
23
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAItB,eAAO,MAAM,iBAAiB,EAAG,oBAA6B,CAAC;AAE/D,eAAO,MAAM,0BAA0B;;;;;;iBAMrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,MAAM,WAAW,YAAY;IAC3B,CAAC,iBAAiB,CAAC,EAAE,oBAAoB,CAAC;CAC3C;AAED,eAAO,MAAM,gBAAgB;;;;;;;;CAEoB,CAAC"}
package/dist/events.js ADDED
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ const nonEmptyStringSchema = z.string().nonempty();
3
+ export const LOG_STREAM_CLOSED = 'logs.stream.closed';
4
+ export const logStreamClosedEventSchema = z.object({
5
+ workspaceId: nonEmptyStringSchema,
6
+ jobId: nonEmptyStringSchema,
7
+ stepId: nonEmptyStringSchema,
8
+ attempt: z.number(),
9
+ streamId: nonEmptyStringSchema
10
+ });
11
+ export const logsEventSchemas = {
12
+ [LOG_STREAM_CLOSED]: logStreamClosedEventSchema
13
+ };
14
+
15
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/events.ts"],"sourcesContent":["import {z} from 'zod';\n\nconst nonEmptyStringSchema = z.string().nonempty();\n\nexport const LOG_STREAM_CLOSED = 'logs.stream.closed' as const;\n\nexport const logStreamClosedEventSchema = z.object({\n workspaceId: nonEmptyStringSchema,\n jobId: nonEmptyStringSchema,\n stepId: nonEmptyStringSchema,\n attempt: z.number(),\n streamId: nonEmptyStringSchema,\n});\nexport type LogStreamClosedEvent = z.infer<typeof logStreamClosedEventSchema>;\n\nexport interface LogsEventMap {\n [LOG_STREAM_CLOSED]: LogStreamClosedEvent;\n}\n\nexport const logsEventSchemas = {\n [LOG_STREAM_CLOSED]: logStreamClosedEventSchema,\n} satisfies Record<keyof LogsEventMap, z.ZodType>;\n"],"names":["z","nonEmptyStringSchema","string","nonempty","LOG_STREAM_CLOSED","logStreamClosedEventSchema","object","workspaceId","jobId","stepId","attempt","number","streamId","logsEventSchemas"],"mappings":"AAAA,SAAQA,CAAC,QAAO,MAAM;AAEtB,MAAMC,uBAAuBD,EAAEE,MAAM,GAAGC,QAAQ;AAEhD,OAAO,MAAMC,oBAAoB,qBAA8B;AAE/D,OAAO,MAAMC,6BAA6BL,EAAEM,MAAM,CAAC;IACjDC,aAAaN;IACbO,OAAOP;IACPQ,QAAQR;IACRS,SAASV,EAAEW,MAAM;IACjBC,UAAUX;AACZ,GAAG;AAOH,OAAO,MAAMY,mBAAmB;IAC9B,CAACT,kBAAkB,EAAEC;AACvB,EAAkD"}
@@ -0,0 +1,3 @@
1
+ export { LOG_STREAM_CLOSED, type LogStreamClosedEvent, type LogsEventMap, logStreamClosedEventSchema, logsEventSchemas, } from './events.js';
2
+ export { type AppendLogsQueryDto, type AppendLogsResponseDto, appendLogsQuerySchema, appendLogsResponseSchema, type LogRecord, logRecordSchema, MAX_RECORD_DATA_BYTES, MAX_RECORD_NAME_BYTES, type OffsetGapResponseDto, offsetGapResponseSchema, parseLogRecordLine, parseRawLogRecordLine, type RawLogRecord, type ReadLogsQueryDto, type ReadLogsResponseDto, rawLogRecordSchema, readLogsQuerySchema, readLogsResponseSchema, SESSION_VIEW_VERSION, type SessionViewDto, type SessionViewLifecycleRow, type SessionViewMessageRow, type SessionViewRawRow, type SessionViewRow, type SessionViewRowMeta, type SessionViewThinkingRow, type SessionViewToolCallRow, type SessionViewToolResultRow, sessionViewLifecycleRowSchema, sessionViewMessageRowSchema, sessionViewRawRowSchema, sessionViewRowMetaSchema, sessionViewRowSchema, sessionViewSchema, sessionViewThinkingRowSchema, sessionViewToolCallRowSchema, sessionViewToolResultRowSchema, } from './schemas/index.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,KAAK,SAAS,EACd,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,4BAA4B,EAC5B,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { LOG_STREAM_CLOSED, logStreamClosedEventSchema, logsEventSchemas } from './events.js';
2
+ export { appendLogsQuerySchema, appendLogsResponseSchema, logRecordSchema, MAX_RECORD_DATA_BYTES, MAX_RECORD_NAME_BYTES, offsetGapResponseSchema, parseLogRecordLine, parseRawLogRecordLine, rawLogRecordSchema, readLogsQuerySchema, readLogsResponseSchema, SESSION_VIEW_VERSION, sessionViewLifecycleRowSchema, sessionViewMessageRowSchema, sessionViewRawRowSchema, sessionViewRowMetaSchema, sessionViewRowSchema, sessionViewSchema, sessionViewThinkingRowSchema, sessionViewToolCallRowSchema, sessionViewToolResultRowSchema } from './schemas/index.js';
3
+
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n LOG_STREAM_CLOSED,\n type LogStreamClosedEvent,\n type LogsEventMap,\n logStreamClosedEventSchema,\n logsEventSchemas,\n} from './events.js';\nexport {\n type AppendLogsQueryDto,\n type AppendLogsResponseDto,\n appendLogsQuerySchema,\n appendLogsResponseSchema,\n type LogRecord,\n logRecordSchema,\n MAX_RECORD_DATA_BYTES,\n MAX_RECORD_NAME_BYTES,\n type OffsetGapResponseDto,\n offsetGapResponseSchema,\n parseLogRecordLine,\n parseRawLogRecordLine,\n type RawLogRecord,\n type ReadLogsQueryDto,\n type ReadLogsResponseDto,\n rawLogRecordSchema,\n readLogsQuerySchema,\n readLogsResponseSchema,\n SESSION_VIEW_VERSION,\n type SessionViewDto,\n type SessionViewLifecycleRow,\n type SessionViewMessageRow,\n type SessionViewRawRow,\n type SessionViewRow,\n type SessionViewRowMeta,\n type SessionViewThinkingRow,\n type SessionViewToolCallRow,\n type SessionViewToolResultRow,\n sessionViewLifecycleRowSchema,\n sessionViewMessageRowSchema,\n sessionViewRawRowSchema,\n sessionViewRowMetaSchema,\n sessionViewRowSchema,\n sessionViewSchema,\n sessionViewThinkingRowSchema,\n sessionViewToolCallRowSchema,\n sessionViewToolResultRowSchema,\n} from './schemas/index.js';\n"],"names":["LOG_STREAM_CLOSED","logStreamClosedEventSchema","logsEventSchemas","appendLogsQuerySchema","appendLogsResponseSchema","logRecordSchema","MAX_RECORD_DATA_BYTES","MAX_RECORD_NAME_BYTES","offsetGapResponseSchema","parseLogRecordLine","parseRawLogRecordLine","rawLogRecordSchema","readLogsQuerySchema","readLogsResponseSchema","SESSION_VIEW_VERSION","sessionViewLifecycleRowSchema","sessionViewMessageRowSchema","sessionViewRawRowSchema","sessionViewRowMetaSchema","sessionViewRowSchema","sessionViewSchema","sessionViewThinkingRowSchema","sessionViewToolCallRowSchema","sessionViewToolResultRowSchema"],"mappings":"AAAA,SACEA,iBAAiB,EAGjBC,0BAA0B,EAC1BC,gBAAgB,QACX,cAAc;AACrB,SAGEC,qBAAqB,EACrBC,wBAAwB,EAExBC,eAAe,EACfC,qBAAqB,EACrBC,qBAAqB,EAErBC,uBAAuB,EACvBC,kBAAkB,EAClBC,qBAAqB,EAIrBC,kBAAkB,EAClBC,mBAAmB,EACnBC,sBAAsB,EACtBC,oBAAoB,EAUpBC,6BAA6B,EAC7BC,2BAA2B,EAC3BC,uBAAuB,EACvBC,wBAAwB,EACxBC,oBAAoB,EACpBC,iBAAiB,EACjBC,4BAA4B,EAC5BC,4BAA4B,EAC5BC,8BAA8B,QACzB,qBAAqB"}
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Append endpoint contract: `POST .../steps/:stepId/logs?attempt=N&offset=B`.
4
+ *
5
+ * The body is raw NDJSON bytes (whole records, newline-terminated), not a
6
+ * Zod-validated object — it is parsed line by line against the raw log record
7
+ * union (`rawLogRecordSchema`). `offset` is a position in the raw
8
+ * NDJSON spool stream; both `offset` and the returned `committed_length` are
9
+ * bounded far below 2^53 by the accrual budget, so JavaScript `number` is safe.
10
+ */
11
+ export declare const appendLogsQuerySchema: z.ZodObject<{
12
+ attempt: z.ZodCoercedNumber<unknown>;
13
+ offset: z.ZodCoercedNumber<unknown>;
14
+ }, z.core.$strip>;
15
+ export type AppendLogsQueryDto = z.infer<typeof appendLogsQuerySchema>;
16
+ export declare const appendLogsResponseSchema: z.ZodObject<{
17
+ committed_length: z.ZodNumber;
18
+ capped: z.ZodBoolean;
19
+ }, z.core.$strip>;
20
+ export type AppendLogsResponseDto = z.infer<typeof appendLogsResponseSchema>;
21
+ /** Body of the 409 returned on an offset gap, so the runner rewinds its spool cursor. */
22
+ export declare const offsetGapResponseSchema: z.ZodObject<{
23
+ code: z.ZodLiteral<"offset-gap">;
24
+ details: z.ZodObject<{
25
+ committed_length: z.ZodNumber;
26
+ }, z.core.$strip>;
27
+ }, z.core.$strip>;
28
+ export type OffsetGapResponseDto = z.infer<typeof offsetGapResponseSchema>;
29
+ //# sourceMappingURL=append.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../../src/schemas/append.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB;;;iBAchC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEvE,eAAO,MAAM,wBAAwB;;;iBASnC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE7E,yFAAyF;AACzF,eAAO,MAAM,uBAAuB;;;;;iBASlC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Append endpoint contract: `POST .../steps/:stepId/logs?attempt=N&offset=B`.
4
+ *
5
+ * The body is raw NDJSON bytes (whole records, newline-terminated), not a
6
+ * Zod-validated object — it is parsed line by line against the raw log record
7
+ * union (`rawLogRecordSchema`). `offset` is a position in the raw
8
+ * NDJSON spool stream; both `offset` and the returned `committed_length` are
9
+ * bounded far below 2^53 by the accrual budget, so JavaScript `number` is safe.
10
+ */ export const appendLogsQuerySchema = z.object({
11
+ attempt: z.coerce.number().int().min(1).max(2_147_483_647).describe('Attempt number of the step this chunk belongs to.'),
12
+ offset: z.coerce.number().int().min(0).describe('Byte position of this chunk in the raw NDJSON spool. Must equal the server-held committed length: an earlier offset is acknowledged as already applied, a later offset returns 409 so the runner rewinds.')
13
+ });
14
+ export const appendLogsResponseSchema = z.object({
15
+ committed_length: z.number().int().min(0).describe('New server-held byte position after this chunk was applied.'),
16
+ capped: z.boolean().describe('When true, the per-job log budget is exhausted and further output is dropped.')
17
+ });
18
+ /** Body of the 409 returned on an offset gap, so the runner rewinds its spool cursor. */ export const offsetGapResponseSchema = z.object({
19
+ code: z.literal('offset-gap'),
20
+ details: z.object({
21
+ committed_length: z.number().int().min(0).describe('Current server-held committed length the runner should rewind to.')
22
+ })
23
+ });
24
+
25
+ //# sourceMappingURL=append.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/schemas/append.ts"],"sourcesContent":["import {z} from 'zod';\n\n/**\n * Append endpoint contract: `POST .../steps/:stepId/logs?attempt=N&offset=B`.\n *\n * The body is raw NDJSON bytes (whole records, newline-terminated), not a\n * Zod-validated object — it is parsed line by line against the raw log record\n * union (`rawLogRecordSchema`). `offset` is a position in the raw\n * NDJSON spool stream; both `offset` and the returned `committed_length` are\n * bounded far below 2^53 by the accrual budget, so JavaScript `number` is safe.\n */\nexport const appendLogsQuerySchema = z.object({\n attempt: z.coerce\n .number()\n .int()\n .min(1)\n .max(2_147_483_647)\n .describe('Attempt number of the step this chunk belongs to.'),\n offset: z.coerce\n .number()\n .int()\n .min(0)\n .describe(\n 'Byte position of this chunk in the raw NDJSON spool. Must equal the server-held committed length: an earlier offset is acknowledged as already applied, a later offset returns 409 so the runner rewinds.',\n ),\n});\n\nexport type AppendLogsQueryDto = z.infer<typeof appendLogsQuerySchema>;\n\nexport const appendLogsResponseSchema = z.object({\n committed_length: z\n .number()\n .int()\n .min(0)\n .describe('New server-held byte position after this chunk was applied.'),\n capped: z\n .boolean()\n .describe('When true, the per-job log budget is exhausted and further output is dropped.'),\n});\n\nexport type AppendLogsResponseDto = z.infer<typeof appendLogsResponseSchema>;\n\n/** Body of the 409 returned on an offset gap, so the runner rewinds its spool cursor. */\nexport const offsetGapResponseSchema = z.object({\n code: z.literal('offset-gap'),\n details: z.object({\n committed_length: z\n .number()\n .int()\n .min(0)\n .describe('Current server-held committed length the runner should rewind to.'),\n }),\n});\n\nexport type OffsetGapResponseDto = z.infer<typeof offsetGapResponseSchema>;\n"],"names":["z","appendLogsQuerySchema","object","attempt","coerce","number","int","min","max","describe","offset","appendLogsResponseSchema","committed_length","capped","boolean","offsetGapResponseSchema","code","literal","details"],"mappings":"AAAA,SAAQA,CAAC,QAAO,MAAM;AAEtB;;;;;;;;CAQC,GACD,OAAO,MAAMC,wBAAwBD,EAAEE,MAAM,CAAC;IAC5CC,SAASH,EAAEI,MAAM,CACdC,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJC,GAAG,CAAC,eACJC,QAAQ,CAAC;IACZC,QAAQV,EAAEI,MAAM,CACbC,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJE,QAAQ,CACP;AAEN,GAAG;AAIH,OAAO,MAAME,2BAA2BX,EAAEE,MAAM,CAAC;IAC/CU,kBAAkBZ,EACfK,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJE,QAAQ,CAAC;IACZI,QAAQb,EACLc,OAAO,GACPL,QAAQ,CAAC;AACd,GAAG;AAIH,uFAAuF,GACvF,OAAO,MAAMM,0BAA0Bf,EAAEE,MAAM,CAAC;IAC9Cc,MAAMhB,EAAEiB,OAAO,CAAC;IAChBC,SAASlB,EAAEE,MAAM,CAAC;QAChBU,kBAAkBZ,EACfK,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJE,QAAQ,CAAC;IACd;AACF,GAAG"}
@@ -0,0 +1,5 @@
1
+ export { type AppendLogsQueryDto, type AppendLogsResponseDto, appendLogsQuerySchema, appendLogsResponseSchema, type OffsetGapResponseDto, offsetGapResponseSchema, } from './append.js';
2
+ export { type ReadLogsQueryDto, type ReadLogsResponseDto, readLogsQuerySchema, readLogsResponseSchema, } from './read.js';
3
+ export { type LogRecord, logRecordSchema, MAX_RECORD_DATA_BYTES, MAX_RECORD_NAME_BYTES, parseLogRecordLine, parseRawLogRecordLine, type RawLogRecord, rawLogRecordSchema, } from './record.js';
4
+ export { SESSION_VIEW_VERSION, type SessionViewDto, type SessionViewLifecycleRow, type SessionViewMessageRow, type SessionViewRawRow, type SessionViewRow, type SessionViewRowMeta, type SessionViewThinkingRow, type SessionViewToolCallRow, type SessionViewToolResultRow, sessionViewLifecycleRowSchema, sessionViewMessageRowSchema, sessionViewRawRowSchema, sessionViewRowMetaSchema, sessionViewRowSchema, sessionViewSchema, sessionViewThinkingRowSchema, sessionViewToolCallRowSchema, sessionViewToolResultRowSchema, } from './session-view.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,SAAS,EACd,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,YAAY,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,4BAA4B,EAC5B,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { appendLogsQuerySchema, appendLogsResponseSchema, offsetGapResponseSchema } from './append.js';
2
+ export { readLogsQuerySchema, readLogsResponseSchema } from './read.js';
3
+ export { logRecordSchema, MAX_RECORD_DATA_BYTES, MAX_RECORD_NAME_BYTES, parseLogRecordLine, parseRawLogRecordLine, rawLogRecordSchema } from './record.js';
4
+ export { SESSION_VIEW_VERSION, sessionViewLifecycleRowSchema, sessionViewMessageRowSchema, sessionViewRawRowSchema, sessionViewRowMetaSchema, sessionViewRowSchema, sessionViewSchema, sessionViewThinkingRowSchema, sessionViewToolCallRowSchema, sessionViewToolResultRowSchema } from './session-view.js';
5
+
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/schemas/index.ts"],"sourcesContent":["export {\n type AppendLogsQueryDto,\n type AppendLogsResponseDto,\n appendLogsQuerySchema,\n appendLogsResponseSchema,\n type OffsetGapResponseDto,\n offsetGapResponseSchema,\n} from './append.js';\nexport {\n type ReadLogsQueryDto,\n type ReadLogsResponseDto,\n readLogsQuerySchema,\n readLogsResponseSchema,\n} from './read.js';\nexport {\n type LogRecord,\n logRecordSchema,\n MAX_RECORD_DATA_BYTES,\n MAX_RECORD_NAME_BYTES,\n parseLogRecordLine,\n parseRawLogRecordLine,\n type RawLogRecord,\n rawLogRecordSchema,\n} from './record.js';\nexport {\n SESSION_VIEW_VERSION,\n type SessionViewDto,\n type SessionViewLifecycleRow,\n type SessionViewMessageRow,\n type SessionViewRawRow,\n type SessionViewRow,\n type SessionViewRowMeta,\n type SessionViewThinkingRow,\n type SessionViewToolCallRow,\n type SessionViewToolResultRow,\n sessionViewLifecycleRowSchema,\n sessionViewMessageRowSchema,\n sessionViewRawRowSchema,\n sessionViewRowMetaSchema,\n sessionViewRowSchema,\n sessionViewSchema,\n sessionViewThinkingRowSchema,\n sessionViewToolCallRowSchema,\n sessionViewToolResultRowSchema,\n} from './session-view.js';\n"],"names":["appendLogsQuerySchema","appendLogsResponseSchema","offsetGapResponseSchema","readLogsQuerySchema","readLogsResponseSchema","logRecordSchema","MAX_RECORD_DATA_BYTES","MAX_RECORD_NAME_BYTES","parseLogRecordLine","parseRawLogRecordLine","rawLogRecordSchema","SESSION_VIEW_VERSION","sessionViewLifecycleRowSchema","sessionViewMessageRowSchema","sessionViewRawRowSchema","sessionViewRowMetaSchema","sessionViewRowSchema","sessionViewSchema","sessionViewThinkingRowSchema","sessionViewToolCallRowSchema","sessionViewToolResultRowSchema"],"mappings":"AAAA,SAGEA,qBAAqB,EACrBC,wBAAwB,EAExBC,uBAAuB,QAClB,cAAc;AACrB,SAGEC,mBAAmB,EACnBC,sBAAsB,QACjB,YAAY;AACnB,SAEEC,eAAe,EACfC,qBAAqB,EACrBC,qBAAqB,EACrBC,kBAAkB,EAClBC,qBAAqB,EAErBC,kBAAkB,QACb,cAAc;AACrB,SACEC,oBAAoB,EAUpBC,6BAA6B,EAC7BC,2BAA2B,EAC3BC,uBAAuB,EACvBC,wBAAwB,EACxBC,oBAAoB,EACpBC,iBAAiB,EACjBC,4BAA4B,EAC5BC,4BAA4B,EAC5BC,8BAA8B,QACzB,oBAAoB"}
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Read endpoint contract: `GET .../steps/:stepId/attempts/:attempt/logs?cursor=N`.
4
+ *
5
+ * `cursor` is an opaque chunk-sequence position, not a byte offset. Server-injected
6
+ * control tombstones (`capped`, `runner_lost`) do not advance the runner byte axis, so
7
+ * the read walks chunks by insertion `seq` to keep every record in stream order. The
8
+ * same `seq` walk backs compaction, so the inline `ndjson` is byte-identical to the
9
+ * decompressed compacted object. Start at 0 and echo back `next_cursor` to page forward.
10
+ */
11
+ export declare const readLogsQuerySchema: z.ZodObject<{
12
+ cursor: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
13
+ }, z.core.$strip>;
14
+ export type ReadLogsQueryDto = z.infer<typeof readLogsQuerySchema>;
15
+ export declare const readLogsResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
16
+ mode: z.ZodLiteral<"inline">;
17
+ ndjson: z.ZodString;
18
+ next_cursor: z.ZodNumber;
19
+ has_more: z.ZodBoolean;
20
+ state: z.ZodEnum<{
21
+ open: "open";
22
+ closed: "closed";
23
+ }>;
24
+ truncated: z.ZodBoolean;
25
+ }, z.core.$strip>, z.ZodObject<{
26
+ mode: z.ZodLiteral<"presigned">;
27
+ url: z.ZodString;
28
+ state: z.ZodLiteral<"closed">;
29
+ expires_at: z.ZodString;
30
+ total_bytes: z.ZodNumber;
31
+ truncated: z.ZodBoolean;
32
+ }, z.core.$strip>], "mode">;
33
+ export type ReadLogsResponseDto = z.infer<typeof readLogsResponseSchema>;
34
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/schemas/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB;;iBAS9B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAwDnE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;2BAGjC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Read endpoint contract: `GET .../steps/:stepId/attempts/:attempt/logs?cursor=N`.
4
+ *
5
+ * `cursor` is an opaque chunk-sequence position, not a byte offset. Server-injected
6
+ * control tombstones (`capped`, `runner_lost`) do not advance the runner byte axis, so
7
+ * the read walks chunks by insertion `seq` to keep every record in stream order. The
8
+ * same `seq` walk backs compaction, so the inline `ndjson` is byte-identical to the
9
+ * decompressed compacted object. Start at 0 and echo back `next_cursor` to page forward.
10
+ */ export const readLogsQuerySchema = z.object({
11
+ cursor: z.coerce.number().int().min(0).default(0).describe('Opaque chunk-sequence cursor. Start at 0; echo back the previous response next_cursor to page forward. Not a byte offset.')
12
+ });
13
+ /**
14
+ * Inline shape: stored NDJSON bytes from `cursor`, parsed client-side with
15
+ * `parseLogRecordLine`. Served while the stream is open or closed but not yet compacted.
16
+ * The bytes carry every record of every type for the `(step, attempt)`; the client
17
+ * filters by record type for display.
18
+ */ const readLogsInlineSchema = z.object({
19
+ mode: z.literal('inline'),
20
+ ndjson: z.string().describe('Stored NDJSON: every record for this (step, attempt) from cursor, in stream order.'),
21
+ next_cursor: z.number().int().min(0).describe('Cursor to pass on the next poll to fetch records after this page.'),
22
+ has_more: z.boolean().describe('True when more buffered records remain past this page; re-poll immediately to drain before tailing at the refresh interval.'),
23
+ state: z.enum([
24
+ 'open',
25
+ 'closed'
26
+ ]).describe('Stream lifecycle: open still accepts appends, closed is terminal.'),
27
+ truncated: z.boolean().describe('True when the stream was force-closed because the runner stopped reporting.')
28
+ });
29
+ /**
30
+ * Presigned shape: a short-lived GET URL to the compacted object, fetched directly by
31
+ * the browser (API egress bypassed). Served once the stream is compacted (`object_key`
32
+ * set). The object is the same NDJSON the inline shape streams, gzip-compressed.
33
+ */ const readLogsPresignedSchema = z.object({
34
+ mode: z.literal('presigned'),
35
+ url: z.string().url().describe('Presigned GET URL for the compacted NDJSON object.'),
36
+ state: z.literal('closed').describe('Compacted streams are closed before they are served by URL.'),
37
+ expires_at: z.string().datetime({
38
+ offset: true
39
+ }).describe('ISO 8601 instant after which the presigned URL stops working.'),
40
+ total_bytes: z.number().int().min(0).describe('Committed append byte position for the attempt. This is the runner CAS axis.'),
41
+ truncated: z.boolean().describe('True when the stream was force-closed because the runner stopped reporting.')
42
+ });
43
+ export const readLogsResponseSchema = z.discriminatedUnion('mode', [
44
+ readLogsInlineSchema,
45
+ readLogsPresignedSchema
46
+ ]);
47
+
48
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/schemas/read.ts"],"sourcesContent":["import {z} from 'zod';\n\n/**\n * Read endpoint contract: `GET .../steps/:stepId/attempts/:attempt/logs?cursor=N`.\n *\n * `cursor` is an opaque chunk-sequence position, not a byte offset. Server-injected\n * control tombstones (`capped`, `runner_lost`) do not advance the runner byte axis, so\n * the read walks chunks by insertion `seq` to keep every record in stream order. The\n * same `seq` walk backs compaction, so the inline `ndjson` is byte-identical to the\n * decompressed compacted object. Start at 0 and echo back `next_cursor` to page forward.\n */\nexport const readLogsQuerySchema = z.object({\n cursor: z.coerce\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\n 'Opaque chunk-sequence cursor. Start at 0; echo back the previous response next_cursor to page forward. Not a byte offset.',\n ),\n});\n\nexport type ReadLogsQueryDto = z.infer<typeof readLogsQuerySchema>;\n\n/**\n * Inline shape: stored NDJSON bytes from `cursor`, parsed client-side with\n * `parseLogRecordLine`. Served while the stream is open or closed but not yet compacted.\n * The bytes carry every record of every type for the `(step, attempt)`; the client\n * filters by record type for display.\n */\nconst readLogsInlineSchema = z.object({\n mode: z.literal('inline'),\n ndjson: z\n .string()\n .describe('Stored NDJSON: every record for this (step, attempt) from cursor, in stream order.'),\n next_cursor: z\n .number()\n .int()\n .min(0)\n .describe('Cursor to pass on the next poll to fetch records after this page.'),\n has_more: z\n .boolean()\n .describe(\n 'True when more buffered records remain past this page; re-poll immediately to drain before tailing at the refresh interval.',\n ),\n state: z\n .enum(['open', 'closed'])\n .describe('Stream lifecycle: open still accepts appends, closed is terminal.'),\n truncated: z\n .boolean()\n .describe('True when the stream was force-closed because the runner stopped reporting.'),\n});\n\n/**\n * Presigned shape: a short-lived GET URL to the compacted object, fetched directly by\n * the browser (API egress bypassed). Served once the stream is compacted (`object_key`\n * set). The object is the same NDJSON the inline shape streams, gzip-compressed.\n */\nconst readLogsPresignedSchema = z.object({\n mode: z.literal('presigned'),\n url: z.string().url().describe('Presigned GET URL for the compacted NDJSON object.'),\n state: z\n .literal('closed')\n .describe('Compacted streams are closed before they are served by URL.'),\n expires_at: z\n .string()\n .datetime({offset: true})\n .describe('ISO 8601 instant after which the presigned URL stops working.'),\n total_bytes: z\n .number()\n .int()\n .min(0)\n .describe('Committed append byte position for the attempt. This is the runner CAS axis.'),\n truncated: z\n .boolean()\n .describe('True when the stream was force-closed because the runner stopped reporting.'),\n});\n\nexport const readLogsResponseSchema = z.discriminatedUnion('mode', [\n readLogsInlineSchema,\n readLogsPresignedSchema,\n]);\n\nexport type ReadLogsResponseDto = z.infer<typeof readLogsResponseSchema>;\n"],"names":["z","readLogsQuerySchema","object","cursor","coerce","number","int","min","default","describe","readLogsInlineSchema","mode","literal","ndjson","string","next_cursor","has_more","boolean","state","enum","truncated","readLogsPresignedSchema","url","expires_at","datetime","offset","total_bytes","readLogsResponseSchema","discriminatedUnion"],"mappings":"AAAA,SAAQA,CAAC,QAAO,MAAM;AAEtB;;;;;;;;CAQC,GACD,OAAO,MAAMC,sBAAsBD,EAAEE,MAAM,CAAC;IAC1CC,QAAQH,EAAEI,MAAM,CACbC,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJC,OAAO,CAAC,GACRC,QAAQ,CACP;AAEN,GAAG;AAIH;;;;;CAKC,GACD,MAAMC,uBAAuBV,EAAEE,MAAM,CAAC;IACpCS,MAAMX,EAAEY,OAAO,CAAC;IAChBC,QAAQb,EACLc,MAAM,GACNL,QAAQ,CAAC;IACZM,aAAaf,EACVK,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJE,QAAQ,CAAC;IACZO,UAAUhB,EACPiB,OAAO,GACPR,QAAQ,CACP;IAEJS,OAAOlB,EACJmB,IAAI,CAAC;QAAC;QAAQ;KAAS,EACvBV,QAAQ,CAAC;IACZW,WAAWpB,EACRiB,OAAO,GACPR,QAAQ,CAAC;AACd;AAEA;;;;CAIC,GACD,MAAMY,0BAA0BrB,EAAEE,MAAM,CAAC;IACvCS,MAAMX,EAAEY,OAAO,CAAC;IAChBU,KAAKtB,EAAEc,MAAM,GAAGQ,GAAG,GAAGb,QAAQ,CAAC;IAC/BS,OAAOlB,EACJY,OAAO,CAAC,UACRH,QAAQ,CAAC;IACZc,YAAYvB,EACTc,MAAM,GACNU,QAAQ,CAAC;QAACC,QAAQ;IAAI,GACtBhB,QAAQ,CAAC;IACZiB,aAAa1B,EACVK,MAAM,GACNC,GAAG,GACHC,GAAG,CAAC,GACJE,QAAQ,CAAC;IACZW,WAAWpB,EACRiB,OAAO,GACPR,QAAQ,CAAC;AACd;AAEA,OAAO,MAAMkB,yBAAyB3B,EAAE4B,kBAAkB,CAAC,QAAQ;IACjElB;IACAW;CACD,EAAE"}
@@ -0,0 +1,178 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * NDJSON log record contract — one JSON object per line, runner-framed.
4
+ *
5
+ * `offset` / `committed_length` are byte positions in the raw append NDJSON spool stream
6
+ * (envelope included) — the offset-CAS axis the runner tracks. The per-job accrual
7
+ * budget charges the normalized NDJSON bytes the server stores, so framing and control records
8
+ * count against it too. The per-record byte caps below bound each record so a single
9
+ * entry's overhead is known and a runner cannot grow storage without moving the
10
+ * budget: `data` is non-empty and <= MAX_RECORD_DATA_BYTES, the group `name` is
11
+ * <= MAX_RECORD_NAME_BYTES, the group ids are <= MAX_RECORD_GROUP_ID_BYTES, and every
12
+ * other field is fixed-shape.
13
+ *
14
+ * The envelope is `{v, ts}`, and every record is discriminated by a single flat
15
+ * `type`. The raw/write and stored/read unions are distinct types: the server-only
16
+ * `capped` / `runner_lost` tombstones are members of the read union only, so a forged
17
+ * tombstone cannot pass append validation.
18
+ *
19
+ * The append-side `agent_session` record carries one verbatim agent session entry line
20
+ * in `data`, forwarded opaquely by the runner. On successful ingest, the API normalizes
21
+ * that raw entry into one or more read-side `agent_session` records whose `row` is the
22
+ * canonical session view row. The raw and normalized records travel through the same log
23
+ * append/read pipe; only their contract at each boundary differs.
24
+ */
25
+ /** Largest decoded `data` payload per record. Longer lines are split by the runner. */
26
+ export declare const MAX_RECORD_DATA_BYTES: number;
27
+ /** Largest `group_start` name. Bounds the only variable-length control field. */
28
+ export declare const MAX_RECORD_NAME_BYTES = 1024;
29
+ /**
30
+ * Largest `group_id` / `parent_group_id`. The runner emits short monotonic ids (`g1`,
31
+ * `g2`, …); this only bounds a forged id from a lease-scoped writer so the ids stay a
32
+ * fixed-shape field like every other record field.
33
+ */
34
+ export declare const MAX_RECORD_GROUP_ID_BYTES = 256;
35
+ /** Records a lease-scoped runner may append. The write path validates against this. */
36
+ export declare const rawLogRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
37
+ type: z.ZodLiteral<"output">;
38
+ stream: z.ZodEnum<{
39
+ stdout: "stdout";
40
+ stderr: "stderr";
41
+ }>;
42
+ data: z.ZodString;
43
+ v: z.ZodLiteral<1>;
44
+ ts: z.ZodNumber;
45
+ }, z.core.$strip>, z.ZodObject<{
46
+ type: z.ZodLiteral<"group_start">;
47
+ group_id: z.ZodString;
48
+ parent_group_id: z.ZodNullable<z.ZodString>;
49
+ name: z.ZodString;
50
+ v: z.ZodLiteral<1>;
51
+ ts: z.ZodNumber;
52
+ }, z.core.$strip>, z.ZodObject<{
53
+ type: z.ZodLiteral<"group_end">;
54
+ group_id: z.ZodString;
55
+ v: z.ZodLiteral<1>;
56
+ ts: z.ZodNumber;
57
+ }, z.core.$strip>, z.ZodObject<{
58
+ type: z.ZodLiteral<"end">;
59
+ total_bytes: z.ZodNumber;
60
+ v: z.ZodLiteral<1>;
61
+ ts: z.ZodNumber;
62
+ }, z.core.$strip>, z.ZodObject<{
63
+ type: z.ZodLiteral<"gap">;
64
+ dropped_bytes: z.ZodNumber;
65
+ v: z.ZodLiteral<1>;
66
+ ts: z.ZodNumber;
67
+ }, z.core.$strip>, z.ZodObject<{
68
+ type: z.ZodLiteral<"agent_session">;
69
+ data: z.ZodString;
70
+ v: z.ZodLiteral<1>;
71
+ ts: z.ZodNumber;
72
+ }, z.core.$strip>], "type">;
73
+ /** Stored/read records: regular records, normalized agent sessions, and tombstones. */
74
+ export declare const logRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
75
+ type: z.ZodLiteral<"output">;
76
+ stream: z.ZodEnum<{
77
+ stdout: "stdout";
78
+ stderr: "stderr";
79
+ }>;
80
+ data: z.ZodString;
81
+ v: z.ZodLiteral<1>;
82
+ ts: z.ZodNumber;
83
+ }, z.core.$strip>, z.ZodObject<{
84
+ type: z.ZodLiteral<"group_start">;
85
+ group_id: z.ZodString;
86
+ parent_group_id: z.ZodNullable<z.ZodString>;
87
+ name: z.ZodString;
88
+ v: z.ZodLiteral<1>;
89
+ ts: z.ZodNumber;
90
+ }, z.core.$strip>, z.ZodObject<{
91
+ type: z.ZodLiteral<"group_end">;
92
+ group_id: z.ZodString;
93
+ v: z.ZodLiteral<1>;
94
+ ts: z.ZodNumber;
95
+ }, z.core.$strip>, z.ZodObject<{
96
+ type: z.ZodLiteral<"end">;
97
+ total_bytes: z.ZodNumber;
98
+ v: z.ZodLiteral<1>;
99
+ ts: z.ZodNumber;
100
+ }, z.core.$strip>, z.ZodObject<{
101
+ type: z.ZodLiteral<"gap">;
102
+ dropped_bytes: z.ZodNumber;
103
+ v: z.ZodLiteral<1>;
104
+ ts: z.ZodNumber;
105
+ }, z.core.$strip>, z.ZodObject<{
106
+ type: z.ZodLiteral<"agent_session">;
107
+ row: z.ZodDiscriminatedUnion<[z.ZodObject<{
108
+ kind: z.ZodLiteral<"message">;
109
+ role: z.ZodString;
110
+ label: z.ZodString;
111
+ meta: z.ZodReadonly<z.ZodArray<z.ZodObject<{
112
+ label: z.ZodString;
113
+ value: z.ZodString;
114
+ inline: z.ZodOptional<z.ZodBoolean>;
115
+ }, z.core.$strip>>>;
116
+ text: z.ZodString;
117
+ terminalFailure: z.ZodBoolean;
118
+ timestamp: z.ZodNumber;
119
+ }, z.core.$strip>, z.ZodObject<{
120
+ kind: z.ZodLiteral<"thinking">;
121
+ text: z.ZodString;
122
+ timestamp: z.ZodNumber;
123
+ }, z.core.$strip>, z.ZodObject<{
124
+ kind: z.ZodLiteral<"tool-call">;
125
+ id: z.ZodNullable<z.ZodString>;
126
+ name: z.ZodString;
127
+ input: z.ZodString;
128
+ timestamp: z.ZodNumber;
129
+ }, z.core.$strip>, z.ZodObject<{
130
+ kind: z.ZodLiteral<"tool-result">;
131
+ toolCallId: z.ZodNullable<z.ZodString>;
132
+ toolName: z.ZodString;
133
+ output: z.ZodString;
134
+ isError: z.ZodBoolean;
135
+ timestamp: z.ZodNumber;
136
+ }, z.core.$strip>, z.ZodObject<{
137
+ kind: z.ZodLiteral<"lifecycle">;
138
+ label: z.ZodString;
139
+ detail: z.ZodNullable<z.ZodString>;
140
+ meta: z.ZodReadonly<z.ZodArray<z.ZodObject<{
141
+ label: z.ZodString;
142
+ value: z.ZodString;
143
+ inline: z.ZodOptional<z.ZodBoolean>;
144
+ }, z.core.$strip>>>;
145
+ tone: z.ZodEnum<{
146
+ error: "error";
147
+ default: "default";
148
+ warning: "warning";
149
+ }>;
150
+ terminalFailure: z.ZodBoolean;
151
+ timestamp: z.ZodNumber;
152
+ }, z.core.$strip>, z.ZodObject<{
153
+ kind: z.ZodLiteral<"raw">;
154
+ label: z.ZodString;
155
+ raw: z.ZodString;
156
+ timestamp: z.ZodNumber;
157
+ }, z.core.$strip>], "kind">;
158
+ v: z.ZodLiteral<1>;
159
+ ts: z.ZodNumber;
160
+ }, z.core.$strip>, z.ZodObject<{
161
+ type: z.ZodLiteral<"capped">;
162
+ v: z.ZodLiteral<1>;
163
+ ts: z.ZodNumber;
164
+ }, z.core.$strip>, z.ZodObject<{
165
+ type: z.ZodLiteral<"runner_lost">;
166
+ v: z.ZodLiteral<1>;
167
+ ts: z.ZodNumber;
168
+ }, z.core.$strip>], "type">;
169
+ export type RawLogRecord = z.infer<typeof rawLogRecordSchema>;
170
+ export type LogRecord = z.infer<typeof logRecordSchema>;
171
+ export declare function parseLogRecordLine(line: string): LogRecord;
172
+ /**
173
+ * Parses one NDJSON line against the raw write union. A forged
174
+ * server-only `capped` / `runner_lost` record fails here even though it is valid
175
+ * under the read union — this is the write-path forgery guard.
176
+ */
177
+ export declare function parseRawLogRecordLine(line: string): RawLogRecord;
178
+ //# sourceMappingURL=record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/schemas/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAGtB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,uFAAuF;AACvF,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAE/C,iFAAiF;AACjF,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AA4E7C,uFAAuF;AACvF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAO7B,CAAC;AAEH,uFAAuF;AACvF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAS1B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAEhE"}