@almadar/shell-runtime 0.1.0 → 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.
Files changed (167) hide show
  1. package/dist/chunk-57SBCUSM.js +62 -0
  2. package/dist/chunk-625EP7W2.js +108 -0
  3. package/dist/{chunk-NATGCIVM.js → chunk-7WB6VWRK.js} +344 -129
  4. package/dist/{chunk-Q2H75UYT.js → chunk-A2JJT4GA.js} +1 -37
  5. package/dist/chunk-BAS26HBN.js +10 -0
  6. package/dist/{chunk-REPX5QPI.js → chunk-BOVU4TCQ.js} +11 -3
  7. package/dist/chunk-BY5G4225.js +6 -0
  8. package/dist/chunk-DFDNHVDW.js +284 -0
  9. package/dist/chunk-I3TKINSO.js +398 -0
  10. package/dist/{chunk-DYOJGLIX.js → chunk-LKWYCYX5.js} +2 -5
  11. package/dist/chunk-LYFIQPXX.js +1 -0
  12. package/dist/{chunk-VNMG7NKY.js → chunk-MU335ZA4.js} +20 -26
  13. package/dist/{chunk-ODJCZ27I.js → chunk-N7HYNKK6.js} +35 -2
  14. package/dist/{chunk-4J2QEIUV.js → chunk-NTFQ36UN.js} +4 -30
  15. package/dist/chunk-NU6LVKGS.js +15 -0
  16. package/dist/chunk-P2N6K2IV.js +20 -0
  17. package/dist/{chunk-QQRDUMB2.js → chunk-QCJWPXLH.js} +11 -11
  18. package/dist/{chunk-QELZ6TEJ.js → chunk-UD2CXYSJ.js} +39 -3
  19. package/dist/{chunk-UJHOUZAL.js → chunk-V4EMDPCO.js} +2 -5
  20. package/dist/chunk-VNGXRYFF.js +9 -0
  21. package/dist/{chunk-HNOAZWFH.js → chunk-WGCWJOT2.js} +2 -0
  22. package/dist/chunk-X6W44WHO.js +26 -0
  23. package/dist/chunk-ZUSM4VW4.js +197 -0
  24. package/dist/client/EventTransport.d.ts +23 -7
  25. package/dist/client/EventTransport.js +1 -2
  26. package/dist/client/awaiting.js +0 -1
  27. package/dist/client/channel-transport.d.ts +6 -6
  28. package/dist/client/channel-transport.js +0 -1
  29. package/dist/client/circuit-store.d.ts +16 -5
  30. package/dist/client/circuit-store.js +2 -3
  31. package/dist/client/client-kernel.d.ts +36 -15
  32. package/dist/client/declared-input-dispatch.d.ts +19 -2
  33. package/dist/client/declared-input-dispatch.js +1 -2
  34. package/dist/client/inbound-dispatch.d.ts +21 -2
  35. package/dist/client/inbound-dispatch.js +1 -2
  36. package/dist/client/local-fold.d.ts +15 -8
  37. package/dist/client/local-fold.js +1 -2
  38. package/dist/client/render-sigils.js +0 -1
  39. package/dist/client/state-book.d.ts +9 -16
  40. package/dist/client/state-book.js +1 -2
  41. package/dist/client/trait-mount-error.js +0 -1
  42. package/dist/credentials/env-vars.d.ts +5 -1
  43. package/dist/credentials/env-vars.js +1 -3
  44. package/dist/credentials/scope.d.ts +8 -7
  45. package/dist/credentials/scope.js +0 -1
  46. package/dist/credentials/vault.d.ts +142 -0
  47. package/dist/credentials/vault.js +1 -0
  48. package/dist/effects/in-flight-calls.js +0 -1
  49. package/dist/effects/on-device-model.js +0 -1
  50. package/dist/events/EventBus.d.ts +1 -4
  51. package/dist/events/EventBus.js +0 -1
  52. package/dist/events/emit-stamp.js +0 -1
  53. package/dist/index.d.ts +25 -42
  54. package/dist/index.js +27 -45
  55. package/dist/kernel/decode.d.ts +8 -10
  56. package/dist/kernel/decode.js +1 -2
  57. package/dist/kernel/engine.d.ts +132 -31
  58. package/dist/kernel/engine.js +7 -9
  59. package/dist/kernel/frame-applier.d.ts +8 -7
  60. package/dist/kernel/frame-applier.js +1 -2
  61. package/dist/kernel/host.d.ts +127 -16
  62. package/dist/kernel/host.js +4 -7
  63. package/dist/kernel/lane.d.ts +1 -22
  64. package/dist/kernel/lane.js +1 -2
  65. package/dist/kernel/os-fetch-port.d.ts +7 -0
  66. package/dist/kernel/os-fetch-port.js +3 -0
  67. package/dist/kernel/os-port.d.ts +30 -8
  68. package/dist/kernel/os-port.js +1 -2
  69. package/dist/kernel/program-effects.d.ts +11 -28
  70. package/dist/kernel/program-effects.js +1 -2
  71. package/dist/kernel/secret-ports.d.ts +139 -0
  72. package/dist/kernel/secret-ports.js +2 -0
  73. package/dist/kernel/wire.d.ts +50 -12
  74. package/dist/loader/fetch-loader.d.ts +26 -0
  75. package/dist/loader/fetch-loader.js +1 -0
  76. package/dist/loader/lazy-page.js +0 -1
  77. package/dist/loader/schema-loader.d.ts +1 -17
  78. package/dist/persistence/native-memory.js +0 -1
  79. package/dist/runtime/entities/declaredCollections.d.ts +6 -0
  80. package/dist/runtime/entities/declaredCollections.js +1 -0
  81. package/dist/runtime/evaluation/local-store-transport.d.ts +14 -23
  82. package/dist/runtime/evaluation/local-store-transport.js +9 -13
  83. package/dist/runtime/evaluation/residence-transport.d.ts +3 -3
  84. package/dist/runtime/evaluation/residence-transport.js +1 -2
  85. package/dist/runtime/evaluation/routed-persistence.js +0 -1
  86. package/dist/runtime/events/identity/routing.d.ts +2 -53
  87. package/dist/runtime/events/identity/routing.js +1 -2
  88. package/dist/runtime/types.d.ts +5 -205
  89. package/dist/runtime/types.js +1 -2
  90. package/dist/service/default-call-service.js +0 -1
  91. package/dist/service/service-provider.js +0 -1
  92. package/package.json +8 -5
  93. package/dist/chunk-2JU7Y4KU.js +0 -21
  94. package/dist/chunk-46RWK2B5.js +0 -28
  95. package/dist/chunk-4ZICQ5PM.js +0 -192
  96. package/dist/chunk-53IPZXDP.js +0 -76
  97. package/dist/chunk-5D63EMO5.js +0 -16
  98. package/dist/chunk-CPSQXEJ6.js +0 -55
  99. package/dist/chunk-CQP5XAX6.js +0 -173
  100. package/dist/chunk-CROS2GEX.js +0 -49
  101. package/dist/chunk-D4XJTBLB.js +0 -217
  102. package/dist/chunk-D5USD2EX.js +0 -232
  103. package/dist/chunk-EV56K4GB.js +0 -63
  104. package/dist/chunk-FQ6IZMIU.js +0 -10
  105. package/dist/chunk-HMK6YMQS.js +0 -135
  106. package/dist/chunk-IHQLE5M7.js +0 -62
  107. package/dist/chunk-JFWFDUTR.js +0 -35
  108. package/dist/chunk-MHYSHSRG.js +0 -54
  109. package/dist/chunk-MLKGABMK.js +0 -7
  110. package/dist/chunk-NAECVIAR.js +0 -322
  111. package/dist/chunk-Q7JK4KY7.js +0 -9
  112. package/dist/chunk-RBUMDYFS.js +0 -681
  113. package/dist/chunk-SAS5KKCR.js +0 -43
  114. package/dist/chunk-SWPDU752.js +0 -28
  115. package/dist/chunk-T775TUCD.js +0 -18
  116. package/dist/chunk-VMOBW7RK.js +0 -21
  117. package/dist/chunk-WNPNNYXY.js +0 -22
  118. package/dist/chunk-XB5GYODW.js +0 -28
  119. package/dist/chunk-YL2SO5TP.js +0 -334
  120. package/dist/chunk-YO4LWS3I.js +0 -606
  121. package/dist/chunk-ZAQSS47X.js +0 -157
  122. package/dist/chunk-ZCQUUJIF.js +0 -129
  123. package/dist/client/ServerBridge.d.ts +0 -126
  124. package/dist/client/ServerBridge.js +0 -3
  125. package/dist/credentials/seed.d.ts +0 -21
  126. package/dist/credentials/seed.js +0 -2
  127. package/dist/credentials/store.d.ts +0 -110
  128. package/dist/credentials/store.js +0 -2
  129. package/dist/index-hT1xCdTq.d.ts +0 -46
  130. package/dist/kernel/beacon.d.ts +0 -32
  131. package/dist/kernel/beacon.js +0 -2
  132. package/dist/kernel/http.d.ts +0 -302
  133. package/dist/kernel/http.js +0 -6
  134. package/dist/kernel/oauth-effects.d.ts +0 -25
  135. package/dist/kernel/oauth-effects.js +0 -7
  136. package/dist/kernel/oauth-port.d.ts +0 -31
  137. package/dist/kernel/oauth-port.js +0 -2
  138. package/dist/loader/http-loader.d.ts +0 -111
  139. package/dist/loader/http-loader.js +0 -2
  140. package/dist/runtime/effects/composition/compose-behaviors.d.ts +0 -58
  141. package/dist/runtime/effects/composition/compose-behaviors.js +0 -4
  142. package/dist/runtime/effects/composition/event-wiring.d.ts +0 -38
  143. package/dist/runtime/effects/composition/event-wiring.js +0 -2
  144. package/dist/runtime/effects/composition/index.d.ts +0 -5
  145. package/dist/runtime/effects/composition/index.js +0 -6
  146. package/dist/runtime/effects/composition/layout-strategy.d.ts +0 -35
  147. package/dist/runtime/effects/composition/layout-strategy.js +0 -2
  148. package/dist/runtime/effects/composition/pipe.d.ts +0 -25
  149. package/dist/runtime/effects/composition/pipe.js +0 -2
  150. package/dist/runtime/entities/mockStoreSeed.d.ts +0 -56
  151. package/dist/runtime/entities/mockStoreSeed.js +0 -3
  152. package/dist/runtime/entities/seedBrowserStore.d.ts +0 -28
  153. package/dist/runtime/entities/seedBrowserStore.js +0 -2
  154. package/dist/runtime/entities/std-mock-seed.d.ts +0 -87
  155. package/dist/runtime/entities/std-mock-seed.js +0 -2
  156. package/dist/runtime/time/TickScheduler.d.ts +0 -77
  157. package/dist/runtime/time/TickScheduler.js +0 -3
  158. package/dist/runtime/time/cron.d.ts +0 -25
  159. package/dist/runtime/time/cron.js +0 -2
  160. package/dist/runtime/time/duration.d.ts +0 -20
  161. package/dist/runtime/time/duration.js +0 -2
  162. package/dist/runtime/traits/OrbitalTraitParsing.d.ts +0 -34
  163. package/dist/runtime/traits/OrbitalTraitParsing.js +0 -2
  164. package/dist/runtime/traits/listen-targets.d.ts +0 -16
  165. package/dist/runtime/traits/listen-targets.js +0 -3
  166. package/dist/runtime/traits/trait-index.d.ts +0 -35
  167. package/dist/runtime/traits/trait-index.js +0 -3
@@ -1,12 +1,9 @@
1
1
  import { CallServiceHandler } from '../service/default-call-service.js';
2
2
  import { ServiceCallContext } from '../service/service-provider.js';
3
- import { EventPayload, BusEventSource, BusEventListener, Unsubscribe as Unsubscribe$1, BusEvent, EntityRow, TraitConfig, UserContext, NavItem, RuntimeValue, TraitId, OrbitalId, EventId, FieldValue, SExpr, FetchResult, RowSetRef, PatternConfig, OrbitalDefinition, PageFactField, BrowserPageFacts, JsonValue, ServiceHostPorts, AgentContext, LlmContext, WorkspaceContext, SessionContext, MemoryContext, TraceContext, ResolvedPatternProps } from '@almadar/core';
3
+ import { EventPayload, BusEventSource, BusEventListener, Unsubscribe as Unsubscribe$1, BusEvent, EntityRow, TraitConfig, UserContext, NavItem, RuntimeValue, FieldValue, SExpr, FetchResult, RowSetRef, PatternConfig, PageFactField, BrowserPageFacts, JsonValue, ServiceHostPorts, AgentContext, LlmContext, WorkspaceContext, SessionContext, MemoryContext, TraceContext, ResolvedPatternProps } from '@almadar/core';
4
4
  export { EntityRow, EventPayload, FetchResult, ServiceParams } from '@almadar/core';
5
5
  import { ProgramEffectName, ProgramEffectOutcome } from '../kernel/program-effects.js';
6
- import { ComposeBehaviorsInput, ComposeBehaviorsResult } from './effects/composition/compose-behaviors.js';
7
- import { EventWiringEntry } from './effects/composition/event-wiring.js';
8
- import { LayoutStrategy } from './effects/composition/layout-strategy.js';
9
- import { PipeStep } from './effects/composition/pipe.js';
6
+ import '@almadar/core/kernel-wire';
10
7
 
11
8
  /**
12
9
  * Unified Runtime Types
@@ -18,24 +15,6 @@ import { PipeStep } from './effects/composition/pipe.js';
18
15
 
19
16
  /** Alias for ResolvedPatternProps to avoid breaking internal consumers */
20
17
  type PatternProps = ResolvedPatternProps;
21
- /**
22
- * Value a render-ui pattern prop can carry AFTER interpolation. Mirrors
23
- * `FieldValue` but extends with `RuntimeRenderPattern` so nested pattern
24
- * configs (children, slot props that are themselves render-ui nodes)
25
- * round-trip without an `unknown` escape hatch.
26
- */
27
- type RuntimePatternValue = string | number | boolean | null | undefined | EntityRow | EntityRow[] | readonly RuntimePatternValue[] | RuntimeRenderPattern;
28
- /**
29
- * Shape of a render-ui pattern AFTER interpolation, as the runtime hands
30
- * it to `EffectHandlers.renderUI`. Different from `ResolvedPatternProps`
31
- * (`@almadar/core`) because the post-interpolation pattern carries
32
- * resolved EntityRow values (e.g. `{ entity: <row> }` from `@payload.row`)
33
- * not just primitives. Used by render-ui observability helpers to narrow
34
- * safely without `unknown` casts.
35
- */
36
- interface RuntimeRenderPattern {
37
- readonly [prop: string]: RuntimePatternValue;
38
- }
39
18
 
40
19
  type ConfigContext = TraitConfig;
41
20
  /**
@@ -65,40 +44,12 @@ interface IEventBus {
65
44
  /** Clear all listeners */
66
45
  clear(): void;
67
46
  }
68
- /**
69
- * Result of processing an event through a state machine
70
- */
71
- interface TransitionResult {
72
- /** Whether a transition was executed */
73
- executed: boolean;
74
- /** New state after transition (same as current if not executed) */
75
- newState: string;
76
- /** Previous state before transition */
77
- previousState: string;
78
- /** Effects to execute (empty if guard failed or no transition found) */
79
- effects: SExpr[];
80
- /** The transition that was executed (undefined if none) */
81
- transition?: {
82
- from: string;
83
- to: string;
84
- event: string;
85
- };
86
- /** Guard evaluation result (undefined if no guard) */
87
- guardResult?: boolean;
88
- }
89
47
  /**
90
48
  * Effect handlers interface - platform-specific implementations
91
49
  *
92
50
  * Client: React hooks, DOM, router
93
51
  * Server: Express, database, integrators
94
52
  */
95
- /** What one `http` effect came to: the `<METHOD> <origin><path>` it addressed and, on failure, the declared `emit.failure` event the program routed it to. */
96
- interface HttpEffectReport {
97
- success: boolean;
98
- target: string;
99
- error?: string;
100
- routed?: string;
101
- }
102
53
  interface EffectHandlers {
103
54
  /**
104
55
  * Emit an event to the event bus.
@@ -179,8 +130,6 @@ interface EffectHandlers {
179
130
  * the instant a real async persistence backend (Firestore) was wired in.
180
131
  */
181
132
  set: (entityId: string, field: string, value: FieldValue) => void | Promise<void>;
182
- /** Report the outcome of an `http` effect to the host's effect trace. */
183
- httpResult?: (report: HttpEffectReport) => void;
184
133
  /** Call an external service. `context` carries the caller's identity
185
134
  * (the same viewer entity ACL enforces against) so role-gated services
186
135
  * can enforce server-side; hosts forward it to the integration factory. */
@@ -255,37 +204,6 @@ interface EffectHandlers {
255
204
  navigateBack?: () => void;
256
205
  /** Log a message */
257
206
  log?: (message: string, level?: 'log' | 'warn' | 'error', data?: RuntimeValue) => void;
258
- /** Ref: declarative data subscription (server: same as fetch) */
259
- ref?: (entityType: string, options?: {
260
- id?: string;
261
- filter?: SExpr | Record<string, RuntimeValue>;
262
- limit?: number;
263
- offset?: number;
264
- include?: string[];
265
- }) => Promise<FetchResult | null>;
266
- /** Deref: one-shot data read (server: same as fetch) */
267
- deref?: (entityType: string, options?: {
268
- id?: string;
269
- filter?: SExpr | Record<string, RuntimeValue>;
270
- }) => Promise<FetchResult | null>;
271
- /** Swap!: atomic read-modify-write on an entity */
272
- swap?: (entityType: string, entityId: string, transform: SExpr) => Promise<EntityRow | null>;
273
- /** Watch: client-side reactive subscription (no-op on server) */
274
- watch?: (entityType: string, options?: {
275
- id?: string;
276
- filter?: SExpr | Record<string, RuntimeValue>;
277
- limit?: number;
278
- }) => void;
279
- /** Atomic: execute inner effects as a transaction */
280
- atomic?: (effects: SExpr[]) => Promise<void>;
281
- /** Compose multiple orbitals into one schema. Compile-time only. */
282
- composeBehaviors?: (input: ComposeBehaviorsInput) => ComposeBehaviorsResult;
283
- /** Apply cross-orbital event wiring. Compile-time only. */
284
- applyEventWiring?: (orbitals: OrbitalDefinition[], wiring: EventWiringEntry[]) => OrbitalDefinition[];
285
- /** Auto-detect layout strategy. Compile-time only. */
286
- detectLayoutStrategy?: (orbitals: OrbitalDefinition[], wiring?: EventWiringEntry[]) => LayoutStrategy;
287
- /** Left-to-right behavior pipeline. Compile-time only. */
288
- pipeBehaviors?: <T>(seed: T, ...steps: Array<PipeStep<T, T>>) => T;
289
207
  /** browser/open-file-picker — resolves with `{ files }` inside `result` */
290
208
  browserOpenFilePicker?: (options?: BrowserFilePickerOptions) => Promise<{
291
209
  files: BrowserFileMeta[];
@@ -321,33 +239,6 @@ interface EffectHandlers {
321
239
  programEffect?: (op: ProgramEffectName, args: readonly JsonValue[], context?: Pick<ServiceCallContext, 'principal' | 'role'>) => Promise<ProgramEffectOutcome>;
322
240
  agentPorts?: () => ServiceHostPorts | undefined;
323
241
  }
324
- /**
325
- * What a `batch` persist hands back — the shape `canonical-operators.json`
326
- * declares for persist's batch branch, so the `emit: { success }` envelope
327
- * carries exactly what the type system promises. Before this existed the
328
- * envelope emitted the raw INPUT array, so `?completedCount` / `?totalCount`
329
- * read `undefined` at runtime.
330
- *
331
- * Structurally an {@link EntityRow} — `operations` is an array of rows and the
332
- * counts are numbers, all valid `FieldValue`s — so `EffectHandlers.persist`
333
- * needs no widened return type and no cast: a batch summary reaches the bus by
334
- * the same path a create/update row does.
335
- *
336
- * Declared as a `type` alias, NOT an `interface`, deliberately: only an object
337
- * type alias gets TypeScript's implicit index signature, which is what makes it
338
- * assignable to `EntityRow`'s `Record<string, FieldValue | undefined>` half. As
339
- * an interface it fails that assignment (TS2322) and the only way to ship it
340
- * would be a cast — which the type-safety rule forbids, and rightly: the cast
341
- * would have hidden that the contract, not the value, was wrong.
342
- */
343
- type PersistBatchSummary = {
344
- /** One result row per attempted operation, in submission order. */
345
- operations: EntityRow[];
346
- /** How many operations completed before the batch stopped. */
347
- completedCount: number;
348
- /** How many were submitted. */
349
- totalCount: number;
350
- };
351
242
  /** Options for `browser/open-file-picker`. */
352
243
  interface BrowserFilePickerOptions {
353
244
  /** Allow selecting multiple files. */
@@ -390,11 +281,11 @@ interface BindingContext {
390
281
  user?: UserContext;
391
282
  /** The dispatch's one `now` stamp (ms epoch) — every guard, effect and time operator in it reads this. */
392
283
  now?: number;
393
- /** `@locale`: the viewer's locale (`OrbitalEventRequest.locale`, else the program's first declared locale). */
284
+ /** `@locale`: the viewer's locale (`EventRequest.locale`, else the program's first declared locale). */
394
285
  locale?: string;
395
286
  /** That locale's catalog — `i18n/t` reads it. */
396
287
  messages?: Readonly<Record<string, string>>;
397
- /** `@event`: the delivery being processed (`deliveryRecordValue`, Runtime Spec Clause 5.5). */
288
+ /** `@event`: the delivery being processed (Runtime Spec Clause 5.5). */
398
289
  event?: EventPayload;
399
290
  /** `@prevEvents`: deliveries this trait already received this dispatch. */
400
291
  prevEvents?: EventPayload[];
@@ -447,58 +338,6 @@ interface BindingContext {
447
338
  * narrow it to `Effect[]` at the executor boundary with {@link isEffectTuple}.
448
339
  */
449
340
  type Effect = [string, ...RuntimeValue[]];
450
- /**
451
- * Type guard: is this value an executable effect tuple (operator + args)?
452
- * Narrows wire-level `SExpr` effect lists to the executor-input `Effect`
453
- * without a cast. (Parameter is `RuntimeValue`, not `SExpr`, because a type
454
- * predicate's type must be assignable to its parameter's type — `Effect`'s
455
- * `RuntimeValue` tail is wider than `SExpr`. Every `SExpr` is a `RuntimeValue`,
456
- * so call sites pass either.)
457
- */
458
- declare function isEffectTuple(value: RuntimeValue): value is Effect;
459
- /**
460
- * Effect execution context
461
- */
462
- interface EffectContext {
463
- /** Trait name */
464
- traitName: string;
465
- /** Orbital that owns the firing trait. Used to stamp the source
466
- * metadata on emits so source-scoped listens (`TraitName EVENT` for
467
- * intra-orbital, `Orbital.TraitName EVENT` for cross-orbital) can
468
- * filter by emitter identity. */
469
- orbitalName?: string;
470
- /**
471
- * V4 dual-carry id sibling of `traitName` — stamped onto emit sources
472
- * so id-scoped `listens` (`buildSourceMatcher`) match by id,
473
- * rename-proof. The matcher compares ids ONLY when the listen source
474
- * carries one, so a name-only stamp never matches a `traitId`-carrying
475
- * listen (the chat SAVE → DO_CREATE relay died on the stateful path,
476
- * 2026-09-22). Parity with `OrbitalServerRuntime`'s emit stamp.
477
- */
478
- traitId?: TraitId;
479
- /**
480
- * V4 dual-carry id sibling of `orbitalName` — same contract as
481
- * `traitId`, for `kind: 'orbital'` listen sources.
482
- */
483
- orbitalId?: OrbitalId;
484
- /**
485
- * The trait's emit contracts — the emit-source stamp reads `eventId`
486
- * from the matching contract (parity with `OrbitalServerRuntime`'s
487
- * `emitContract?.eventId`).
488
- */
489
- emits?: ReadonlyArray<{
490
- event: string;
491
- eventId?: EventId;
492
- }>;
493
- /** Current state */
494
- state: string;
495
- /** Transition description */
496
- transition: string;
497
- /** Linked entity name */
498
- linkedEntity?: string;
499
- /** Entity ID (if available) */
500
- entityId?: string;
501
- }
502
341
  /**
503
342
  * Result of executing a single effect, with status tracking.
504
343
  */
@@ -517,33 +356,6 @@ interface EffectResult {
517
356
  * required field), so no handler recorded it — the host reports it. */
518
357
  refusedBeforeHandler?: boolean;
519
358
  }
520
- /**
521
- * Runtime configuration for strictness and safety modes.
522
- *
523
- * These options control how the runtime handles edge cases:
524
- * - `strictBindings`: Log warnings when bindings resolve to undefined (RCG-01)
525
- * - `maxEventDepth`: Prevent infinite event loops (RCG-05)
526
- */
527
- interface RuntimeConfig {
528
- /**
529
- * When true, log warnings when bindings like @entity.field resolve to undefined.
530
- * Helps detect typos and missing fields early. (RCG-01)
531
- * @default false
532
- */
533
- strictBindings?: boolean;
534
- /**
535
- * Maximum event emission depth before triggering circuit breaker. (RCG-05)
536
- * Prevents infinite loops from circular emit/listen chains.
537
- * @default 10
538
- */
539
- maxEventDepth?: number;
540
- /**
541
- * Additional fields to spread onto every EvaluationContext.
542
- * Used to inject module contexts (e.g., { agent: AgentContext }).
543
- * The evaluator dispatches agent/* operators to ctx.agent.
544
- */
545
- contextExtensions?: EvaluationContextExtensions;
546
- }
547
359
  /**
548
360
  * Typed extensions that get spread onto every EvaluationContext.
549
361
  * Each field here corresponds to an optional field on EvaluationContext.
@@ -558,17 +370,5 @@ interface EvaluationContextExtensions {
558
370
  memory?: MemoryContext;
559
371
  trace?: TraceContext;
560
372
  }
561
- /**
562
- * Execution context for handler manifest validation.
563
- * Defines which effect handlers should be available in each environment.
564
- */
565
- type ExecutionEnvironment = "client" | "server" | "test" | "ssr";
566
- /**
567
- * Effect handlers each execution environment is expected to carry. `client`
568
- * and `server` derive from the registry's `runsOn`; `ssr` is a render mode
569
- * (one server-side page render), not an execution site, so it stays listed.
570
- */
571
- declare const HANDLER_MANIFEST: Record<ExecutionEnvironment, string[]>;
572
373
 
573
- export { HANDLER_MANIFEST, isEffectTuple };
574
- export type { BindingContext, BrowserFileMeta, BrowserFilePickerOptions, BrowserGeolocationOptions, BrowserGeolocationPosition, ConfigContext, Effect, EffectContext, EffectHandlers, EffectResult, EvaluationContextExtensions, EventListener, ExecutionEnvironment, HttpEffectReport, IEventBus, PatternProps, PersistBatchSummary, RuntimeConfig, RuntimeEvent, RuntimePatternValue, RuntimeRenderPattern, TransitionResult, Unsubscribe };
374
+ export type { BindingContext, Effect, EffectHandlers, EffectResult, EvaluationContextExtensions, EventListener, IEventBus, PatternProps, RuntimeEvent, Unsubscribe };
@@ -1,2 +1 @@
1
- export { HANDLER_MANIFEST, isEffectTuple } from '../chunk-WNPNNYXY.js';
2
- import '../chunk-MLKGABMK.js';
1
+ import '../chunk-LYFIQPXX.js';
@@ -1,3 +1,2 @@
1
1
  export { defaultCallService } from '../chunk-4SEK5ER2.js';
2
2
  import '../chunk-UBN5JJKZ.js';
3
- import '../chunk-MLKGABMK.js';
@@ -1,2 +1 @@
1
1
  export { ServiceCallError, callRegisteredService, registerServiceProvider, registeredServices, unregisterServiceProvider } from '../chunk-UBN5JJKZ.js';
2
- import '../chunk-MLKGABMK.js';
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "@almadar/shell-runtime",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
+ "orbRelease": {
5
+ "severity": "normal"
6
+ },
4
7
  "description": "Renderer-neutral kernel adapters and client orchestration for Almadar TypeScript hosts.",
5
8
  "license": "BUSL-1.1",
6
9
  "type": "module",
@@ -21,10 +24,10 @@
21
24
  ],
22
25
  "sideEffects": false,
23
26
  "dependencies": {
24
- "@almadar/core": "^10.129.0",
25
- "@almadar/kernel": "^18.0.0",
26
- "@almadar/logger": "^1.18.0",
27
- "@almadar/std": "^16.255.0"
27
+ "@almadar/core": "^11.1.0",
28
+ "@almadar/kernel": "^19.0.1",
29
+ "@almadar/logger": "^2.1.0",
30
+ "@almadar/std": "^17.0.0"
28
31
  },
29
32
  "devDependencies": {
30
33
  "@types/node": "^20.0.0",
@@ -1,21 +0,0 @@
1
- import { findInbound, unknownHook, credentialUnset, inboundPayload, inboundAnswerOf, dispatchFailed } from '@almadar/core';
2
-
3
- // src/client/inbound-dispatch.ts
4
- async function dispatchInbound(schema, name, delivery, send, credential) {
5
- const route = schema ? findInbound(schema, name) : void 0;
6
- if (route === void 0) return unknownHook(name);
7
- try {
8
- const held = route.verifies !== void 0 ? await credential(route.verifies.credential) : void 0;
9
- if (route.verifies !== void 0 && (held === void 0 || held === null || held === "")) return credentialUnset(route.verifies.credential);
10
- const response = await send(route.orbital, {
11
- event: route.event,
12
- payload: inboundPayload(route, delivery, held),
13
- targetTrait: route.trait
14
- });
15
- return inboundAnswerOf(route, response.emittedEvents, response.error);
16
- } catch (error) {
17
- return dispatchFailed(error instanceof Error ? error.message : String(error));
18
- }
19
- }
20
-
21
- export { dispatchInbound };
@@ -1,28 +0,0 @@
1
- // src/runtime/time/duration.ts
2
- function parseDurationString(interval) {
3
- const match = interval.match(/^(\d+)(ms|s|m|h)?$/);
4
- if (!match) {
5
- throw new Error(
6
- `Invalid duration '${interval}': expected a shape like '5ms'/'5s'/'1m'/'1h'`
7
- );
8
- }
9
- const value = parseInt(match[1], 10);
10
- const unit = match[2] || "ms";
11
- switch (unit) {
12
- case "ms":
13
- return value;
14
- case "s":
15
- return value * 1e3;
16
- case "m":
17
- return value * 60 * 1e3;
18
- case "h":
19
- return value * 60 * 60 * 1e3;
20
- default:
21
- return value;
22
- }
23
- }
24
- function isValidDurationString(interval) {
25
- return /^(\d+)(ms|s|m|h)?$/.test(interval);
26
- }
27
-
28
- export { isValidDurationString, parseDurationString };
@@ -1,192 +0,0 @@
1
- import { isJsonObject } from '@almadar/core';
2
-
3
- // src/kernel/oauth-port.ts
4
- var PENDING_GRACE_MS = 60 * 60 * 1e3;
5
- var NO_CALLER = "a provider connection needs a signed-in caller";
6
- var NO_CONNECTIONS = "no OAuth connection store is installed on this host";
7
- var NO_TAKE = "this host keeps no derived secrets to take";
8
- var UNREADABLE = "a held OAuth credential is unreadable";
9
- var pendingName = (state) => `oauth:grant:${state}`;
10
- var connectionName = (provider) => `oauth:connection:${provider}`;
11
- function parseObject(text) {
12
- let value;
13
- try {
14
- value = JSON.parse(text);
15
- } catch {
16
- throw new Error(UNREADABLE);
17
- }
18
- if (!isJsonObject(value)) throw new Error(UNREADABLE);
19
- return value;
20
- }
21
- function textOf(object, name) {
22
- const value = object[name];
23
- if (typeof value !== "string") throw new Error(UNREADABLE);
24
- return value;
25
- }
26
- function textOrNull(object, name) {
27
- const value = object[name];
28
- if (value === void 0 || value === null) return null;
29
- if (typeof value !== "string") throw new Error(UNREADABLE);
30
- return value;
31
- }
32
- function textList(object, name) {
33
- const value = object[name];
34
- if (!Array.isArray(value)) throw new Error(UNREADABLE);
35
- return value.map((item) => {
36
- if (typeof item !== "string") throw new Error(UNREADABLE);
37
- return item;
38
- });
39
- }
40
- function objectOf(object, name) {
41
- const value = object[name];
42
- if (value === void 0 || !isJsonObject(value)) throw new Error(UNREADABLE);
43
- return value;
44
- }
45
- function grantOf(object) {
46
- return {
47
- provider: textOf(object, "provider"),
48
- redirectUri: textOf(object, "redirectUri"),
49
- verifier: textOf(object, "verifier"),
50
- subject: textOrNull(object, "subject"),
51
- scopes: textList(object, "scopes")
52
- };
53
- }
54
- function rowOf(object, provider) {
55
- const connected = object.connected;
56
- if (typeof connected !== "boolean") throw new Error(UNREADABLE);
57
- return {
58
- provider,
59
- connected,
60
- account: textOf(object, "account"),
61
- avatarUrl: textOf(object, "avatarUrl"),
62
- scope: textList(object, "scope"),
63
- connectedAt: textOf(object, "connectedAt")
64
- };
65
- }
66
- var disconnected = (provider) => ({ provider, connected: false, account: "", avatarUrl: "", scope: [], connectedAt: "" });
67
- function createOAuthPort(options) {
68
- const secrets = () => typeof options.secrets === "function" ? options.secrets() : options.secrets;
69
- const now = options.now ?? Date.now;
70
- const subjects = /* @__PURE__ */ new Map();
71
- const mockTokens = /* @__PURE__ */ new Map();
72
- const mockRefresh = /* @__PURE__ */ new Map();
73
- const metadata = /* @__PURE__ */ new Map();
74
- const caller = (principal) => {
75
- if (principal === void 0 || principal === "") throw new Error(NO_CALLER);
76
- return principal;
77
- };
78
- const durable = async (held) => held.persist !== void 0 && held.durable !== void 0 && held.durable();
79
- const take = async (held, name, principal) => {
80
- if (held.take === void 0) throw new Error(NO_TAKE);
81
- return held.take(name, principal);
82
- };
83
- return {
84
- async answer(ask, principal) {
85
- switch (ask.ask) {
86
- case "pendingPut": {
87
- const held = secrets();
88
- const record = JSON.stringify({ grant: ask.grant, expiresAt: now() + ask.ttlMs });
89
- if (held.hold !== void 0) await held.hold(pendingName(ask.state), record, ask.ttlMs + PENDING_GRACE_MS, void 0);
90
- else await held.set(pendingName(ask.state), record, ask.ttlMs + PENDING_GRACE_MS, void 0);
91
- return { reply: "done" };
92
- }
93
- case "pendingTake": {
94
- const held = secrets();
95
- const name = pendingName(ask.state);
96
- const text = await take(held, name, void 0);
97
- if (text === void 0) return { reply: "taken", taken: { found: "missing" } };
98
- const record = parseObject(text);
99
- const expiresAt = record.expiresAt;
100
- if (typeof expiresAt !== "number") throw new Error(UNREADABLE);
101
- if (expiresAt < now()) return { reply: "taken", taken: { found: "expired" } };
102
- return { reply: "taken", taken: { found: "grant", grant: grantOf(objectOf(record, "grant")) } };
103
- }
104
- case "connectionAvailable":
105
- return { reply: "flag", value: await durable(secrets()) };
106
- case "connectionSave": {
107
- const held = secrets();
108
- if (held.persist === void 0 || !await durable(held)) throw new Error(NO_CONNECTIONS);
109
- const who = caller(principal);
110
- const row = {
111
- provider: ask.provider,
112
- connected: true,
113
- account: ask.grant.subject ?? "",
114
- avatarUrl: "",
115
- scope: ask.grant.scope ?? [],
116
- connectedAt: new Date(now()).toISOString()
117
- };
118
- await held.persist(connectionName(ask.provider), JSON.stringify({ row, grant: ask.grant }), who);
119
- return { reply: "row", row };
120
- }
121
- case "connectionStatus": {
122
- const text = await secrets().get(connectionName(ask.provider), caller(principal));
123
- return { reply: "row", row: text === void 0 ? disconnected(ask.provider) : rowOf(objectOf(parseObject(text), "row"), ask.provider) };
124
- }
125
- case "connectionRemove":
126
- await secrets().forget(connectionName(ask.provider), caller(principal));
127
- return { reply: "row", row: disconnected(ask.provider) };
128
- case "subjectRemember":
129
- subjects.set(ask.accessToken, ask.subject);
130
- return { reply: "done" };
131
- case "subjectLookup":
132
- return { reply: "subject", subject: subjects.get(ask.accessToken) ?? null };
133
- case "subjectForget":
134
- subjects.delete(ask.accessToken);
135
- return { reply: "done" };
136
- case "metadataGet":
137
- return { reply: "metadata", metadata: metadata.get(ask.issuer) ?? null };
138
- case "metadataPut":
139
- metadata.set(ask.issuer, ask.metadata);
140
- return { reply: "done" };
141
- case "clock":
142
- return { reply: "millis", value: now() };
143
- case "consent":
144
- return { reply: "code", code: options.consent === void 0 ? null : await options.consent({ authUrl: ask.authUrl, state: ask.state, redirectUri: ask.redirectUri }) };
145
- case "mockTokenPut":
146
- mockTokens.set(ask.accessToken, { refresh: ask.refreshToken, expiresAt: ask.expiresAtMs, provider: ask.provider });
147
- mockRefresh.set(ask.refreshToken, { access: ask.accessToken, provider: ask.provider });
148
- return { reply: "done" };
149
- case "mockTokenRefresh": {
150
- const old = mockRefresh.get(ask.refreshToken);
151
- if (old === void 0) return { reply: "flag", value: false };
152
- mockTokens.delete(old.access);
153
- const sub = subjects.get(old.access);
154
- subjects.delete(old.access);
155
- if (sub !== void 0) subjects.set(ask.newAccessToken, sub);
156
- mockTokens.set(ask.newAccessToken, { refresh: ask.refreshToken, expiresAt: ask.expiresAtMs, provider: old.provider });
157
- mockRefresh.set(ask.refreshToken, { access: ask.newAccessToken, provider: old.provider });
158
- return { reply: "flag", value: true };
159
- }
160
- case "mockTokenRevoke": {
161
- const held = mockTokens.get(ask.token);
162
- if (held !== void 0) {
163
- mockTokens.delete(ask.token);
164
- mockRefresh.delete(held.refresh);
165
- subjects.delete(ask.token);
166
- return { reply: "flag", value: true };
167
- }
168
- const issued = mockRefresh.get(ask.token);
169
- if (issued !== void 0) {
170
- mockRefresh.delete(ask.token);
171
- mockTokens.delete(issued.access);
172
- subjects.delete(issued.access);
173
- return { reply: "flag", value: true };
174
- }
175
- return { reply: "flag", value: false };
176
- }
177
- case "mockTokenCheck": {
178
- const held = mockTokens.get(ask.accessToken);
179
- if (held === void 0) return { reply: "mockToken", state: "missing", provider: null };
180
- if (now() > held.expiresAt) {
181
- mockTokens.delete(ask.accessToken);
182
- subjects.delete(ask.accessToken);
183
- return { reply: "mockToken", state: "expired", provider: null };
184
- }
185
- return { reply: "mockToken", state: "valid", provider: held.provider };
186
- }
187
- }
188
- }
189
- };
190
- }
191
-
192
- export { PENDING_GRACE_MS, createOAuthPort };
@@ -1,76 +0,0 @@
1
- // src/kernel/lane.ts
2
- var LaneHeldByParkedDispatch = class extends Error {
3
- ticket;
4
- event;
5
- constructor(ticket, event) {
6
- super(
7
- `dispatch #${ticket} (${event}) is parked holding the dispatch lane on this thread; resume or drop it before starting another dispatch`
8
- );
9
- this.name = "LaneHeldByParkedDispatch";
10
- this.ticket = ticket;
11
- this.event = event;
12
- }
13
- };
14
- var DispatchLane = class {
15
- nextTicket = 0;
16
- holder;
17
- depth = 0;
18
- parkedEvent;
19
- waiters = [];
20
- assertCanReenter(turn) {
21
- if (this.holder === turn && this.parkedEvent !== void 0) throw new LaneHeldByParkedDispatch(turn.ticket, this.parkedEvent);
22
- }
23
- async enter(turn) {
24
- const holder = this.holder;
25
- if (holder !== void 0 && turn === holder) {
26
- if (this.parkedEvent !== void 0) {
27
- throw new LaneHeldByParkedDispatch(holder.ticket, this.parkedEvent);
28
- }
29
- this.depth += 1;
30
- return this.guard(holder, false);
31
- }
32
- const own = { ticket: this.nextTicket };
33
- this.nextTicket += 1;
34
- if (this.holder === void 0) {
35
- this.take(own);
36
- } else {
37
- await new Promise((grant) => {
38
- this.waiters.push({ turn: own, grant });
39
- });
40
- }
41
- return this.guard(own, true);
42
- }
43
- take(turn) {
44
- this.holder = turn;
45
- this.depth = 1;
46
- this.parkedEvent = void 0;
47
- }
48
- guard(turn, outer) {
49
- let done = false;
50
- return {
51
- turn,
52
- park: (event) => {
53
- if (!done && outer && this.holder === turn && this.depth === 1) this.parkedEvent = event;
54
- },
55
- resume: () => {
56
- if (!done && outer && this.holder === turn) this.parkedEvent = void 0;
57
- },
58
- release: () => {
59
- if (done) return;
60
- done = true;
61
- if (this.holder !== turn) return;
62
- this.depth -= 1;
63
- if (this.depth > 0) return;
64
- this.holder = void 0;
65
- this.parkedEvent = void 0;
66
- const next = this.waiters.shift();
67
- if (next !== void 0) {
68
- this.take(next.turn);
69
- next.grant();
70
- }
71
- }
72
- };
73
- }
74
- };
75
-
76
- export { DispatchLane, LaneHeldByParkedDispatch };
@@ -1,16 +0,0 @@
1
- import { pipeBehaviors } from './chunk-FQ6IZMIU.js';
2
- import { composeBehaviors } from './chunk-ZCQUUJIF.js';
3
- import { detectLayoutStrategy } from './chunk-EV56K4GB.js';
4
- import { applyEventWiring } from './chunk-MHYSHSRG.js';
5
- import { __export } from './chunk-MLKGABMK.js';
6
-
7
- // src/runtime/effects/composition/index.ts
8
- var composition_exports = {};
9
- __export(composition_exports, {
10
- applyEventWiring: () => applyEventWiring,
11
- composeBehaviors: () => composeBehaviors,
12
- detectLayoutStrategy: () => detectLayoutStrategy,
13
- pipeBehaviors: () => pipeBehaviors
14
- });
15
-
16
- export { composition_exports };