@almadar/shell-node 0.0.0-stage → 1.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.
@@ -0,0 +1,473 @@
1
+ import { EventPayload, EffectHandlers, EvaluationContextExtensions, KernelModule, SecretPortsOptions, OsGrantPort, OsHostPort, EventBus, TraitState } from '@almadar/shell-runtime';
2
+ import { EventRequest, EventResponse, BusEventSource, OrbitalDefinition, PersistenceAdapter, OrbitalSchema, RowSetRef, RowQueryPage, ExternalInput, UserContext, ServiceHostPorts, DispatchRequestOutcome, ExternalInputRequest, ClientEffectTuple, InboundDelivery, InboundAnswer } from '@almadar/core';
3
+ export { ClientEffectTuple, ClientNavigateBackTuple, ClientNavigateTuple, ClientRenderUITuple, EventRequest, EventResponse, TransitionRejection } from '@almadar/core';
4
+
5
+ /**
6
+ * OrbitalServerRuntime: the Node host that runs a registered program on the kernel. It answers the kernel's asks
7
+ * (rows, services, secrets, `os` through the given os host, live streams), drives its ticks and mounts; it serves no
8
+ * HTTP routes (a served program composes std-http-server for that).
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+
13
+ /** @deprecated Use OrbitalSchema from @almadar/core */
14
+ type RuntimeOrbitalSchema = OrbitalSchema;
15
+ /** @deprecated Use OrbitalDefinition from @almadar/core */
16
+ type RuntimeOrbital = OrbitalDefinition;
17
+ /**
18
+ * Incremental-push item streamed to an SSE client mid-dispatch (an emitted
19
+ * event or a client effect), before the response resolves.
20
+ */
21
+ type PushItem = {
22
+ type: 'event';
23
+ data: {
24
+ event: string;
25
+ payload?: EventPayload;
26
+ source?: BusEventSource;
27
+ };
28
+ timestamp?: number;
29
+ } | {
30
+ type: 'effect';
31
+ data: ClientEffectTuple;
32
+ timestamp?: number;
33
+ };
34
+ /**
35
+ * Registered orbital with runtime state
36
+ */
37
+ interface RegisteredOrbital {
38
+ schema: OrbitalDefinition;
39
+ }
40
+ /**
41
+ * One persist-envelope success emit, handed to the live-broadcast sink
42
+ * (`setLiveBroadcastSink`). Fired only from the `persist` effect's
43
+ * `emit:{success}` envelope (batch and single-op) — never from the generic
44
+ * emit funnel — so transport layers can fan it out to every OTHER
45
+ * connected client without matching on event names.
46
+ */
47
+ interface LiveBroadcastItem {
48
+ event: string;
49
+ payload?: EventPayload;
50
+ source: BusEventSource;
51
+ /** `clientId` of the request that produced this emit. */
52
+ originClientId?: string;
53
+ /**
54
+ * `peers`: every OTHER client (persist envelopes, tick relay). `origin`:
55
+ * only the requesting client, while its request is still running (a
56
+ * `call-service`'s live `emit.onMessage`).
57
+ */
58
+ target: 'peers' | 'origin';
59
+ }
60
+ /**
61
+ * The result of a dispatch the host ran on its own — a follow-on step's `call-service`
62
+ * outcome, run after the request that started the call had answered — for the tab that
63
+ * asked (`originClientId`). Handed to the host-dispatch sink (`setHostDispatchSink`).
64
+ */
65
+ interface HostDispatchItem {
66
+ orbitalName: string;
67
+ request: EventRequest;
68
+ response: EventResponse;
69
+ originClientId?: string;
70
+ }
71
+ /**
72
+ * Loader configuration for resolving `uses` imports
73
+ */
74
+ interface LoaderConfig {
75
+ /** Where `orb` resolves a registered program's imports from, when no `programHost` names it. */
76
+ basePath: string;
77
+ }
78
+ /**
79
+ * Runtime configuration
80
+ */
81
+ interface OrbitalServerRuntimeConfig {
82
+ /** Enable debug logging */
83
+ debug?: boolean;
84
+ /**
85
+ * Snapshot cadence (ms) for relaying tick-stamped broadcasts to other
86
+ * clients — newest-per-(client, orbital, event) wins between flushes
87
+ * (T6, docs/Almadar_Tick_Loop.md §3a). Default 50 (≈20Hz).
88
+ */
89
+ tickRelayIntervalMs?: number;
90
+ /** Custom effect handlers (for integrating with your data layer) */
91
+ effectHandlers?: Partial<EffectHandlers>;
92
+ /** Persistence adapter for entity data */
93
+ persistence?: PersistenceAdapter;
94
+ /** Where a registered program with imports is resolved from (`orb resolve`). */
95
+ loaderConfig?: LoaderConfig;
96
+ /**
97
+ * Additional fields to spread onto every EvaluationContext.
98
+ * Use this to inject module contexts (e.g., { agent: AgentContext }).
99
+ * The evaluator dispatches agent/* operators to ctx.agent.
100
+ */
101
+ contextExtensions?: EvaluationContextExtensions;
102
+ /**
103
+ * The program host behind behavior/catalog|describe|source and
104
+ * program/read|print|eval: the project root `orb` runs from. Absent means
105
+ * those effects fail explicitly ("no program host configured").
106
+ */
107
+ programHost?: {
108
+ cwd: string;
109
+ orbBin?: string;
110
+ };
111
+ /**
112
+ * The initialised `@almadar/kernel` module that decides execution and whose I/O this runtime answers with its
113
+ * persistence, service and program-host adapters. Absent, the runtime loads the installed `@almadar/kernel` itself
114
+ * (`loadInstalledKernel`) when a program is first registered.
115
+ */
116
+ kernel?: KernelModule;
117
+ /**
118
+ * What the kernel's secret, random and credential asks run on: optionally the secret store, the CSPRNG and the
119
+ * credential administration port. Absent, those asks fail as unavailable.
120
+ */
121
+ secretPorts?: SecretPortsOptions;
122
+ /**
123
+ * Builds the `os` host of the kernel engine from the grant port backed by the kernel (`createNodeOsHost` from
124
+ * `@almadar/shell-node`). Absent, every `os` ask is denied, as the native host does with none.
125
+ */
126
+ osHost?: (grants: OsGrantPort) => OsHostPort;
127
+ /** The clock the kernel's `clock` ask is answered from, in epoch milliseconds; absent, the system clock. */
128
+ clock?: () => number;
129
+ }
130
+
131
+ /**
132
+ * Check whether a schema needs preprocessing (has `uses` declarations or
133
+ * un-inlined cross-orbital trait references).
134
+ *
135
+ * Cross-orbital refs are trait entries like
136
+ * `{ ref: "Modal.traits.ModalRecordModal", ... }` with no inline
137
+ * `stateMachine`. If these aren't resolved before `register()` runs, the
138
+ * trait binder produces an empty state machine and all interactions
139
+ * targeting the trait are silently dropped.
140
+ */
141
+ /**
142
+ * Walk a trait's DECLARED config schema (`{ icon: { type, default }, ... }`)
143
+ * and collect a flat `{ icon: <default>, ... }` map of just the default
144
+ * values. Used to seed the `@config.X` binding context with the atom's
145
+ * own declared defaults before any call-site override is applied. Mirrors
146
+ * the compiled path's `DEFAULT_<TRAIT>_CONFIG` constant emitted by
147
+ * backend.rs's Solution-1 plumbing.
148
+ *
149
+ * Returns `undefined` when the trait has no config schema or none of its
150
+ * fields declare a default — keeps the caller's existing fast-path.
151
+ */
152
+ /**
153
+ * Structural shape that both `@almadar/core`'s `Trait` and
154
+ * `ResolvedTrait` satisfy: a `config?` map keyed by field name whose
155
+ * values either carry a `default` (the declared-schema form loaded
156
+ * from `.orb`) or are bare values (the runtime-resolved form).
157
+ *
158
+ * Widening to a structural parameter lets callers from the resolved
159
+ * side (e.g., `@almadar/ui`'s `useTraitStateMachine`) pass their own
160
+ * `ResolvedTrait` without an `as unknown as` cast.
161
+ */
162
+ /**
163
+ * Read the `default` from each field of a trait's declared
164
+ * `config { }` schema and return the flat `{ key: default, ... }`
165
+ * map. Used to seed `@config.X` binding context with the atom's
166
+ * own declared defaults before any call-site override is applied.
167
+ *
168
+ * Mirrors the compiled path's `DEFAULT_<TRAIT>_CONFIG` constant
169
+ * emitted by `backend.rs` Solution-1.
170
+ */
171
+ /** A program with imports registered where `orb` cannot run (a browser): resolve it first (`orb resolve`). */
172
+ declare class UnresolvedProgramError extends Error {
173
+ constructor(schemaName: string);
174
+ }
175
+ /** What `register` takes beside the schema: the folder its `uses lazy` behaviors sit beside (EXEC-LOAD-1). The program carries its own messages. */
176
+ interface RegisterOptions {
177
+ lazyDir?: string;
178
+ }
179
+ declare class OrbitalServerRuntime {
180
+ protected orbitals: Map<string, RegisteredOrbital>;
181
+ private eventBus;
182
+ private config;
183
+ /** The row store a host-supplied `persistence` replaces: the kernel's own `MemoryStore`, opened by the first `register()`. */
184
+ private ownedStore;
185
+ /**
186
+ * The bound persistence adapter (host-supplied, else the kernel's own memory store). Public so a test can
187
+ * inspect committed rows honestly. A runtime that owns its store has one from the first `register()`.
188
+ */
189
+ get persistence(): PersistenceAdapter;
190
+ /** The kernel running the registered program; null before a program is registered. */
191
+ private kernelEngine;
192
+ /** What the kernel holds of every trait of the registered program, read once when the kernel opens. */
193
+ private programSurface;
194
+ /** The `os` handles of the program the kernel runs; closed when that program is replaced, reset or dropped. */
195
+ private kernelOs;
196
+ /** Drives the kernel's one tick clock: every pass asks `KernelEngine.tickPass` which ticks are due. */
197
+ private tickTimer;
198
+ private programHandlersPromise;
199
+ private resolvedSchema;
200
+ /** The folder the program's lazy files sit beside; the pages that name them are on `resolvedSchema.lazyPages`. */
201
+ private lazyDir;
202
+ /** Wired by the hosting server (e.g. the playground SSE endpoint) via `setLiveBroadcastSink`. */
203
+ private readonly liveSubscribers;
204
+ private liveBroadcastSink;
205
+ private hostDispatchSink;
206
+ /** The one-shot timer that flushes the kernel's coalesced tick relay window. */
207
+ private tickRelayTimer;
208
+ constructor(config: OrbitalServerRuntimeConfig);
209
+ /**
210
+ * Lazily wire the program host handlers (behavior/* and program/* effects),
211
+ * merging them UNDER any user-provided handlers. Only when `programHost`
212
+ * is configured; otherwise the effects fail explicitly.
213
+ */
214
+ private ensureProgramHandlers;
215
+ /**
216
+ * Register an OrbitalSchema for execution.
217
+ *
218
+ * Auto-preprocesses the schema when it contains `uses` declarations or
219
+ * unresolved cross-orbital trait references (e.g. a trait with
220
+ * `ref: "Modal.traits.ModalRecordModal"` and no inline `stateMachine`).
221
+ * Without preprocessing, those refs arrive empty at the state machine and
222
+ * button clicks silently do nothing — see Phase 9.5.H.
223
+ *
224
+ * Preprocessing needs a loader. If `loaderConfig` is set, that loader is
225
+ * used. Otherwise, a default loader is constructed that points at
226
+ * `<cwd>` (for `basePath`) and the nearest `node_modules/@almadar/std` (for
227
+ * `stdLibPath`), which matches how every caller in this monorepo has the
228
+ * std registry on disk.
229
+ */
230
+ /**
231
+ * The in-flight (or last-completed) app mutation — `register()` chains its
232
+ * body onto this, and `unregisterAll()` stamps a marker after clearing.
233
+ * `processOrbitalEvent` consults it when the requested orbital is missing:
234
+ * during a catalog-style app swap the new schema's registration is already
235
+ * in flight while a client's first events arrive, and answering those with
236
+ * an immediate `Orbital not found` 404 (the pre-fix behavior) races the
237
+ * swap — big multi-orbital organisms lost their mount INITs intermittently
238
+ * while single-orbital ones almost always won. Awaiting the epoch and
239
+ * re-reading the map turns the race into a brief wait. `BrowserPlayground`
240
+ * gated dispatches on registration ad hoc for the same race; the epoch is
241
+ * the canonical, host-wide fix.
242
+ */
243
+ private registrationEpoch;
244
+ /**
245
+ * Reentrancy guard for `withRegistrationMutation`. While a bracket is
246
+ * open, `register()`/`unregisterAll()` must NOT chain/stamp the epoch:
247
+ * the callback's sequential awaits already order them, and chaining a
248
+ * `register()` awaited by the callback onto the bracket's gate would
249
+ * deadlock (callback → register → epoch → gate → callback's finally).
250
+ */
251
+ private registrationMutationDepth;
252
+ register(schema: OrbitalSchema, options?: RegisterOptions): Promise<void>;
253
+ private doRegister;
254
+ /** The kernel's own row store, opened once in the register phase when the host supplied none. */
255
+ private openOwnedStore;
256
+ /**
257
+ * One-call entry point: read an `.orb` file from disk, parse it, preprocess
258
+ * cross-orbital imports, and register the result. Callers never touch raw
259
+ * `.orb` bytes — `register()` handles preprocessing internally.
260
+ *
261
+ * Node only. Browsers must receive already-resolved schemas from their
262
+ * server (see `getResolvedSchema()`).
263
+ */
264
+ registerFromFile(path: string): Promise<void>;
265
+ /** A program with imports resolved by `orb` from the configured base path (Node only: the one resolver is the compiler). */
266
+ private resolveWithOrb;
267
+ /**
268
+ * Register a single orbital
269
+ */
270
+ private registerOrbitalAsync;
271
+ /** The adapters the kernel's I/O is answered with: this runtime's persistence, services and program host. */
272
+ private secretPorts;
273
+ private kernelPorts;
274
+ /** One live message of a running `call-service`, stamped as its calling trait, to the requesting tab only. */
275
+ private deliverLiveMessage;
276
+ /** The traits of one orbital as the kernel holds them. */
277
+ private traitsOf;
278
+ /** The project root this runtime hands `orb` and the kernel's language data: the program host's cwd, else the loader base path. */
279
+ private programRoot;
280
+ /** The kernel module this runtime runs on: the one the host handed in, else the installed `@almadar/kernel`. */
281
+ private kernelModule;
282
+ /** (Re)open the kernel on the program just registered. */
283
+ private openKernel;
284
+ /** Run the kernel's boot mounts for the server side (EXEC-ENDPOINT-3): the host sends what the kernel lists and chooses nothing. */
285
+ private mountBootEndpoints;
286
+ /** What answers the declared contract: the registered program's kernel, else the kernel's own program-less answers, which refuse every input and hook. */
287
+ private contractEngine;
288
+ private requireKernelEngine;
289
+ /** Ask the kernel's clock which ticks are due and start each as a `runTick` request to the orbital it names. */
290
+ private tickPass;
291
+ /** Run the kernel's clock on this host's timer when the program declares a tick. */
292
+ private restartTickClock;
293
+ /** A tick: the host owns the timer, the kernel decides whether and over which rows it fires. */
294
+ private executeTick;
295
+ /**
296
+ * Stop the host's timers
297
+ */
298
+ private cleanupTicks;
299
+ /**
300
+ * Unregister all orbitals and clean up
301
+ */
302
+ unregisterAll(): void;
303
+ /**
304
+ * Bracket a multi-step app mutation (the classic swap is
305
+ * `unregisterAll()` → resolve next schema → `register()`) as ONE
306
+ * registration epoch. `register()` alone chains only its own body onto
307
+ * the epoch, so between `unregisterAll()` and the `register()` call the
308
+ * runtime's map is empty while the epoch marker has already resolved —
309
+ * any `processOrbitalEvent` that lands in that gap (the resolve of a big
310
+ * organism takes real time) 404s `Orbital not found` even though the
311
+ * requested orbital is milliseconds away from landing. Inside this
312
+ * bracket the epoch stays pending for the WHOLE callback, so mid-swap
313
+ * dispatches await the completed swap and then resolve against the new
314
+ * app. A failed callback still releases the epoch (chained on both
315
+ * branches), so a failed swap falls through to the honest 404 instead of
316
+ * wedging the queue. Callbacks SERIALIZE: each bracket awaits the previous
317
+ * epoch before running `fn`, so two hosts swapping at once (a catalog
318
+ * select racing a preview remount's `/register`) cannot interleave their
319
+ * unregister/register sequences into a mixed registry. A bracket opened
320
+ * from INSIDE another bracket's callback runs `fn` directly — detected
321
+ * via the AsyncLocalStorage context below (a depth counter alone can't
322
+ * tell a true nest from a concurrent caller) — because the outer
323
+ * callback's awaits already serialize it and queueing on the outer gate
324
+ * would deadlock. Deadlock-free otherwise: `doRegister` never dispatches
325
+ * events, so awaiting dispatches never block registration progress.
326
+ */
327
+ /**
328
+ * Reentrancy context for `withRegistrationMutation`. A depth counter alone
329
+ * cannot distinguish "called from inside a bracket callback" (must run
330
+ * directly — queueing on the outer gate would deadlock) from "called
331
+ * concurrently while another bracket is in flight" (must queue — running
332
+ * directly would interleave two swaps). The ALS marks the callback's async
333
+ * context, which separates the two exactly.
334
+ */
335
+ private bracketAls;
336
+ private ensureBracketAls;
337
+ withRegistrationMutation<T>(fn: () => Promise<T>): Promise<T>;
338
+ /**
339
+ * Return every registered orbital's circuit to boot: trait states to their
340
+ * initial states, frames and row cache emptied, and a fresh mount (no trait
341
+ * awaiting INIT, nothing held).
342
+ */
343
+ resetCircuitState(): void;
344
+ /**
345
+ * Wire a live-broadcast sink. Called only from a `persist` effect's
346
+ * `emit:{success}` envelope firing site (batch and single-op) — see
347
+ * `docs/Almadar_Live_Push.md`. The hosting server (e.g. the playground's
348
+ * `/api/events` SSE endpoint) uses this to fan persist mutations out to
349
+ * every OTHER connected client; a fresh call replaces the previous sink.
350
+ */
351
+ setLiveBroadcastSink(sink: (item: LiveBroadcastItem) => void): void;
352
+ private publishLiveItem;
353
+ /** Wire where a host-run dispatch's result goes (see `HostDispatchItem`); a fresh call replaces the previous sink. */
354
+ setHostDispatchSink(sink: (item: HostDispatchItem) => void): void;
355
+ /** Run a follow-on step's call outcome as its own dispatch, and hand its result to the host-dispatch sink. */
356
+ private runDeferredOutcome;
357
+ /**
358
+ * A tick-stamped dispatch is a latest-state broadcast (T6): the kernel coalesces it with the others of the window
359
+ * (newest per origin client, orbital and event) and says how long the window stays open; this host only runs
360
+ * the timer.
361
+ */
362
+ private queueTickRelay;
363
+ private flushTickRelay;
364
+ /**
365
+ * `reference` resolved for the identity bound to `clientId`'s session (none: the anonymous viewer) against the store as it is now: the rows that still match its query and that identity's `@read`, in the reference's order, `total` re-counted. The kernel resolves through its server
366
+ * resolve flight. A client reaches it with
367
+ * `POST /:orbital/../resolve-rows`.
368
+ */
369
+ resolveRows(reference: RowSetRef, clientId: string | undefined): Promise<RowQueryPage>;
370
+ /**
371
+ * Process an event for an orbital — the stateful host's thin shell over
372
+ * the unified `evaluateOrbitalEvent` composition (design:
373
+ * docs/Almadar_Runtime_Stateless_Stateful_PLAN.md §4.1). This method owns
374
+ * ONLY session concerns: orbital lookup, viewer normalization, the lazy
375
+ * OS/substrate handler wiring, the per-request relay mask
376
+ * (G-RUNTIME-031 — the client's mounted set as DATA, replacing the
377
+ * deleted blanket `originClientId` skip), the tick snapshot relay, and
378
+ * the cross-orbital listens relay (a listener registered under a
379
+ * DIFFERENT orbital than the emitter — the per-orbital composition's
380
+ * in-band fan-out covers the rest). Target resolution, payload
381
+ * validation, the cascade, the fan-out, structured rejections, and
382
+ * response assembly are the composition's, identical to the stateless
383
+ * path.
384
+ *
385
+ * Serialization: the whole evaluation runs on ONE runtime-wide async
386
+ * queue. The composition commits manager state directly (no per-trait
387
+ * actor queue), so concurrent requests against the long-lived session
388
+ * manager would otherwise both evaluate from the same held state and
389
+ * lose a transition. Coarser than the old per-(trait, entityId) actor
390
+ * queues — a deliberate W4 tradeoff, recorded in the plan doc.
391
+ *
392
+ * @param onPush - Optional incremental-push callback. Called immediately
393
+ * when an event is emitted or a client effect fires, before the promise
394
+ * resolves. Used by the SSE streaming path to write items to the
395
+ * response as they arrive rather than buffering and flushing at the end.
396
+ */
397
+ /**
398
+ * Read an orbital by name, awaiting an in-flight registration mutation
399
+ * first when the lookup misses (G-RUNTIME-038): mid-swap lookups 404ed
400
+ * against the emptied map even though the requested orbital was
401
+ * milliseconds from landing. A failed mutation falls through to the miss.
402
+ */
403
+ private resolveRegisteredOrbital;
404
+ /** The first request that names a `uses lazy` orbital registers it here; the kernel loads the same file on that request's dispatch (EXEC-LOAD-2). */
405
+ private loadLazyOrbital;
406
+ /** The program's declared external inputs: what an outside client may send which trait. */
407
+ listExternalInputs(): ExternalInput[];
408
+ /**
409
+ * The outside-client input channel: an API caller, an agent acting as the
410
+ * user, an MCP client. Only a declared external input of the target trait is
411
+ * dispatched — through `processOrbitalEvent`, so guards, entity policies and
412
+ * cascades apply exactly as for a click. Anything else is refused with
413
+ * `not-an-external-input`. The app's own UI keeps using `processOrbitalEvent`.
414
+ */
415
+ /**
416
+ * The running app lent to one `call-service` provider as the caller: the
417
+ * declared inputs, the input channel as `user`, and the rows `user` may read
418
+ * (the entity's `@read` policy, the same rule a `fetch` effect applies).
419
+ */
420
+ servicePorts(caller: {
421
+ orbital: string;
422
+ trait: string;
423
+ }, user: UserContext | undefined, message?: (payload: EventPayload) => void, assertReentry?: () => void): ServiceHostPorts;
424
+ /**
425
+ * A `program/dispatch` event request, as the events route (or with `input`, the inputs route) runs it: the
426
+ * runs as the session's identity, never a viewer the request names. An unknown orbital is `ORBITAL_NOT_FOUND`, an undeclared
427
+ * locale `LOCALE_NOT_DECLARED`; an inbound-only event and an undeclared input are the routes' refusals.
428
+ */
429
+ dispatchEventRequest(orbital: string, parsed: EventRequest, input: boolean, stream?: boolean): Promise<DispatchRequestOutcome>;
430
+ dispatchExternalInput(orbitalName: string, request: ExternalInputRequest, onPush?: (item: PushItem) => void): Promise<EventResponse>;
431
+ /**
432
+ * An inbound delivery (`/api/hooks/<name>`): the runtime decides whether the name is served, runs
433
+ * the handler through `processOrbitalEvent` and answers; the host only carries the bytes.
434
+ */
435
+ /**
436
+ * An event that is an inbound hook's is delivered only by `deliverInbound`: the app's own event
437
+ * route refuses it, as the input channel refuses an event that is no declared input.
438
+ */
439
+ refuseInboundOnly(orbitalName: string, request: Pick<EventRequest, 'event' | 'targetTrait'>): EventResponse | undefined;
440
+ deliverInbound(name: string, delivery: InboundDelivery, onPush?: (item: PushItem) => void): Promise<InboundAnswer>;
441
+ processOrbitalEvent(orbitalName: string, request: EventRequest, onPush?: (item: PushItem) => void): Promise<EventResponse>;
442
+ /**
443
+ * One request evaluated on the kernel, which orders it among every other (EXEC-CONC-2), then its emits relayed
444
+ * to the host sinks.
445
+ */
446
+ private evaluateForOrbital;
447
+ /**
448
+ * Feed the host sinks from a kernel response: the kernel answers a dispatch whole, so each emit reaches the
449
+ * event bus (the public firehose) and `onPush` once the dispatch is done, in the order the response carries them.
450
+ */
451
+ private publishKernelResponse;
452
+ /** This app's in-flight keyed `call-service`s, shared by every transition it runs (`cancel-call`). */
453
+ private readonly inFlightCalls;
454
+ /**
455
+ * Get the event bus for manual event emission
456
+ */
457
+ getEventBus(): EventBus;
458
+ /**
459
+ * Get state for a specific orbital/trait
460
+ */
461
+ getState(orbitalName: string, traitName?: string): TraitState | Record<string, TraitState> | undefined;
462
+ /**
463
+ * List registered orbitals
464
+ */
465
+ listOrbitals(): string[];
466
+ /**
467
+ * Check if an orbital is registered
468
+ */
469
+ hasOrbital(name: string): boolean;
470
+ }
471
+
472
+ export { OrbitalServerRuntime, UnresolvedProgramError };
473
+ export type { HostDispatchItem, LiveBroadcastItem, LoaderConfig, OrbitalServerRuntimeConfig, PushItem, RegisterOptions, RegisteredOrbital, RuntimeOrbital, RuntimeOrbitalSchema };
@@ -0,0 +1,3 @@
1
+ export { OrbitalServerRuntime, UnresolvedProgramError } from './chunk-3PNZYEZQ.js';
2
+ import './chunk-VQVAHUAX.js';
3
+ import './chunk-EEYGL7AB.js';