@supernovae-st/nika 0.71.0 → 0.120.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.
@@ -0,0 +1,889 @@
1
+ interface NikaSharedConfig {
2
+ /**
3
+ * How many of a run's most recent frames a session retains, and therefore
4
+ * the most a view opened after the fact can be given, and the largest
5
+ * `bufferSize` a view may ask for. Default: 4096 frames. For scale, one
6
+ * measured fixture (a clean native run of 90 independent mock/echo infer
7
+ * tasks) wrote 273 frames; other shapes write more, so count your own.
8
+ *
9
+ * It is a finite bound, never a promise about the run. A run longer than it
10
+ * still succeeds and `run.result()` still resolves; only a late view is
11
+ * refused, with `NikaEventBufferOverflowError` whose `reason` is
12
+ * `replay_truncated` and whose `observed` says what to set. An explicit
13
+ * value is kept exactly as given. Each frame is bounded by
14
+ * `machineBufferBytes`, so the retained history holds at most
15
+ * `eventBufferSize * machineBufferBytes` of frame text per run. That bounds
16
+ * the history only: frames already handed to a consumer, other views and
17
+ * other runs are not counted in it.
18
+ */
19
+ eventBufferSize?: number;
20
+ /** Bound for buffered diagnostics and one machine frame. Default: 64 KiB. */
21
+ machineBufferBytes?: number;
22
+ }
23
+ /** The default configuration drives a native `nika` process. */
24
+ interface NikaLocalConfig extends NikaSharedConfig {
25
+ /** Working directory used by the native process transport. */
26
+ cwd?: string;
27
+ /** Binary resolution: this value, then NIKA_BIN, then the host payload package. */
28
+ bin?: string;
29
+ url?: never;
30
+ token?: never;
31
+ allowInsecureHttp?: never;
32
+ requestTimeout?: never;
33
+ fetch?: never;
34
+ }
35
+ /** Supplying a URL selects the authenticated HTTP transport. */
36
+ interface NikaRemoteConfig extends NikaSharedConfig {
37
+ /** A `nika serve --bind` base URL. */
38
+ url: string;
39
+ /** Bearer token matching the server's `--token-file`. */
40
+ token: string;
41
+ /** Plain HTTP is refused unless this is explicitly true. */
42
+ allowInsecureHttp?: boolean;
43
+ /** Bound for HTTP admission. Default: 30 seconds. */
44
+ requestTimeout?: number;
45
+ /** Fetch implementation used by the HTTP transport. */
46
+ fetch?: typeof globalThis.fetch;
47
+ /** Working directory used while capturing the immutable snapshot locally. */
48
+ cwd?: string;
49
+ /** Local engine used to capture the immutable snapshot before HTTP admission. */
50
+ bin?: string;
51
+ }
52
+ /** Public configuration for the one Nika client surface. */
53
+ type NikaConfig = NikaLocalConfig | NikaRemoteConfig;
54
+ type NikaTransportKind = 'native-process' | 'http';
55
+ /**
56
+ * Brand carrier for engine-issued identities. The SDK brands an identity
57
+ * only where the engine (or its durable record) issues it; it never invents
58
+ * one itself.
59
+ */
60
+ declare const NikaIdentityBrand: unique symbol;
61
+ interface NikaIdentity<Name extends string> {
62
+ readonly [NikaIdentityBrand]: Name;
63
+ }
64
+ /** A run identity issued by `run()` or `attachRun()`. Assignable to `string`. */
65
+ type NikaRunId = string & NikaIdentity<'NikaRunId'>;
66
+ /** An engine execution identity carried by terminal settlements and receipts. */
67
+ type NikaExecutionId = string & NikaIdentity<'NikaExecutionId'>;
68
+ /** A durable `nika serve` job identity accepted by `attachRun()`. */
69
+ type NikaJobId = string & NikaIdentity<'NikaJobId'>;
70
+ /** Machine vocabulary is additive. Known words aid completion without closing the set. */
71
+ type NikaRunStatus = 'queued' | 'running' | 'paused' | 'succeeded' | 'failed' | 'interrupted' | 'cancelled' | (string & {});
72
+ /** A machine check report. Unknown engine fields deliberately ride through. */
73
+ interface NikaCheckResult {
74
+ report_version?: number;
75
+ clean?: boolean;
76
+ exitCode?: number;
77
+ [key: string]: unknown;
78
+ }
79
+ /** Fields every engine event can carry, whether its kind is known or not. */
80
+ interface NikaEventFields {
81
+ status?: NikaRunStatus;
82
+ sequence?: number;
83
+ receipt?: NikaReceipt;
84
+ outputs?: Record<string, unknown>;
85
+ [key: string]: unknown;
86
+ }
87
+ /** The workflow graph started executing. */
88
+ interface NikaWorkflowStartedEvent extends NikaEventFields {
89
+ kind: 'workflow_started';
90
+ }
91
+ /** A task was scheduled for execution. */
92
+ interface NikaTaskScheduledEvent extends NikaEventFields {
93
+ kind: 'task_scheduled';
94
+ }
95
+ /** A task started executing. */
96
+ interface NikaTaskStartedEvent extends NikaEventFields {
97
+ kind: 'task_started';
98
+ }
99
+ /** A task settled. Per-task payloads ride the open fields. */
100
+ interface NikaTaskCompletedEvent extends NikaEventFields {
101
+ kind: 'task_completed';
102
+ }
103
+ /**
104
+ * The workflow graph settled. This is the terminal frame of a native-process
105
+ * run and carries the run's outputs, receipt, and final status together.
106
+ */
107
+ interface NikaWorkflowCompletedEvent<Outputs extends Record<string, unknown> = Record<string, unknown>> extends NikaEventFields {
108
+ kind: 'workflow_completed';
109
+ status?: NikaRunStatus;
110
+ outputs?: Outputs;
111
+ receipt?: NikaReceipt;
112
+ }
113
+ /** The workflow graph failed. */
114
+ interface NikaWorkflowFailedEvent extends NikaEventFields {
115
+ kind: 'workflow_failed';
116
+ error?: NikaMachineError;
117
+ }
118
+ /** The workflow graph was interrupted before settling. */
119
+ interface NikaWorkflowInterruptedEvent extends NikaEventFields {
120
+ kind: 'workflow_interrupted';
121
+ }
122
+ /**
123
+ * The terminal settlement frame of a native engine process: the one frame
124
+ * that carries the run's outputs, receipt, and final status together. Its
125
+ * HTTP peer is `execution.settled`; one guard narrows both.
126
+ */
127
+ interface NikaRunSettledEvent<Outputs extends Record<string, unknown> = Record<string, unknown>> extends NikaEventFields {
128
+ kind: 'run_settled';
129
+ status?: NikaRunStatus;
130
+ /** Why the run settled this way (engine 0.118+ · flattened on this frame). */
131
+ cause?: NikaRunCause;
132
+ elapsed_ms?: number;
133
+ tasks?: NikaTaskTally;
134
+ spend?: NikaSpend;
135
+ outputs?: Outputs;
136
+ receipt?: NikaReceipt;
137
+ /**
138
+ * The cause of a `failed` settlement (engine 0.117+): the first failed
139
+ * task's code, message and task id. Absent on a succeeded or paused run,
140
+ * and on engines that only name the cause on their `task_failed` frame.
141
+ */
142
+ error?: NikaMachineError;
143
+ }
144
+ /** The run's trace chain was sealed. */
145
+ interface NikaRunSealedEvent extends NikaEventFields {
146
+ kind: 'run_sealed';
147
+ receipt?: NikaReceipt;
148
+ }
149
+ /**
150
+ * A journal delivery loss the resident reported, exactly as its contract
151
+ * closes it: the run's journal mirror stopped recording. It is independent of
152
+ * the execution: a run can settle `succeeded` and still carry it. It is never
153
+ * a verdict and never changes a status; it says the trace may be incomplete
154
+ * before `traceVerify` is trusted. Its absence is only absence: it never
155
+ * claims that a journal exists.
156
+ *
157
+ * Engine main, ahead of the contract this package pins: no released engine
158
+ * writes it yet, and a resident that predates it simply never sends it.
159
+ */
160
+ interface NikaJournalEvidence {
161
+ status: 'mirror_lost';
162
+ /** The mirror's first error, classified: never OS text, never a path. */
163
+ reason: 'write_failed' | 'record_refused';
164
+ }
165
+ /**
166
+ * Fields only the resident's frames carry, both from engine main, ahead of the
167
+ * contract this package pins. Both are optional on the wire and absent on a
168
+ * resident that predates them.
169
+ */
170
+ interface NikaResidentEventFields extends NikaEventFields {
171
+ /** When the resident admitted the event: RFC 3339, UTC. Outside the event's hash chain. */
172
+ at?: string;
173
+ /** A reported journal delivery loss, on the terminal frame. */
174
+ evidence?: NikaJournalEvidence;
175
+ }
176
+ /**
177
+ * The HTTP transport admitted the execution and it is running. This is the
178
+ * first lifecycle frame `nika serve --bind` streams for a durable job.
179
+ */
180
+ interface NikaExecutionStartedEvent extends NikaResidentEventFields {
181
+ kind: 'execution.started';
182
+ }
183
+ /**
184
+ * The terminal settlement frame of the HTTP transport, and the peer of
185
+ * `run_settled`: the one frame that carries the run's outputs, receipt, and
186
+ * final status together.
187
+ */
188
+ interface NikaExecutionSettledEvent<Outputs extends Record<string, unknown> = Record<string, unknown>> extends NikaResidentEventFields {
189
+ kind: 'execution.settled';
190
+ status?: NikaRunStatus;
191
+ outputs?: Outputs;
192
+ receipt?: NikaReceipt;
193
+ /** The settlement the resident nests whole on this frame (engine 0.118+ · ADR-128). */
194
+ settlement?: NikaSettlement;
195
+ }
196
+ /**
197
+ * The resident cancelled the execution: a queued job cancelled before it was
198
+ * claimed, or a running one whose owner settled the request as a
199
+ * cancellation. It carries the settlement when the runtime built one.
200
+ */
201
+ interface NikaExecutionCancelledEvent extends NikaResidentEventFields {
202
+ kind: 'execution.cancelled';
203
+ settlement?: NikaSettlement;
204
+ }
205
+ /** The server refused the execution. */
206
+ interface NikaExecutionRefusedEvent extends NikaResidentEventFields {
207
+ kind: 'execution.refused';
208
+ }
209
+ /**
210
+ * The execution was interrupted before settling. A resident that restarts
211
+ * marks an orphaned running job with either word, so both are one variant.
212
+ */
213
+ interface NikaExecutionInterruptedEvent extends NikaResidentEventFields {
214
+ kind: 'execution.interrupted' | 'interrupted';
215
+ }
216
+ /**
217
+ * Forward-compatibility variant: any kind this SDK version does not know
218
+ * yet stays representable, so the event union is intentionally
219
+ * non-exhaustive.
220
+ */
221
+ interface NikaUnknownEvent extends NikaEventFields {
222
+ kind?: string;
223
+ }
224
+ /**
225
+ * One engine-owned run event, from either transport: the native process emits
226
+ * the `workflow_*` / `task_*` / `run_*` kinds, `nika serve` emits the
227
+ * `execution.*` kinds. Known kinds discriminate on `kind`; unknown kinds fall
228
+ * back to `NikaUnknownEvent`. Future fields stay open on every variant.
229
+ * `Outputs` types the terminal frames' outputs and defaults to the transport
230
+ * shape, so untyped callers see no change.
231
+ */
232
+ type NikaEvent<Outputs extends Record<string, unknown> = Record<string, unknown>> = NikaWorkflowStartedEvent | NikaTaskScheduledEvent | NikaTaskStartedEvent | NikaTaskCompletedEvent | NikaWorkflowCompletedEvent<Outputs> | NikaWorkflowFailedEvent | NikaWorkflowInterruptedEvent | NikaRunSettledEvent<Outputs> | NikaRunSealedEvent | NikaExecutionStartedEvent | NikaExecutionSettledEvent<Outputs> | NikaExecutionCancelledEvent | NikaExecutionRefusedEvent | NikaExecutionInterruptedEvent | NikaUnknownEvent;
233
+ /**
234
+ * The SDK's one lifecycle vocabulary, identical on both transports. Each word
235
+ * names a fact an engine wrote; the protocol word that carried it stays on
236
+ * `raw.kind`. Transports differ in cardinality, never in these names.
237
+ *
238
+ * A frame that speaks of the run's state earns its name only for a
239
+ * (kind, status) pair a producer defines. The engine's state word decides and
240
+ * is never defaulted: an absent, null, future, or still-running status, or
241
+ * one that contradicts its kind, stays an `engine.event`.
242
+ *
243
+ * - `run.started`: `workflow_started` · `execution.started`.
244
+ * - `task.scheduled` · `task.started` · `task.completed` · `task.failed`: the
245
+ * native `task_*` frames. `nika serve` streams no per-task frame, so an HTTP
246
+ * run yields none; the SDK never synthesizes one.
247
+ * - `run.waiting`: the settlement frame (`run_settled` · `execution.settled`)
248
+ * carrying `paused`. A human gate holds the run: it is not failed, not a
249
+ * completed execution, and stays resumable.
250
+ * - `run.settled`: exactly these pairs, and no other. The settlement frame
251
+ * (`run_settled` · `execution.settled`) carrying `succeeded`, `failed`, or
252
+ * `cancelled`; `execution.cancelled` carrying `cancelled`;
253
+ * `execution.refused` carrying `failed`. A dedicated end kind with another
254
+ * terminal word (a refusal that `succeeded`, a cancellation that `failed`)
255
+ * contradicts itself and stays an `engine.event`.
256
+ * - `run.interrupted`: `workflow_interrupted` · `execution.interrupted` ·
257
+ * `interrupted` carrying `interrupted`. The engine lost the execution and
258
+ * its settlement is unknown: an evidence state, never a settlement. This is
259
+ * an engine-reported frame, distinct from the thrown
260
+ * `NikaObservationInterrupted`, which means this client lost its
261
+ * observation of a run that may still be running.
262
+ * - `run.sealed`: `run_sealed`, native only.
263
+ * - `engine.event`: every other frame, including kinds this SDK version does
264
+ * not know yet. Nothing is dropped; read `raw`.
265
+ *
266
+ * The projection keeps no state between frames and deduplicates nothing. The
267
+ * set is additive: keep a `default` branch.
268
+ */
269
+ type NikaRunEventKind = 'run.started' | 'task.scheduled' | 'task.started' | 'task.completed' | 'task.failed' | 'run.waiting' | 'run.settled' | 'run.interrupted' | 'run.sealed' | 'engine.event';
270
+ /**
271
+ * One run event in the SDK's lifecycle vocabulary, as `run.events()` yields
272
+ * it. It is a projection of exactly one protocol frame: `raw` is that frame,
273
+ * untouched, and every other field is present only when the frame stated it.
274
+ * An `engine.event` is given no lifecycle meaning: it carries no `status`,
275
+ * `task` or `error`, only its cursor and `raw`.
276
+ */
277
+ interface NikaRunEvent<Outputs extends Record<string, unknown> = Record<string, unknown>> {
278
+ readonly kind: NikaRunEventKind;
279
+ /** The transport whose protocol `raw` speaks. */
280
+ readonly transport: NikaTransportKind;
281
+ /** The engine's own state word, never renamed: a waiting run reads `paused`. */
282
+ readonly status?: NikaRunStatus;
283
+ /**
284
+ * HTTP only: the SSE sequence of this frame, the cursor to persist for
285
+ * `attachRun(id, { lastEventId })`. A native process has no durable replay,
286
+ * so a native event never carries one.
287
+ */
288
+ readonly sequence?: number;
289
+ /** The task a `task.*` frame named. */
290
+ readonly task?: string;
291
+ /** The failure the frame named: a failed task, or a failed settlement. */
292
+ readonly error?: NikaMachineError;
293
+ /** The exact protocol frame the engine wrote. */
294
+ readonly raw: NikaEvent<Outputs>;
295
+ }
296
+ /**
297
+ * Engine-issued proof material. The SDK transports it but never constructs,
298
+ * reads a workflow to enrich it, or verifies its claims itself.
299
+ */
300
+ type NikaReceipt = Readonly<Record<string, unknown>>;
301
+ interface NikaMachineError {
302
+ code?: string;
303
+ message?: string;
304
+ /** The task that failed, when a native `task_failed` frame named it. */
305
+ task?: string;
306
+ [key: string]: unknown;
307
+ }
308
+ /** Why a run settled the way it did (engine 0.118+ · ADR-128). */
309
+ type NikaRunCause = 'normal' | 'human_gate' | 'task_failed' | 'output_contract' | 'budget' | 'operator' | 'refused' | (string & {});
310
+ /**
311
+ * How much of the spend is priced (engine 0.118+): `unmetered` = no metered
312
+ * call · `unpriced` = a local or subscription seat, never free · `partially_priced`
313
+ * · `priced`.
314
+ */
315
+ type NikaCostQualifier = 'priced' | 'partially_priced' | 'unpriced' | 'unmetered' | (string & {});
316
+ /** How the run's tasks ended (engine 0.118+): `recovered` is a tally, never a state. */
317
+ interface NikaTaskTally {
318
+ total?: number;
319
+ ok?: number;
320
+ failed?: number;
321
+ recovered?: number;
322
+ skipped?: number;
323
+ cancelled?: number;
324
+ never_started?: number;
325
+ [key: string]: unknown;
326
+ }
327
+ /** What the run spent and how much of it is priced (engine 0.118+). */
328
+ interface NikaSpend {
329
+ /** Present only when at least one call metered real spend; unknown cost is never zero. */
330
+ total_cost_usd?: number | null;
331
+ priced_calls?: number;
332
+ unpriced_calls?: number;
333
+ qualifier?: NikaCostQualifier;
334
+ pricing_as_of?: string | null;
335
+ /** Spend per pricing source, when the engine broke it down. */
336
+ by_source?: Record<string, number>;
337
+ [key: string]: unknown;
338
+ }
339
+ /**
340
+ * The run's settlement as the engine built it once (ADR-128): the state's
341
+ * cause, the task tally, the spend and its qualifier, the elapsed time.
342
+ * Absent on engines before 0.118; never derived from an exit code.
343
+ */
344
+ interface NikaSettlement {
345
+ /**
346
+ * The state word the settlement itself carries (`succeeded` · `failed` ·
347
+ * `paused` · `cancelled`) on the resident's nested projection; the native
348
+ * `run_settled` frame states it on the frame instead.
349
+ */
350
+ status?: NikaRunStatus;
351
+ cause?: NikaRunCause;
352
+ elapsed_ms?: number;
353
+ tasks?: NikaTaskTally;
354
+ spend?: NikaSpend;
355
+ /** The failure named on a `failed` settlement: code, message and the task, when one failed. */
356
+ error?: NikaMachineError;
357
+ [key: string]: unknown;
358
+ }
359
+ /**
360
+ * The engine's result of observing an admitted run, including a paused run.
361
+ * Admitted workflow failure resolves with `status: 'failed'`; configuration,
362
+ * transport, protocol, and compatibility errors reject instead. Use
363
+ * `isNikaRunSucceeded(result)` before treating an observation as success.
364
+ * Outputs are optional even on success, and status stays forward-compatible.
365
+ */
366
+ interface NikaRunResult<Outputs extends Record<string, unknown> = Record<string, unknown>> {
367
+ id: NikaRunId;
368
+ status: NikaRunStatus;
369
+ transport: NikaTransportKind;
370
+ exitCode?: number;
371
+ outputs?: Outputs;
372
+ receipt?: NikaReceipt;
373
+ error?: NikaMachineError;
374
+ /** Engine execution identity, when the transport surface reports one. */
375
+ execution_id?: NikaExecutionId;
376
+ /** The settlement's cause, tally and spend (engine 0.118+), when the terminal frame carried them. */
377
+ settlement?: NikaSettlement;
378
+ /**
379
+ * HTTP only: the journal delivery loss the resident reported on the terminal
380
+ * frame or the durable job that settled this run. Copied, never inferred:
381
+ * absent when the resident reported none, which claims nothing about a
382
+ * journal. It never changes `status`. A native process reports none.
383
+ */
384
+ evidence?: NikaJournalEvidence;
385
+ [key: string]: unknown;
386
+ }
387
+ /**
388
+ * An admitted run and its whole lifecycle. `run()` and `attachRun()` return
389
+ * one only after admission: a workflow the engine refuses rejects there and
390
+ * never yields a handle. Every member is bound to the run, so a method may be
391
+ * extracted (`const { events, result } = run`) and still works.
392
+ *
393
+ * The handle owns observation, settlement, status and cancellation, nothing
394
+ * else: checking, proof, catalogs and authoring stay on `Nika`. It is
395
+ * process-bound. To continue in another process, persist `id` and the last
396
+ * `event.sequence` you fully processed, then call
397
+ * `nika.attachRun(id, { lastEventId })`, the one recovery door.
398
+ *
399
+ * `id` is what differs by transport, and the type cannot show it:
400
+ * - HTTP: the resident's durable job id. This is the identity to store.
401
+ * - native: an ephemeral correlation id of this SDK process. It appears in no
402
+ * journal and cannot be recovered after the process ends; `attachRun`
403
+ * refuses it. Resume a native run through the engine's own trace.
404
+ */
405
+ interface NikaRun<Outputs extends Record<string, unknown> = Record<string, unknown>> {
406
+ readonly id: NikaRunId;
407
+ /**
408
+ * A bounded view of the run's events in the SDK's lifecycle vocabulary;
409
+ * each event keeps its protocol frame on `raw`. Transports differ in how
410
+ * many facts they emit, never in their names. The iterator throws for a
411
+ * broken observation (`NikaObservationInterrupted` carries the cursor); an
412
+ * admitted workflow failure ends it normally and is read from `result()`.
413
+ */
414
+ readonly events: (options?: NikaEventsOptions) => AsyncIterable<NikaRunEvent<Outputs>>;
415
+ /**
416
+ * The engine's result of observing this run, settled once. One failure law:
417
+ * - rejects: a transport, protocol, or compatibility fault, or a broken
418
+ * observation (`NikaObservationInterrupted`, which carries the cursor).
419
+ * None of them says the run failed; it may still be running.
420
+ * - resolves with `status: 'failed'`: an admitted failure is result data,
421
+ * with the engine's `error.code` when the engine named one. `cancelled`
422
+ * and the engine-reported `interrupted` resolve the same way.
423
+ * - resolves with `status: 'paused'`: a human gate holds the run. It is
424
+ * neither a failure nor a completed execution.
425
+ * Read `isNikaRunSucceeded(result)` before treating it as success.
426
+ */
427
+ readonly result: () => Promise<NikaRunResult<Outputs>>;
428
+ /**
429
+ * The current durable status, without waiting for settlement. Only a
430
+ * resident owns one: a native run rejects with a typed
431
+ * `NikaCompatibilityError` instead of inventing a status.
432
+ */
433
+ readonly status: () => Promise<NikaRunStatus>;
434
+ /**
435
+ * Ask the engine to cancel. Idempotent: every call returns the one request.
436
+ * Acceptance is not a result; read what the engine recorded from `result()`.
437
+ */
438
+ readonly cancel: () => Promise<NikaCancelResult>;
439
+ /** Compatibility alias of `result()`: the same promise, kept while code migrates. */
440
+ readonly done: Promise<NikaRunResult<Outputs>>;
441
+ }
442
+ interface NikaCancelResult {
443
+ runId: NikaRunId;
444
+ accepted: boolean;
445
+ /**
446
+ * `cancelled`: the job settled cancelled on the cancel reply itself.
447
+ * `already_settled`: the run had already ended, nothing was cancelled.
448
+ * `cancellation_requested`: the request was accepted while the execution
449
+ * owner had not settled yet (a native SIGTERM, or the resident's 202); the
450
+ * run then settles on its own terminal, read from `run.result()`, which may
451
+ * be `cancelled`, `succeeded`, `failed`, or `interrupted` once the
452
+ * resident's grace expired. Open to the engine's future words.
453
+ */
454
+ status: 'cancelled' | 'already_settled' | 'cancellation_requested' | (string & {});
455
+ transport: NikaTransportKind;
456
+ [key: string]: unknown;
457
+ }
458
+ /** Server-owned metadata for one contained resident workflow. */
459
+ interface NikaWorkflowMetadata {
460
+ workflow: string;
461
+ [key: string]: unknown;
462
+ }
463
+ interface NikaTraceVerifyResult {
464
+ verified: boolean;
465
+ /**
466
+ * Engine-owned trace verdict. The native path answers `verified` or
467
+ * `invalid`; the resident's door answers `unavailable` while it has no
468
+ * trace-journal authority (engine 0.118), and will speak the CLI's tiers
469
+ * (`OK` · `SEALED` · `ANCHORED` · `REPLAYED` hold · `INCOMPLETE` ·
470
+ * `TAMPERED` do not) once it does. Open to additive future vocabulary.
471
+ */
472
+ verdict?: 'verified' | 'invalid' | 'unavailable' | 'OK' | 'SEALED' | 'ANCHORED' | 'REPLAYED' | 'INCOMPLETE' | 'TAMPERED' | (string & {});
473
+ /** Engine-owned explanation for a negative or unavailable verdict; a verdict that holds carries none. */
474
+ reason?: 'trace_invalid' | 'receipt_mismatch' | 'run_not_terminal' | 'trace_journal_unavailable' | (string & {});
475
+ trace_id?: string;
476
+ exitCode?: number;
477
+ output?: string;
478
+ [key: string]: unknown;
479
+ }
480
+ interface NikaCheckOptions {
481
+ model?: string;
482
+ nativeStrict?: boolean;
483
+ /** Stops only this check request/process. */
484
+ signal?: AbortSignal;
485
+ }
486
+ interface NikaRunOptions {
487
+ /**
488
+ * Literal values for the workflow's declared `inputs:`, by name, with the
489
+ * same meaning on both transports. Values are strict JSON and stay literal:
490
+ * a string is never read as `@env:NAME`, an expression or a number, and
491
+ * nothing is coerced to the declared type. The engine validates the map
492
+ * (unknown key, type mismatch, missing required input) and refuses before
493
+ * any run exists. A value JSON cannot carry (`undefined`, a function, a
494
+ * symbol, a bigint, a non-finite number, a cycle, a class instance, a
495
+ * custom prototype, an array hole, an accessor, a Proxy) rejects `run()`
496
+ * with `NikaConfigurationError` instead of being dropped, and the
497
+ * serialized map is bounded at 1 MiB. No caller code runs while it is
498
+ * judged: no getter is invoked, and a Proxy is refused before it is read.
499
+ *
500
+ * Needs an engine that advertises the literal channel: `inputsLiteral`
501
+ * natively (values ride stdin, never argv), `jobInputs` over HTTP by served
502
+ * name. An engine without it rejects with `NikaCompatibilityError`; the SDK
503
+ * never falls back to `--var`. An execution snapshot freezes its inputs, so
504
+ * an HTTP run of a local path refuses `inputs`. Never put a secret here.
505
+ */
506
+ inputs?: Record<string, unknown>;
507
+ /**
508
+ * @deprecated Use `inputs`. `vars` is the native `--var KEY=VALUE` operator
509
+ * channel: the engine reads `@env:NAME` from its environment and coerces
510
+ * text to the declared type, so it cannot carry literal API values and has
511
+ * no HTTP form. Combining it with `inputs` rejects `run()`.
512
+ */
513
+ vars?: Record<string, string | number | boolean>;
514
+ model?: string;
515
+ maxCostUsd?: number;
516
+ /**
517
+ * Required for HTTP admission; reuse the same key and request after an
518
+ * uncertain response. Direct native runs reject this option.
519
+ */
520
+ idempotencyKey?: string;
521
+ }
522
+ /** Resume observation of an already-admitted durable HTTP job. */
523
+ interface NikaAttachRunOptions {
524
+ /** Last SSE sequence durably consumed by the caller. Default: 0. */
525
+ lastEventId?: number;
526
+ }
527
+ interface NikaEventsOptions {
528
+ /** Stops this subscriber view. It never cancels the run. */
529
+ signal?: AbortSignal;
530
+ /**
531
+ * Per-view queue bound, capped by the client eventBufferSize, which is also
532
+ * its default. A live view that falls further behind than this fails with
533
+ * `reason: 'live_backpressure'`; a view opened after more frames than this
534
+ * is refused with `reason: 'replay_truncated'`. Neither skips a frame.
535
+ */
536
+ bufferSize?: number;
537
+ }
538
+ interface NikaTraceVerifyOptions {
539
+ /** Stops only the verification request/process. */
540
+ signal?: AbortSignal;
541
+ }
542
+ /** The SDK operations whose engine refusal can be returned as a typed error. */
543
+ type NikaOperation = 'check' | 'run' | 'attachRun' | 'status' | 'cancel' | 'listWorkflows' | 'workflow' | 'traceVerify' | 'schedule' | 'scheduleStatus';
544
+ /** One engine-owned schedule finding. The vocabulary remains additive. */
545
+ interface NikaScheduleFinding {
546
+ code: string;
547
+ detail: string;
548
+ [key: string]: unknown;
549
+ }
550
+ /**
551
+ * One engine-owned check finding, exactly as the engine's check report
552
+ * carries it. `code` is absent when the engine's failure class names none (an
553
+ * unreadable workflow file); the SDK never supplies one. The vocabulary
554
+ * remains additive.
555
+ */
556
+ interface NikaCheckFinding {
557
+ code?: string;
558
+ message?: string;
559
+ severity?: string;
560
+ gate?: string;
561
+ kind?: string;
562
+ /** The task the finding judges, when it judges one. */
563
+ task?: string;
564
+ docs_url?: string;
565
+ [key: string]: unknown;
566
+ }
567
+ /**
568
+ * Findings carried by the one operation-error taxonomy: a schedule refusal
569
+ * carries schedule findings (`detail`), a refused `run()` carries the check
570
+ * findings that refused it (`message`).
571
+ */
572
+ type NikaOperationFinding = NikaScheduleFinding | NikaCheckFinding;
573
+ type NikaScheduleWhen = {
574
+ kind: 'once';
575
+ at: string;
576
+ } | {
577
+ kind: 'cadence';
578
+ expression: string;
579
+ };
580
+ /** Exact declarative input accepted by PUT /v1/schedules/{id}. */
581
+ interface NikaScheduleOptions {
582
+ /** Stable path identity for the resident schedule. */
583
+ id: string;
584
+ when: NikaScheduleWhen;
585
+ maxCostUsd: number;
586
+ missed: 'catch-up' | 'catch-up-once' | 'skip';
587
+ maxLatenessSeconds?: number;
588
+ overlap?: 'skip' | 'queue' | 'replace';
589
+ afterSkip?: 'next_slot' | 'on_completion';
590
+ jitter?: 'hash';
591
+ tolerance?: string;
592
+ active?: boolean;
593
+ pauseReason?: string;
594
+ /** ISO calendar date (`YYYY-MM-DD`) required when active is false. */
595
+ pauseUntil?: string;
596
+ /** Exact prior revision for an update. Omit for create-if-absent. */
597
+ revision?: string;
598
+ }
599
+ type NikaScheduleMissed = 'catch-up' | 'catch-up-once' | 'skip' | (string & {});
600
+ type NikaScheduleOverlap = 'skip' | 'queue' | 'replace' | (string & {});
601
+ type NikaScheduleAfterSkip = 'next_slot' | 'on_completion' | (string & {});
602
+ /** The engine-normalized schedule definition; the SDK never normalizes it. */
603
+ interface NikaScheduleDefinition {
604
+ id: string;
605
+ workflow: string;
606
+ when: NikaScheduleWhen | {
607
+ kind: string;
608
+ [key: string]: unknown;
609
+ };
610
+ maxCostUsd: number;
611
+ missed: NikaScheduleMissed;
612
+ maxLatenessSeconds: number | null;
613
+ overlap: NikaScheduleOverlap;
614
+ afterSkip: NikaScheduleAfterSkip;
615
+ jitter: 'hash' | (string & {}) | null;
616
+ tolerance: string | null;
617
+ active: boolean;
618
+ pauseReason: string | null;
619
+ pauseUntil: string | null;
620
+ [key: string]: unknown;
621
+ }
622
+ interface NikaScheduleSlot {
623
+ slotId: string;
624
+ scheduledFor: string;
625
+ requestedCivil: string | null;
626
+ shift: 'exact' | 'advanced_first_valid' | 'folded_first' | (string & {});
627
+ [key: string]: unknown;
628
+ }
629
+ type NikaScheduleDue = {
630
+ kind: 'scheduled';
631
+ slot: NikaScheduleSlot;
632
+ } | {
633
+ kind: 'catch_up';
634
+ slot: NikaScheduleSlot;
635
+ missedSlots: number;
636
+ } | {
637
+ kind: 'skipped_missed';
638
+ slot: NikaScheduleSlot;
639
+ missedSlots: number;
640
+ } | {
641
+ kind: 'skipped_too_late';
642
+ slot: NikaScheduleSlot;
643
+ latenessSeconds: number;
644
+ maximumSeconds: number;
645
+ } | {
646
+ kind: 'paused';
647
+ reason: string | null;
648
+ pauseUntil: string | null;
649
+ } | {
650
+ kind: 'once_consumed';
651
+ slotId: string;
652
+ scheduledFor: string;
653
+ } | {
654
+ kind: 'not_due';
655
+ } | {
656
+ kind: string & {};
657
+ [key: string]: unknown;
658
+ };
659
+ interface NikaSchedulePause {
660
+ reason: string | null;
661
+ until: string | null;
662
+ }
663
+ interface NikaScheduleClaim {
664
+ runId: string;
665
+ executionId: string;
666
+ traceId: string;
667
+ generation: string;
668
+ [key: string]: unknown;
669
+ }
670
+ interface NikaScheduleLastDecision {
671
+ action: 'claimed' | 'skipped' | (string & {});
672
+ decision: 'scheduled' | 'catch_up' | (string & {});
673
+ revision: string;
674
+ slotId: string;
675
+ scheduledFor: string;
676
+ decidedAt: string;
677
+ reason: string | null;
678
+ claim: NikaScheduleClaim | null;
679
+ [key: string]: unknown;
680
+ }
681
+ /** Fresh engine planning facts. The SDK transports them without interpretation. */
682
+ interface NikaScheduleStatus {
683
+ definition: NikaScheduleDefinition;
684
+ origin: 'api' | (string & {});
685
+ revision: string;
686
+ active: boolean;
687
+ pause: NikaSchedulePause | null;
688
+ due?: NikaScheduleDue;
689
+ finding?: NikaScheduleFinding;
690
+ next: NikaScheduleSlot[];
691
+ earliestWakeHint: string | null;
692
+ lastDecision: NikaScheduleLastDecision | null;
693
+ [key: string]: unknown;
694
+ }
695
+ /** Durable apply acknowledgement. It does not wait for a scheduled fire. */
696
+ interface NikaScheduleApplyResult {
697
+ applied: true;
698
+ changed: boolean;
699
+ status: NikaScheduleStatus;
700
+ }
701
+
702
+ declare class NikaError extends Error {
703
+ constructor(message: string, options?: ErrorOptions);
704
+ }
705
+ declare class NikaConfigurationError extends NikaError {
706
+ constructor(message: string);
707
+ }
708
+ declare class NikaTransportError extends NikaError {
709
+ readonly transport: NikaTransportKind;
710
+ constructor(transport: NikaTransportKind, message: string, options?: ErrorOptions);
711
+ }
712
+ /** A typed engine/adapter capability gap, not a workflow failure. */
713
+ declare class NikaCompatibilityError extends NikaError {
714
+ readonly capability: string;
715
+ readonly transport: NikaTransportKind;
716
+ constructor(capability: string, transport: NikaTransportKind, message: string);
717
+ }
718
+ declare class NikaProtocolError extends NikaTransportError {
719
+ constructor(transport: NikaTransportKind, message: string, options?: ErrorOptions);
720
+ }
721
+ /**
722
+ * Observation broke before terminal settlement and the final durable read
723
+ * stayed non-terminal. The cursor feeds attachRun(id, { lastEventId }).
724
+ *
725
+ * This is about the client's view, never about the run: the run may still be
726
+ * running on the resident. It is not the engine's own `interrupted` state,
727
+ * which arrives as a `run.interrupted` event and as `result.status`.
728
+ */
729
+ declare class NikaObservationInterrupted extends NikaTransportError {
730
+ readonly runId: string;
731
+ readonly lastSequence: number;
732
+ readonly attempts: number;
733
+ constructor(transport: NikaTransportKind, runId: string, lastSequence: number, attempts: number);
734
+ }
735
+ /** One taxonomy for engine refusals returned by an SDK operation. */
736
+ declare class NikaOperationError extends NikaError {
737
+ readonly operation: NikaOperation;
738
+ readonly code: string;
739
+ readonly transport: NikaTransportKind;
740
+ readonly status: number;
741
+ readonly findings?: readonly NikaOperationFinding[];
742
+ readonly currentRevision?: string | null;
743
+ readonly machineCode?: string;
744
+ constructor(operation: NikaOperation, transport: NikaTransportKind, code: string, message: string, details: {
745
+ status: number;
746
+ findings?: readonly NikaOperationFinding[];
747
+ currentRevision?: string | null;
748
+ machineCode?: string;
749
+ });
750
+ }
751
+ /**
752
+ * An event view would have had to skip frames, so it refused instead. The SDK
753
+ * never silently omits a frame. Two different bounds can be exceeded, and
754
+ * `reason` says which. Neither is about the run: it keeps running or stays
755
+ * settled, and `run.result()` is unaffected.
756
+ *
757
+ * - `live_backpressure`: a view that was observing live fell more than
758
+ * `limit` frames behind the stream. Read faster, or give it a larger
759
+ * `bufferSize`. Other views are unaffected.
760
+ * - `replay_truncated`: a view was opened after the run had already produced
761
+ * more frames than it can be given. `observed` is how many the session saw
762
+ * and `retained` how many it still holds. When `retained === observed`
763
+ * nothing is lost and a view with `bufferSize >= observed` replays them
764
+ * all; when `retained < observed` the earlier frames are gone from this
765
+ * process, so raise `eventBufferSize` to at least `observed` for the next
766
+ * run, or observe it live.
767
+ */
768
+ declare class NikaEventBufferOverflowError extends NikaError {
769
+ readonly runId: string;
770
+ /** The bound that was exceeded: the view's `bufferSize`. */
771
+ readonly limit: number;
772
+ readonly reason: 'live_backpressure' | 'replay_truncated';
773
+ /** `replay_truncated` only: frames the session had observed when it refused. */
774
+ readonly observed?: number;
775
+ /** `replay_truncated` only: frames the session still held when it refused. */
776
+ readonly retained?: number;
777
+ constructor(runId: string, limit: number, replay?: {
778
+ observed: number;
779
+ retained: number;
780
+ });
781
+ }
782
+ declare class NikaRunOwnershipError extends NikaError {
783
+ constructor();
784
+ }
785
+
786
+ /** The local engine could not be resolved without an implicit PATH lookup. */
787
+ declare class NikaEngineUnavailable extends NikaError {
788
+ readonly code = "NIKA_ENGINE_UNAVAILABLE";
789
+ readonly platform: string;
790
+ readonly arch: string;
791
+ readonly packageName?: string;
792
+ constructor(platform: string, arch: string, packageName?: string);
793
+ }
794
+
795
+ /**
796
+ * Narrows a result to the engine's successful settlement. Admitted failures
797
+ * resolve as result data; awaiting a run alone does not establish success.
798
+ * Paused, cancelled, interrupted, failed, and unknown statuses return false.
799
+ * Outputs remain optional: a successful workflow need not declare any.
800
+ */
801
+ declare function isNikaRunSucceeded<Outputs extends Record<string, unknown> = Record<string, unknown>>(result: NikaRunResult<Outputs>): result is NikaRunResult<Outputs> & {
802
+ status: 'succeeded';
803
+ };
804
+
805
+ /**
806
+ * Narrows any run event to the terminal settlement frame, which carries the
807
+ * run's status, outputs, and receipt together. Both transports have one: the
808
+ * native process emits `run_settled`, `nika serve` emits `execution.settled`.
809
+ * Kind equality alone cannot exclude the forward-compatibility variant; this
810
+ * guard can.
811
+ */
812
+ declare function isNikaRunSettledEvent<Outputs extends Record<string, unknown> = Record<string, unknown>>(event: NikaEvent<Outputs>): event is NikaRunSettledEvent<Outputs> | NikaExecutionSettledEvent<Outputs>;
813
+ /**
814
+ * Narrows any run event to a terminal one by the status the engine reported,
815
+ * not by its kind, so it holds on either transport and across kinds this SDK
816
+ * version does not know yet. It therefore also covers the frames that end a
817
+ * run without settling outputs: `execution.cancelled`, `execution.refused`,
818
+ * `interrupted`, `workflow_failed` and `workflow_cancelled` (the engine's
819
+ * four run terminals are `workflow_completed` · `workflow_failed` ·
820
+ * `workflow_paused` · `workflow_cancelled` · ADR-128).
821
+ */
822
+ declare function isNikaTerminalEvent<Outputs extends Record<string, unknown> = Record<string, unknown>>(event: NikaEvent<Outputs>): event is NikaEvent<Outputs> & {
823
+ status: 'succeeded' | 'failed' | 'interrupted' | 'cancelled';
824
+ };
825
+ /** Narrows any run event to the frame that sealed the run's trace chain. */
826
+ declare function isNikaRunSealedEvent<Outputs extends Record<string, unknown> = Record<string, unknown>>(event: NikaEvent<Outputs>): event is NikaRunSealedEvent;
827
+
828
+ /** One client surface for a local engine process or a live nika serve URL. */
829
+ declare class Nika {
830
+ readonly transportKind: NikaTransportKind;
831
+ private readonly transport;
832
+ private readonly sessions;
833
+ private readonly eventBufferSize;
834
+ constructor(config?: NikaConfig);
835
+ check(workflow: string, options?: NikaCheckOptions): Promise<NikaCheckResult>;
836
+ /**
837
+ * Resolves with the run's handle once the engine admitted it, and rejects
838
+ * without one when the engine refused it. The handle owns the lifecycle:
839
+ * `run.events()`, `run.result()`, `run.status()`, `run.cancel()`.
840
+ *
841
+ * `Outputs` is the caller's projection of the engine-emitted outputs map;
842
+ * the SDK transports outputs without validating their shape.
843
+ */
844
+ run<Outputs extends Record<string, unknown> = Record<string, unknown>>(workflow: string, options?: NikaRunOptions): Promise<NikaRun<Outputs>>;
845
+ /**
846
+ * The one recovery door: reattach this client process to an
847
+ * already-admitted durable HTTP job and get a full `NikaRun` back. Pass the
848
+ * last `event.sequence` you fully processed as `lastEventId`. A native
849
+ * process is process-bound and refuses with a typed compatibility error.
850
+ */
851
+ attachRun<Outputs extends Record<string, unknown> = Record<string, unknown>>(id: string, options?: NikaAttachRunOptions): Promise<NikaRun<Outputs>>;
852
+ /** List contained workflow names from a resident HTTP authority. */
853
+ listWorkflows(): Promise<readonly string[]>;
854
+ /** Read path-free metadata for one contained workflow. */
855
+ workflow(name: string): Promise<NikaWorkflowMetadata>;
856
+ /**
857
+ * The run's events in the protocol vocabulary of its transport
858
+ * (`workflow_*` · `task_*` · `run_*` natively, `execution.*` over HTTP).
859
+ *
860
+ * @deprecated Use `run.events()`: one lifecycle vocabulary on both
861
+ * transports, with this same frame kept on `event.raw`. This wrapper is a
862
+ * compatibility door for one release train, counted from publication: it
863
+ * ships unchanged in the first published train that carries `run.events()`,
864
+ * and the earliest train that may remove it is the one after, as announced
865
+ * in that train's release notes. It accepts only a run this client created.
866
+ */
867
+ events<Outputs extends Record<string, unknown> = Record<string, unknown>>(run: NikaRun<Outputs>, options?: NikaEventsOptions): AsyncIterable<NikaEvent<Outputs>>;
868
+ /**
869
+ * @deprecated Use `run.cancel()`; both return the one memoized request.
870
+ * Kept through the same compatibility window as `events(run)`. It accepts
871
+ * only a run this client created.
872
+ */
873
+ cancel(run: NikaRun): Promise<NikaCancelResult>;
874
+ /**
875
+ * Read the current durable status without waiting for terminal settlement.
876
+ *
877
+ * @deprecated Use `run.status()`. Kept through the same compatibility
878
+ * window as `events(run)`. It accepts only a run this client created.
879
+ */
880
+ status(run: NikaRun): Promise<NikaRunStatus>;
881
+ schedule(workflow: string, options: NikaScheduleOptions): Promise<NikaScheduleApplyResult>;
882
+ scheduleStatus(id: string): Promise<NikaScheduleStatus>;
883
+ traceVerify(receipt: NikaReceipt, options?: NikaTraceVerifyOptions): Promise<NikaTraceVerifyResult>;
884
+ /** One session per admitted run, owned by this client and by no registry. */
885
+ private own;
886
+ private session;
887
+ }
888
+
889
+ export { Nika, type NikaAttachRunOptions, type NikaCancelResult, type NikaCheckFinding, type NikaCheckOptions, type NikaCheckResult, NikaCompatibilityError, type NikaConfig, NikaConfigurationError, type NikaCostQualifier, NikaEngineUnavailable, NikaError, type NikaEvent, NikaEventBufferOverflowError, type NikaEventsOptions, type NikaExecutionCancelledEvent, type NikaExecutionId, type NikaExecutionInterruptedEvent, type NikaExecutionRefusedEvent, type NikaExecutionSettledEvent, type NikaExecutionStartedEvent, type NikaJobId, type NikaJournalEvidence, type NikaLocalConfig, type NikaMachineError, NikaObservationInterrupted, type NikaOperation, NikaOperationError, type NikaOperationFinding, NikaProtocolError, type NikaReceipt, type NikaRemoteConfig, type NikaRun, type NikaRunCause, type NikaRunEvent, type NikaRunEventKind, type NikaRunId, type NikaRunOptions, NikaRunOwnershipError, type NikaRunResult, type NikaRunSealedEvent, type NikaRunSettledEvent, type NikaRunStatus, type NikaScheduleAfterSkip, type NikaScheduleApplyResult, type NikaScheduleClaim, type NikaScheduleDefinition, type NikaScheduleDue, type NikaScheduleFinding, type NikaScheduleLastDecision, type NikaScheduleMissed, type NikaScheduleOptions, type NikaScheduleOverlap, type NikaSchedulePause, type NikaScheduleSlot, type NikaScheduleStatus, type NikaScheduleWhen, type NikaSettlement, type NikaSpend, type NikaTaskCompletedEvent, type NikaTaskScheduledEvent, type NikaTaskStartedEvent, type NikaTaskTally, type NikaTraceVerifyOptions, type NikaTraceVerifyResult, NikaTransportError, type NikaTransportKind, type NikaUnknownEvent, type NikaWorkflowCompletedEvent, type NikaWorkflowFailedEvent, type NikaWorkflowInterruptedEvent, type NikaWorkflowMetadata, type NikaWorkflowStartedEvent, isNikaRunSealedEvent, isNikaRunSettledEvent, isNikaRunSucceeded, isNikaTerminalEvent };