iterate 0.2.7 → 0.4.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 (73) hide show
  1. package/README.md +173 -81
  2. package/dist/api.d.ts +643 -0
  3. package/dist/api.mjs +0 -0
  4. package/dist/app-server.d.ts +51 -0
  5. package/dist/app-server.mjs +481 -0
  6. package/dist/app-server.mjs.map +1 -0
  7. package/dist/app-session.d.ts +49 -0
  8. package/dist/app-session.mjs +235 -0
  9. package/dist/app-session.mjs.map +1 -0
  10. package/dist/app.d.ts +29 -0
  11. package/dist/app.mjs +180 -0
  12. package/dist/app.mjs.map +1 -0
  13. package/dist/client/live-state.d.ts +63 -0
  14. package/dist/client/oauth.d.ts +17 -0
  15. package/dist/client/react.d.ts +77 -0
  16. package/dist/client/socket.d.ts +7 -0
  17. package/dist/client.mjs +156 -0
  18. package/dist/client.mjs.map +1 -0
  19. package/dist/expression.d.ts +88 -0
  20. package/dist/expression.mjs +301 -0
  21. package/dist/expression.mjs.map +1 -0
  22. package/dist/lib-BWr-5mFO.mjs +36 -0
  23. package/dist/lib-BWr-5mFO.mjs.map +1 -0
  24. package/dist/lib.d.ts +70 -0
  25. package/dist/lib.mjs +228 -0
  26. package/dist/lib.mjs.map +1 -0
  27. package/dist/node.d.ts +15 -0
  28. package/dist/node.mjs +47 -0
  29. package/dist/node.mjs.map +1 -0
  30. package/dist/oauth-scopes.d.ts +32 -0
  31. package/dist/oauth-scopes.mjs +40 -0
  32. package/dist/oauth-scopes.mjs.map +1 -0
  33. package/dist/oauth.mjs +41 -0
  34. package/dist/oauth.mjs.map +1 -0
  35. package/dist/principal.d.ts +8 -0
  36. package/dist/principal.mjs +8 -0
  37. package/dist/principal.mjs.map +1 -0
  38. package/dist/project-ingress.d.ts +58 -0
  39. package/dist/project-ingress.mjs +104 -0
  40. package/dist/project-ingress.mjs.map +1 -0
  41. package/dist/react.mjs +285 -0
  42. package/dist/react.mjs.map +1 -0
  43. package/dist/sdk/auth.d.ts +25 -0
  44. package/dist/sdk/index.d.ts +155 -0
  45. package/dist/sdk/record-pipelined-steps.d.ts +19 -0
  46. package/dist/sdk.mjs +245 -0
  47. package/dist/sdk.mjs.map +1 -0
  48. package/dist/stream/processor.d.ts +383 -0
  49. package/dist/stream/processor.mjs +605 -0
  50. package/dist/stream/processor.mjs.map +1 -0
  51. package/dist/stream/run.d.ts +61 -0
  52. package/dist/stream/run.mjs +45 -0
  53. package/dist/stream/run.mjs.map +1 -0
  54. package/dist/stream/test-support.d.ts +45 -0
  55. package/dist/stream/test-support.mjs +196 -0
  56. package/dist/stream/test-support.mjs.map +1 -0
  57. package/dist/usingCtx-inzbY1Qz.mjs +57 -0
  58. package/package.json +93 -30
  59. package/bin/iterate.js +0 -86
  60. package/dist/cli-DMS4kJph.mjs +0 -868
  61. package/dist/cli-DMS4kJph.mjs.map +0 -1
  62. package/dist/config-DtnR7Lv7.mjs +0 -170
  63. package/dist/config-DtnR7Lv7.mjs.map +0 -1
  64. package/dist/index.d.mts +0 -5
  65. package/dist/index.d.mts.map +0 -1
  66. package/dist/index.mjs +0 -8
  67. package/dist/index.mjs.map +0 -1
  68. package/dist/stream-tui/agent-chat-terminal.d.mts +0 -1
  69. package/dist/stream-tui/agent-chat-terminal.mjs +0 -933
  70. package/dist/stream-tui/agent-chat-terminal.mjs.map +0 -1
  71. package/dist/worker.d.mts +0 -33
  72. package/dist/worker.mjs +0 -18
  73. package/dist/worker.mjs.map +0 -1
@@ -0,0 +1,383 @@
1
+ import type { SqlStorageValue } from "@cloudflare/workers-types";
2
+ import { z } from "zod";
3
+ /** What a processor declares: its checkpoint slug and reducer version, what it consumes and emits,
4
+ * and its initial state (`defineProcessorContract` below builds one from zod schemas). */
5
+ export type ProcessorContract<State = unknown> = {
6
+ slug: string;
7
+ /** Bumping this re-reduces state from offset 0 (reduce only — side effects never re-run). */
8
+ version: string;
9
+ description?: string;
10
+ /** What it reacts to: type strings, or "*" for every DURABLE event. Ephemeral events are
11
+ * delivered ONLY when their type is named here — `"*"` never sweeps them. */
12
+ consumes: readonly string[];
13
+ /** What its `append` is allowed to emit. */
14
+ emits: readonly string[];
15
+ /** The schema-initial state ("{} with every field defaulted" for zod contracts). */
16
+ initialState: () => State;
17
+ /** The zod payload schema for a consumed event type (owned or a dep's), or undefined if the type
18
+ * is unknown or the contract declares no `events` catalog. The engine validates a consumed event's
19
+ * payload against it before reducing (a malformed payload for a KNOWN event is skipped, never
20
+ * folded). Present on `defineProcessorContract` contracts; a hand-built core contract omits it and
21
+ * reduces unvalidated. */
22
+ payloadSchemaFor?: (type: string) => z.ZodType | undefined;
23
+ };
24
+ /** The stream a processor reduces. `read` answers durable rows plus the proof: `scannedThroughOffset`
25
+ * is how far the read is CONTIGUOUSLY known (never past the durable mark — stream.ts), and `atHead`
26
+ * says whether the page was cut; its length says nothing (a budget cut is short of `limit`). */
27
+ export type ProcessorStream = {
28
+ append(...events: StreamEventInput[]): Promise<StreamEvent[]> | StreamEvent[];
29
+ read(afterOffset?: number, limit?: number): Promise<{
30
+ events: StreamEvent[];
31
+ scannedThroughOffset: number;
32
+ atHead: boolean;
33
+ }>;
34
+ /** This processor's claim on its context's alarm: "come back by `at`" (the context's alarm pass
35
+ * then calls `revive()`), or `null` to release it. Durable on the context, never a log event. */
36
+ claim(at: number | null): Promise<unknown>;
37
+ };
38
+ /** How long after an attempt starts a dead host is revived: the recovery bound. A revive that finds
39
+ * the attempt still in flight claims again with the delay doubled, up to `REVIVE_AFTER_MAX_MS`. */
40
+ export declare const REVIVE_AFTER_MS = 20000;
41
+ export declare const REVIVE_AFTER_MAX_MS: number;
42
+ /** The contiguity proof a delivery carries: the half-open offset window `(after, through]`. A chain
43
+ * of these (each `after` === the previous `through`) is how a subscriber proves it missed nothing. */
44
+ export type ScannedRange = {
45
+ after: number;
46
+ through: number;
47
+ };
48
+ export type ReduceArgs<State, Event = StreamEvent> = {
49
+ event: Event;
50
+ state: State;
51
+ };
52
+ export type ProcessEventArgs<State, Event = StreamEvent,
53
+ /** What `append` takes: `EmittedEventInput<typeof Contract>` for a processor that declares one —
54
+ * each type the contract `emits`, its payload as the catalog spells it. */
55
+ Emitted extends StreamEventInput = StreamEventInput> = {
56
+ /** The consumed event — or `null` for the eventless at-head pass. */
57
+ event: Event | null;
58
+ state: State;
59
+ previousState: State;
60
+ /** Emit (validated against `emits`, provenance-stamped) onto this processor's own stream. Declared
61
+ * as METHODS (not arrow-typed properties) on purpose: a subclass that narrows `Emitted` must stay
62
+ * assignable to `StreamProcessor<State>` (the host's field), and only method parameters are
63
+ * compared bivariantly. */
64
+ append(...events: Emitted[]): Promise<StreamEvent[]>;
65
+ /** Hold the cursor until `work` settles; FIFO with other blockers of the SAME event. */
66
+ blockProcessorWhile: (work: () => Promise<unknown>) => void;
67
+ /** Fire-and-forget attempt; may overtake later events; outcome must be state-recoverable. */
68
+ runInBackground: (work: () => Promise<unknown>) => void;
69
+ delivery: {
70
+ caughtUp: boolean;
71
+ };
72
+ };
73
+ /** THE ONE consumes rule — the processor engine, the subscription delivery loop, and the inline
74
+ * reduces all call this; there is no second copy to drift. `consumes` undefined = every durable event
75
+ * (a subscriber's default). "*" = every durable event. A NAMED type opts that type in, INCLUDING
76
+ * ephemerals ("*" NEVER sweeps ephemerals) — so a live-state watcher spells
77
+ * `consumes: ["events.iterate.com/itx/live-state-changed"]` and filters `payload.key` itself. The wake
78
+ * record (`itx/woken`) is a durable event like any other: a "*" row receives every incarnation's. */
79
+ export declare function consumesEvent(consumes: readonly string[] | undefined, event: {
80
+ type: string;
81
+ ephemeral?: boolean;
82
+ }): boolean;
83
+ /** THE AUTHOR CLASS: a contract, three hooks and one helper. Deps an effect needs arrive through
84
+ * the subclass's own constructor, as for any class. One instance lives as long as its host; a field
85
+ * on it is RUNTIME state (gone with the host), which `projectLiveState` may reduce into the live view. */
86
+ export declare abstract class StreamProcessor<State, Event extends StreamEvent = StreamEvent> {
87
+ abstract readonly contract: ProcessorContract<State>;
88
+ /** Pure reduce. Return the NEXT state (a new object) — or null/undefined to keep the current. The
89
+ * `Event` type param — a discriminated union of the events the contract consumes — narrows
90
+ * `event.payload` per `event.type` inside the body, so no cast is needed; it defaults to the
91
+ * untyped `StreamEvent` for processors that don't declare one. */
92
+ reduce(_args: ReduceArgs<State, Event>): State | null | undefined;
93
+ /** Side-effect hook. Synchronous by design: register async work via the two helpers on args.
94
+ * `append` takes what THIS class's `contract` emits (`EmittedEventInput<this["contract"]>`:
95
+ * a subclass whose `contract` is a defined one gets each emitted type's payload as its catalog
96
+ * spells it; the base, and a hand-built contract, take any input). */
97
+ processEvent(_args: ProcessEventArgs<State, Event, EmittedEventInput<this["contract"]>>): undefined;
98
+ /** The live-state PROJECTION — the shape clients see and the diffs are computed over. DEFAULT: the
99
+ * reduced state verbatim, so every processor is live out of the box; that is deliberate — the
100
+ * delta is an EPHEMERAL event, so "always live" costs an offset and a cheap diff, nothing durable.
101
+ * Override to redact, or to REDUCE IN RUNTIME FIELDS (`return { ...state, lastSeenMs: this.lastSeenMs }`);
102
+ * the engine re-projects after EVERY batch, and a field changed outside a batch needs the host's
103
+ * `publishLiveState()`. */
104
+ projectLiveState(state: State): unknown;
105
+ /** Stable idempotency key namespaced by slug; pass the event being processed for a per-event key. */
106
+ idempotencyKey(key: string, event?: StreamEvent): string;
107
+ }
108
+ /** THE ENGINE: everything below the author's three hooks — the serial chain, the checkpoint, gap
109
+ * repair, the at-head pass, version re-reduces, live-state publishing. Constructed by the host
110
+ * (`StreamProcessorDurableObject`; a test with the stand-ins in test-support.ts). */
111
+ export declare class ProcessorEngine<State> {
112
+ #private;
113
+ readonly processor: StreamProcessor<State>;
114
+ constructor(processor: StreamProcessor<State>, deps: {
115
+ stream: ProcessorStream;
116
+ storage: ReduceCheckpointTable;
117
+ /** The host's word that a subscription row pushes this processor every commit it consumes
118
+ * (`processEventBatch`). The read verbs then trust the head a catch-up read until a push shows
119
+ * a later one; absent, only a push's head is trusted, so an unpushed processor reads each time. */
120
+ fedByPushes?: boolean;
121
+ });
122
+ /** THE SEED READ for live-state clients (LiveState.snapshot), caught up first. */
123
+ liveSnapshot(): Promise<{
124
+ rev: number;
125
+ state: unknown;
126
+ }>;
127
+ /** Emit a delta for the CURRENT projection (reduced + any runtime fields) if it changed. The engine
128
+ * calls this after every batch; the host calls it after a runtime field moved outside a batch. A
129
+ * throwing projection loses only its notification (the client re-seeds on the chain gap). */
130
+ publishLiveState(): void;
131
+ /** THE push method: contiguous → reduce it directly (no read); anything else → gap repair from the
132
+ * own cursor first. Fire-and-forget safe: enqueues on the serial chain. */
133
+ processEventBatch(events: StreamEvent[], range: ScannedRange): Promise<void>;
134
+ /** Catch up from the own checkpoint (a cold boot, the read verbs, the barrier), page by page — a
135
+ * failed batch, a missed push, or a fresh incarnation can never skip a durable event. */
136
+ catchUpFromLog(): Promise<void>;
137
+ /** Reduce-and-effects caught up through the log, then `{ offset, state }`. */
138
+ snapshot(): Promise<{
139
+ offset: number;
140
+ state: State;
141
+ }>;
142
+ /** THE barrier verb (read-your-writes): resolves once processed AT LEAST through `offset`. An
143
+ * offset ABOVE the durable mark (an ephemeral's) is reached only if this processor was pushed it —
144
+ * the log cannot prove past the mark, so a wake alone never advances there. */
145
+ waitUntilProcessed(input: {
146
+ offset: number;
147
+ timeoutMs?: number;
148
+ }): Promise<void>;
149
+ /** THE REVIVE — the context's alarm pass calls this for a due claim (spent by then): catch up
150
+ * from the log and run the at-head pass, so a processor restarts what state says is still owed
151
+ * (rule 3). A fresh incarnation finds nothing in flight and starts it; an attempt still in flight
152
+ * here claims again, later each time (20 s, 40 s, … `REVIVE_AFTER_MAX_MS`). */
153
+ revive(): Promise<void>;
154
+ }
155
+ /** What `append` accepts: the event body, before the stream assigns its committed identity. The
156
+ * append method checks ONE rule by hand: `type` is a non-empty string. */
157
+ export type StreamEventInput = {
158
+ /** `events.iterate.com/<namespace>/<event>` for the platform's types, named by the rules in
159
+ * packages/iterate/README.md#event-types; any other string is the appender's own. */
160
+ type: string;
161
+ payload?: Record<string, unknown>;
162
+ metadata?: Record<string, unknown>;
163
+ /** Provenance: which processor (while processing what) appended this — stamped by the engine's
164
+ * `append` — and WHO: the session's verified principal (src/principal.ts), set by the DO's append
165
+ * root from the session's project token and never taken from a client. */
166
+ source?: {
167
+ /** The durable schedule definition responsible for this occurrence. */
168
+ schedule?: {
169
+ key: string;
170
+ scheduledAtOffset: number;
171
+ at: string;
172
+ /** Attribution of the definition, distinct from the platform writing the occurrence. */
173
+ definedBy?: Omit<NonNullable<StreamEventInput["source"]>, "schedule">;
174
+ };
175
+ processor?: {
176
+ slug: string;
177
+ version: string;
178
+ whileProcessing?: {
179
+ offset: number;
180
+ type: string;
181
+ };
182
+ };
183
+ principal?: {
184
+ actor: string;
185
+ email?: string;
186
+ };
187
+ /** THE CONNECTION the principal acted through: the OAuth grant's id — one per
188
+ * connected client (a Claude Code install, a dash sign-in, a personal token). Stamped beside
189
+ * `principal` by the platform when it appends; absent for the admin secret and the kernel. */
190
+ grant?: string;
191
+ /** THE PLATFORM WROTE THIS FACT, on the principal's behalf:
192
+ * what a processor folding an account's or an organization's facts requires — a client can
193
+ * append any type to a context it holds, never this. */
194
+ platform?: true;
195
+ };
196
+ /** Same key + same body = dedupe (the existing event is returned); different body = loud error. */
197
+ idempotencyKey?: string;
198
+ /** OPTIONAL PRECONDITION: land at exactly this offset or refuse the whole batch with
199
+ * OFFSET_CONFLICT — "nothing has happened since I last looked". Never stored in the body. */
200
+ offset?: number;
201
+ /** An EPHEMERAL event rides the stream to live subscribers but is NEVER persisted: it consumes an
202
+ * offset, triggers zero writes, and its body is gone the moment the incarnation ends — nobody can
203
+ * redeliver it (stream.ts, the zero-write contract). A durable OMITS the field. */
204
+ ephemeral?: true;
205
+ };
206
+ /** A committed event: the input plus the identity the stream assigned at its commit point. */
207
+ export type StreamEvent = Omit<StreamEventInput, "offset"> & {
208
+ offset: number;
209
+ createdAt: string;
210
+ path: string;
211
+ };
212
+ export declare function idempotencyConflictMessage(idempotencyKey: string, existingOffset: number): string;
213
+ /** Structural equality of the parts an idempotent retry must not change. */
214
+ export declare function sameIdempotentEvent(existingEvent: StreamEventInput, requestedEvent: StreamEventInput): boolean;
215
+ /** Sync SQLite as the platform hands it over (`ctx.storage.sql`): a query is a LAZY cursor —
216
+ * iterate it, or `toArray()`. Spelled structurally so a node:sqlite stand-in satisfies it. */
217
+ export type SqlStorageHandle = {
218
+ exec<T extends Record<string, SqlStorageValue>>(query: string, ...bindings: unknown[]): Iterable<T> & {
219
+ toArray(): T[];
220
+ };
221
+ };
222
+ /** A persisted checkpoint as read back: the version it was reduced under (the caller gates on it),
223
+ * the offset reduced through, and the state — `undefined` when the reduce never changed it. */
224
+ export type ReduceCheckpoint<State> = {
225
+ reducerVersion: string;
226
+ reducedThroughOffset: number;
227
+ state: State | undefined;
228
+ };
229
+ /** What BOTH hosts read and write their checkpoints through — the stream's storage and a facet's
230
+ * own (the Node unit tests drive it over node:sqlite, stream/test-support.ts). */
231
+ export declare class ReduceCheckpointTable {
232
+ #private;
233
+ /** `createTable: false` when the caller knows the table exists (the stream's storage skips every
234
+ * CREATE on a re-wake); a facet host constructs one per incarnation and lets it create. */
235
+ constructor(sql: SqlStorageHandle, options?: {
236
+ createTable: boolean;
237
+ });
238
+ static createTable(sql: SqlStorageHandle): void;
239
+ read<State>(slug: string): ReduceCheckpoint<State> | undefined;
240
+ /** ALWAYS the cursor; the state ONLY when `stateChanged` — one write either way. */
241
+ write<State>(slug: string, cursor: {
242
+ reducerVersion: string;
243
+ reducedThroughOffset: number;
244
+ }, state: State, stateChanged: boolean): void;
245
+ }
246
+ /** The only thing a LiveState needs from its host: somewhere to append the delta. A
247
+ * `ProcessorStream` satisfies it; a facet that is no processor passes one round trip per delta,
248
+ * `{ append: (e) => withItx(this.env.ITX, (itx) => itx.append(e)) }` (sdk/index.ts), never a scope it
249
+ * holds. */
250
+ export type LiveStateSink = {
251
+ append(event: {
252
+ type: string;
253
+ ephemeral?: true;
254
+ payload?: Record<string, unknown>;
255
+ }): unknown;
256
+ };
257
+ export declare class LiveState<S> {
258
+ #private;
259
+ constructor(sink: LiveStateSink, key: string, initial: S);
260
+ /** The current value (reflects every `set`). */
261
+ get(): S;
262
+ /** THE seed read: `{rev, state}` read together (single-threaded ⇒ atomically), which is what lets
263
+ * a client chain patches exactly instead of guessing which changes its snapshot already contains. */
264
+ snapshot(): {
265
+ rev: number;
266
+ state: S;
267
+ };
268
+ /** Replace the value: diff the last serialized base → next; on a real change bump the revision
269
+ * and append the delta. Build a NEW value (don't mutate `next` in place) — the diff is over JSON.
270
+ * A diff/append failure degrades to a LOST notification (the client re-seeds on the chain gap),
271
+ * never a throw the caller sees. */
272
+ set(next: S): void;
273
+ }
274
+ /** One owned event: its description and the zod schema for its payload. `ephemeral: true` marks a
275
+ * non-durable event (delivered only when its type is named in `consumes`). */
276
+ export type EventDefinition = {
277
+ description: string;
278
+ payloadSchema: z.ZodType;
279
+ ephemeral?: true;
280
+ };
281
+ /** A durable event type string → its definition. */
282
+ export type EventCatalog = Record<string, EventDefinition>;
283
+ /** A `processorDeps` entry's own event catalog. */
284
+ type DepCatalog<Dep> = Dep extends {
285
+ events: infer Events extends EventCatalog;
286
+ } ? Events : never;
287
+ /** The definition owning `Type` — local events win, then each dep. */
288
+ type DefinitionForType<Events extends EventCatalog, Deps extends readonly unknown[], Type extends string> = Type extends keyof Events ? Events[Type] : Deps[number] extends infer Dep ? Dep extends unknown ? Type extends keyof DepCatalog<Dep> ? DepCatalog<Dep>[Type] : never : never : never;
289
+ /** The committed event for one resolved type: `StreamEvent` narrowed to its `{ type, payload }`. */
290
+ type EventForType<Events extends EventCatalog, Deps extends readonly unknown[], Type extends string> = Type extends unknown ? DefinitionForType<Events, Deps, Type> extends {
291
+ payloadSchema: infer Schema extends z.ZodType;
292
+ } ? StreamEvent & {
293
+ type: Type;
294
+ payload: z.output<Schema>;
295
+ } : never : never;
296
+ /** The reduce union for a `consumes` tuple — `"*"` alone means any `StreamEvent`. */
297
+ type EventForTypes<Events extends EventCatalog, Deps extends readonly unknown[], Types extends readonly string[]> = "*" extends Types[number] ? StreamEvent : EventForType<Events, Deps, Types[number]>;
298
+ /** A contract's `processorDeps` tuple, defaulting to empty. */
299
+ type DepsOf<Contract> = Contract extends {
300
+ processorDeps: infer Deps extends readonly unknown[];
301
+ } ? Deps : readonly [];
302
+ /** A contract's reduced-state type, inferred from its `stateSchema`. */
303
+ export type ProcessorState<Contract> = Contract extends {
304
+ stateSchema: infer Schema extends z.ZodType;
305
+ } ? z.output<Schema> : never;
306
+ /** The committed-event union a contract's `consumes` list can deliver to `reduce`/`processEvent`. */
307
+ export type ConsumedEvent<Contract> = Contract extends {
308
+ events: infer Events extends EventCatalog;
309
+ consumes: infer Consumes extends readonly string[];
310
+ } ? EventForTypes<Events, DepsOf<Contract>, Consumes> : never;
311
+ /** The input for ONE event type as a catalog spells it (`EventInput`'s row) — or, for a type no
312
+ * catalog defines (a core control event a processor emits, `itx/ingress-configured`), the plain
313
+ * input: it widens the whole union, so a contract that emits one undefined type appends untyped
314
+ * until that type is in a catalog it depends on. */
315
+ type EventInputForType<Events extends EventCatalog, Deps extends readonly unknown[], Type extends string> = Type extends unknown ? [DefinitionForType<Events, Deps, Type>] extends [never] ? StreamEventInput : DefinitionForType<Events, Deps, Type> extends {
316
+ payloadSchema: infer Schema extends z.ZodType;
317
+ } ? {
318
+ type: Type;
319
+ payload: z.input<Schema>;
320
+ idempotencyKey?: string;
321
+ metadata?: Record<string, unknown>;
322
+ } & (DefinitionForType<Events, Deps, Type> extends {
323
+ ephemeral: true;
324
+ } ? {
325
+ ephemeral: true;
326
+ } : {
327
+ ephemeral?: never;
328
+ }) : never : never;
329
+ /** What a processor's `append` takes: one input per type the contract `emits` — its own
330
+ * events and its deps' as their catalogs spell them (`z.input`), a type no catalog defines as the
331
+ * plain input under that name. A contract whose `emits` is not a literal tuple gets every input. */
332
+ export type EmittedEventInput<Contract> = Contract extends {
333
+ events: infer Events extends EventCatalog;
334
+ emits: infer Emits extends readonly string[];
335
+ } ? string[] extends Emits ? StreamEventInput : Emits extends readonly [] ? StreamEventInput : EventInputForType<Events, DepsOf<Contract>, Emits[number]> : StreamEventInput;
336
+ /** What a caller APPENDS for one of a contract's OWNED events — the typed write on an entity
337
+ * (`itx.agents.get(path).append(…)`, library.ts): the type string, the payload as its schema takes
338
+ * it (`z.input`), a key and metadata; `ephemeral` only where the definition says so. Derived from
339
+ * the catalog, so a payload field renamed in the contract is a type error at every call site. */
340
+ export type EventInput<Contract> = Contract extends {
341
+ events: infer Events extends EventCatalog;
342
+ } ? {
343
+ [Type in keyof Events & string]: {
344
+ type: Type;
345
+ payload: z.input<Events[Type]["payloadSchema"]>;
346
+ idempotencyKey?: string;
347
+ metadata?: Record<string, unknown>;
348
+ } & (Events[Type] extends {
349
+ ephemeral: true;
350
+ } ? {
351
+ ephemeral: true;
352
+ } : {
353
+ ephemeral?: never;
354
+ });
355
+ }[keyof Events & string] : never;
356
+ /** What `defineProcessorContract` returns: the base the engine reads, plus the events catalog and the
357
+ * resolved deps. (Events are written LITERALLY at the call site — `itx.append({ type, payload })` —
358
+ * so there is no event-builder here; the engine validates the payload against `payloadSchemaFor` at
359
+ * reduce, and `ConsumedEvent`/`ProcessorState` give the reduce its types.) */
360
+ export type DefinedProcessorContract<StateSchema extends z.ZodType, Events extends EventCatalog, Consumes extends readonly string[], Deps extends readonly unknown[], Emits extends readonly string[] = readonly string[]> = ProcessorContract<z.output<StateSchema>> & {
361
+ stateSchema: StateSchema;
362
+ events: Events;
363
+ consumes: Consumes;
364
+ emits: Emits;
365
+ processorDeps: Deps;
366
+ };
367
+ export declare function defineProcessorContract<const StateSchema extends z.ZodType, const Events extends EventCatalog = Record<string, never>, const Consumes extends readonly string[] = readonly string[], const Deps extends readonly {
368
+ events: EventCatalog;
369
+ }[] = readonly [], const Emits extends readonly string[] = readonly string[]>(contract: {
370
+ slug: string;
371
+ version: string;
372
+ description: string;
373
+ /** Must parse `{}` — the initial state is `stateSchema.parse({})` (all fields defaulted). */
374
+ stateSchema: StateSchema;
375
+ /** The events this contract OWNS, keyed by durable type string. Omit for a kernel-generic
376
+ * processor that types its own reduce through the `Event` param instead of an events catalog. */
377
+ events?: Events;
378
+ /** Other processors' contracts whose events this one may `consumes`/`emits` without owning. */
379
+ processorDeps?: Deps;
380
+ consumes: Consumes;
381
+ emits: Emits;
382
+ }): DefinedProcessorContract<StateSchema, Events, Consumes, Deps, Emits>;
383
+ export {};