@almadar/runtime 6.32.0 → 6.34.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.
@@ -1,4 +1,4 @@
1
- import { a as EffectHandlers } from './types-D-9feVsj.js';
1
+ import { E as EffectHandlers } from './types-C8RsO0xa.js';
2
2
  import { EventPayload } from '@almadar/core';
3
3
 
4
4
  /**
@@ -50,6 +50,22 @@ var LoaderCache = class {
50
50
  return this.cache.size;
51
51
  }
52
52
  };
53
+ var BROWSE_FORM_HELP = "Accepted forms \u2014 loader: std/behaviors/<name> (e.g. std/behaviors/std-stats) | almadar-behaviors/<name> (e.g. almadar-behaviors/rpg-hero); browse: @std/<topic>/<kind>/<name>.lolo (e.g. @std/ui/core/atoms/std-stats.lolo) | @behaviors/<topic>/<kind>/<name>.lolo (e.g. @behaviors/app/molecules/app-crud-manager.lolo)";
54
+ var BROWSE_PREFIX_TO_PACKAGE = [
55
+ ["@std/", "std/behaviors/"],
56
+ ["@behaviors/", "almadar-behaviors/"]
57
+ ];
58
+ function mapBrowseSpecifier(importPath) {
59
+ for (const [prefix, pkg] of BROWSE_PREFIX_TO_PACKAGE) {
60
+ if (!importPath.startsWith(prefix)) continue;
61
+ const rest = importPath.slice(prefix.length);
62
+ const basename2 = rest.slice(rest.lastIndexOf("/") + 1);
63
+ const name = basename2.endsWith(".lolo") ? basename2.slice(0, -".lolo".length) : basename2;
64
+ if (name.length === 0) return { kind: "malformed" };
65
+ return { kind: "mapped", canonical: `${pkg}${name}` };
66
+ }
67
+ return { kind: "not-browse-form" };
68
+ }
53
69
  var ExternalOrbitalLoader = class {
54
70
  options;
55
71
  cache;
@@ -147,6 +163,16 @@ var ExternalOrbitalLoader = class {
147
163
  * Resolve an import path to an absolute filesystem path.
148
164
  */
149
165
  resolvePath(importPath, fromPath) {
166
+ const mapped = mapBrowseSpecifier(importPath);
167
+ if (mapped.kind === "malformed") {
168
+ return {
169
+ success: false,
170
+ error: `Unresolvable primitive import "${importPath}". ${BROWSE_FORM_HELP}`
171
+ };
172
+ }
173
+ if (mapped.kind === "mapped") {
174
+ importPath = mapped.canonical;
175
+ }
150
176
  if (importPath.startsWith("std/")) {
151
177
  return this.resolveStdPath(importPath);
152
178
  }
@@ -438,4 +464,4 @@ function autoDetectBehaviorsLibPaths(stdLibPath) {
438
464
  return found;
439
465
  }
440
466
 
441
- export { ExternalOrbitalLoader, ImportChain, LoaderCache, createLoader, parseImportPath };
467
+ export { ExternalOrbitalLoader, ImportChain, LoaderCache, createLoader, mapBrowseSpecifier, parseImportPath };
package/dist/index.d.ts CHANGED
@@ -1,14 +1,16 @@
1
- import { B as BindingContext, E as EvaluationContextExtensions, P as PatternProps, a as EffectHandlers, b as EffectContext, c as ExecutionEnvironment, d as EffectResult, T as TraitDefinition } from './types-D-9feVsj.js';
2
- export { e as Effect, f as EventListener, H as HANDLER_MANIFEST, I as IEventBus, R as RuntimeConfig, g as RuntimeEvent, h as TraitState, i as TransitionObserver, j as TransitionResult, U as Unsubscribe } from './types-D-9feVsj.js';
3
- import { U as UnifiedLoaderOptions, S as SchemaLoader, I as ImportChainLike, L as LoadResult, a as LoadedSchema, b as LoadedOrbital, P as PersistenceAdapter } from './OrbitalServerRuntime-DpAwIrmv.js';
4
- export { E as EntitySharingMap, c as EventBus, d as EventNamespaceMap, e as InMemoryPersistence, O as OrbitalEventRequest, f as OrbitalEventResponse, g as OrbitalServerRuntimeConfig, h as PreprocessOptions, i as PreprocessResult, j as PreprocessedSchema, k as ProcessEventOptions, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, o as StateMachineManager, p as collectDeclaredConfigDefaults, q as collectDeclaredEntityDefaults, r as createInitialTraitState, s as findInitialState, t as findTransition, u as getIsolatedCollectionName, v as getNamespacedEvent, w as isBrowser, x as isElectron, y as isNamespacedEvent, z as isNode, A as normalizeCallSiteConfigToValues, B as normalizeEventKey, C as parseNamespacedEvent, D as preprocessSchema, F as processEvent } from './OrbitalServerRuntime-DpAwIrmv.js';
1
+ import { B as BindingContext, f as EvaluationContextExtensions, P as PatternProps, E as EffectHandlers, g as EffectContext, h as ExecutionEnvironment, i as EffectResult, T as TraitDefinition } from './types-C8RsO0xa.js';
2
+ export { j as BrowserFileMeta, k as BrowserFilePickerOptions, l as BrowserGeolocationOptions, m as BrowserGeolocationPosition, C as ConfigContext, n as Effect, a as EventListener, H as HANDLER_MANIFEST, I as IEventBus, b as RuntimeConfig, R as RuntimeEvent, d as TraitState, c as TransitionObserver, e as TransitionResult, U as Unsubscribe } from './types-C8RsO0xa.js';
3
+ import { U as UnifiedLoaderOptions, S as SchemaLoader, I as ImportChainLike, L as LoadResult, a as LoadedSchema, b as LoadedOrbital, P as PersistenceAdapter } from './OrbitalServerRuntime-BrHSXDfp.js';
4
+ export { E as EntitySharingMap, c as EventBus, d as EventNamespaceMap, e as InMemoryPersistence, O as OrbitalEventRequest, f as OrbitalEventResponse, g as OrbitalServerRuntimeConfig, h as PreprocessOptions, i as PreprocessResult, j as PreprocessedSchema, k as ProcessEventOptions, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, o as StateMachineManager, p as collectDeclaredConfigDefaults, q as collectDeclaredEntityDefaults, r as createInitialTraitState, s as findInitialState, t as findTransition, u as getIsolatedCollectionName, v as getNamespacedEvent, w as isBrowser, x as isElectron, y as isNamespacedEvent, z as isNode, A as normalizeEventKey, B as parseNamespacedEvent, C as preprocessSchema, D as processEvent } from './OrbitalServerRuntime-BrHSXDfp.js';
5
5
  import { EvaluationContext, SExpressionEvaluator } from '@almadar/evaluator';
6
6
  export { EvaluationContext, createMinimalContext } from '@almadar/evaluator';
7
- import { EventPayload, EntityField, EntityRow, ServiceParams, PayloadField, OrbitalDefinition, OrbitalSchema } from '@almadar/core';
8
- export { EntityField } from '@almadar/core';
7
+ import { TraitConfigObject, EventPayload, PatternConfig, EntityId, EntityField, EntityRow, ServiceParams, PayloadField, OrbitalDefinition, OrbitalSchema } from '@almadar/core';
8
+ export { EntityField, normalizeCallSiteConfigToValues } from '@almadar/core';
9
9
  export { ServerBridgeConfig, ServerBridgeState } from './ServerBridge.js';
10
10
  export { OsHandlerContext, OsHandlerResult } from './createOsHandlers.js';
11
+ export { MultiSourceSlotManager, PERF_NAMESPACE, PerfDetail, PerfDetailValue, PerfEntry, PreparedPreviewSchema, RendererContractViolationError, ResolvedPageTraits, SlotContent, SlotContentValidationError, SlotManager, SlotSource, VerificationBus, adjustSchemaForMockData, aggregateSlotContent, assertIsMultiSourceSlotManager, assertIsSlotManager, bindEventBus, bindTraitStateGetter, buildMockData, buildOrbitalsByTrait, clearPerf, collectEmbeddedTraits, collectTraitRefsFromResolvedTrait, createSlotSetter, ensureVerificationApi, getOrbitalVerification, perfEnd, perfStart, perfStore, perfTime, prepareSchemaForPreview, pushPerfEntry, validateSlotContent, wrapCallbackForEvent } from './ui/index.js';
11
12
  import 'express';
13
+ import '@almadar/core/patterns';
12
14
 
13
15
  /**
14
16
  * Unified Schema Loader
@@ -242,6 +244,23 @@ declare function isValidDurationString(interval: string): boolean;
242
244
  * @packageDocumentation
243
245
  */
244
246
 
247
+ /**
248
+ * Call-site payload capture grammar. Mirrors the Rust orbital-core
249
+ * `CALLSITE_PAYLOAD_PREFIX` (`@callsitePayload.`). A composed trait's call-site
250
+ * config value of this form is a snapshot of the COMPOSING effect's triggering
251
+ * event payload, captured at the call site — deliberately distinct from
252
+ * `@payload.` so it is never evaluated in the child's own INIT scope.
253
+ */
254
+ declare const CALLSITE_PAYLOAD_PREFIX = "@callsitePayload.";
255
+ /**
256
+ * Resolve call-site payload captures in a child trait's call-site config
257
+ * against the COMPOSING effect's triggering event payload. Each value of the
258
+ * form `@callsitePayload.<field>` becomes the literal read from `payload`
259
+ * (snapshot semantics — the child sees a plain value, never a payload ref).
260
+ * Non-capture entries pass through untouched. Returns a new object; the input
261
+ * is not mutated.
262
+ */
263
+ declare function resolveCallSitePayloadCaptures(config: TraitConfigObject, payload: EventPayload | undefined): TraitConfigObject;
245
264
  /**
246
265
  * Interpolate binding references in props.
247
266
  *
@@ -448,7 +467,7 @@ interface ClientEventBus {
448
467
  */
449
468
  interface SlotSetter {
450
469
  /** Accumulate a pattern into the pending slot map */
451
- addPattern: (slot: string, pattern: unknown, props?: PatternProps) => void;
470
+ addPattern: (slot: string, pattern: PatternConfig, props?: PatternProps) => void;
452
471
  /** Mark a slot for clearing */
453
472
  clearSlot: (slot: string) => void;
454
473
  }
@@ -504,10 +523,10 @@ interface CreateClientEffectHandlersOptions {
504
523
  declare function createClientEffectHandlers(options: CreateClientEffectHandlersOptions): EffectHandlers;
505
524
 
506
525
  /**
507
- * MockPersistenceAdapter - In-memory data store with faker-based mock generation
526
+ * MockPersistenceAdapter - In-memory data store with seeded mock generation
508
527
  *
509
528
  * Provides a stateful mock data layer that implements PersistenceAdapter.
510
- * Uses @faker-js/faker for realistic data generation based on field types.
529
+ * Uses a lightweight seeded PRNG so the client bundle does not pull in faker.
511
530
  *
512
531
  * @packageDocumentation
513
532
  */
@@ -521,8 +540,10 @@ type NamedEntityField = EntityField & {
521
540
  };
522
541
  interface EntitySchema {
523
542
  name: string;
543
+ /** V4 dual-carry id sibling of `name` — optional until the Phase-7 flip. */
544
+ id?: EntityId;
524
545
  fields: NamedEntityField[];
525
- /** Pre-authored instance data from the schema (used instead of faker generation) */
546
+ /** Pre-authored instance data from the schema (used instead of generated mocks) */
526
547
  seedData?: EntityRow[];
527
548
  }
528
549
  interface MockPersistenceConfig {
@@ -534,17 +555,19 @@ interface MockPersistenceConfig {
534
555
  debug?: boolean;
535
556
  }
536
557
  /**
537
- * In-memory mock data store with CRUD operations and faker-based seeding.
558
+ * In-memory mock data store with CRUD operations and seeded mock generation.
538
559
  */
539
560
  declare class MockPersistenceAdapter implements PersistenceAdapter {
540
561
  private stores;
541
562
  private schemas;
542
563
  private idCounters;
564
+ /** entityId -> normalized store name, so relation lookups can prefer the id sibling over `relation.entity` name-matching. */
565
+ private storeNameById;
543
566
  private config;
544
567
  constructor(config?: MockPersistenceConfig);
545
- /** Re-anchor faker's PRNG to the configured seed. Called before every
568
+ /** Re-anchor the PRNG to the configured seed. Called before every
546
569
  * re-seed loop so identical reseed sequences produce identical rows
547
- * (timestamps + faker-generated fields). Without this, the first
570
+ * (timestamps + generated fields). Without this, the first
548
571
  * reseed produces row set A, the second produces row set B, and
549
572
  * diff observers see all rows as "changed" between frames. */
550
573
  resetFakerSeed(): void;
@@ -553,7 +576,7 @@ declare class MockPersistenceAdapter implements PersistenceAdapter {
553
576
  /**
554
577
  * Register an entity schema and seed mock data.
555
578
  * If the schema has seedData, those instances are used directly.
556
- * Otherwise, random mock data is generated with faker.
579
+ * Otherwise, random mock data is generated with the seeded PRNG.
557
580
  */
558
581
  registerEntity(schema: EntitySchema, seedCount?: number): void;
559
582
  /**
@@ -605,7 +628,7 @@ declare class MockPersistenceAdapter implements PersistenceAdapter {
605
628
  private generateArrayValue;
606
629
  /**
607
630
  * Generate a single object value with each declared property populated
608
- * by faker. Walks `properties` and recursively delegates to
631
+ * by the seeded PRNG. Walks `properties` and recursively delegates to
609
632
  * `generateFieldValue` per property so nested objects-of-arrays-of-objects
610
633
  * compose correctly.
611
634
  */
@@ -613,7 +636,7 @@ declare class MockPersistenceAdapter implements PersistenceAdapter {
613
636
  /**
614
637
  * Generate a string value based on the field's declared schema metadata.
615
638
  * Reads `values` (enum) first, then `format` (email/url/phone/uuid/date/
616
- * datetime), then falls back to faker.lorem.words. No field-name heuristics
639
+ * datetime), then falls back to randomWords. No field-name heuristics
617
640
  * — the schema is the source of truth. If a caller needs a real email, they
618
641
  * declare `format: "email"`; if they need an enum, they declare `values: [...]`.
619
642
  */
@@ -644,7 +667,7 @@ declare class MockPersistenceAdapter implements PersistenceAdapter {
644
667
  * Clear all data for an entity.
645
668
  */
646
669
  clear(entityName: string): void;
647
- /** Clear all data + re-anchor faker so the next seed loop reproduces
670
+ /** Clear all data + re-anchor the PRNG so the next seed loop reproduces
648
671
  * identical rows. Hermetic-frame mode calls this between every step
649
672
  * via OrbitalServerRuntime.resetMockPersistence. */
650
673
  clearAll(): void;
@@ -942,8 +965,8 @@ declare function detectLayoutStrategy(orbitals: OrbitalDefinition[], eventWiring
942
965
  interface ComposeBehaviorsInput {
943
966
  /** Application name */
944
967
  appName: string;
945
- /** Orbital definitions to compose */
946
- orbitals: OrbitalDefinition[];
968
+ /** Orbital definitions (or schemas) to compose */
969
+ orbitals: (OrbitalDefinition | OrbitalSchema)[];
947
970
  /** Layout strategy override, or 'auto' to detect */
948
971
  layoutStrategy?: LayoutStrategy | 'auto';
949
972
  /** Cross-orbital event wiring */
@@ -1031,4 +1054,4 @@ declare namespace index {
1031
1054
  export { type index_ComposeBehaviorsInput as ComposeBehaviorsInput, type index_ComposeBehaviorsResult as ComposeBehaviorsResult, type index_EventWiringEntry as EventWiringEntry, type index_LayoutStrategy as LayoutStrategy, type index_PipeStep as PipeStep, index_applyEventWiring as applyEventWiring, index_composeBehaviors as composeBehaviors, index_detectLayoutStrategy as detectLayoutStrategy, index_pipeBehaviors as pipeBehaviors };
1032
1055
  }
1033
1056
 
1034
- export { BindingContext, type ClientEventBus, type ComposeBehaviorsInput, type ComposeBehaviorsResult, type CreateClientEffectHandlersOptions, type CreateServerEffectHandlersOptions, type CronFields, EffectContext, EffectExecutor, type EffectExecutorOptions, EffectHandlers, EffectResult, type EntitySchema, type EventWiringEntry, ExecutionEnvironment, ImportChainLike, type LayoutStrategy, LoadResult, LoadedOrbital, LoadedSchema, MockPersistenceAdapter, type MockPersistenceConfig, type PayloadMismatch, type PayloadValidationFailure, PersistenceAdapter, type PipeStep, SchemaLoader, type ServerEffectResult, type SlotSetter, type TickHandle, TickScheduler, TraitDefinition, UnifiedLoaderOptions, applyEventWiring, buildEmitsFromTraits, composeBehaviors, index as composition, containsBindings, createClientEffectHandlers, createContextFromBindings, createMockPersistence, createServerEffectHandlers, createTestExecutor, createTickScheduler, createUnifiedLoader, cronMatches, cronMinuteKey, detectLayoutStrategy, extractBindings, formatPayloadValidationError, interpolateProps, interpolateValue, isValidCronExpression, isValidDurationString, parseCron, parseCronField, parseDurationString, pipeBehaviors, validateEventPayload, validatePayloadShapes };
1057
+ export { BindingContext, CALLSITE_PAYLOAD_PREFIX, type ClientEventBus, type ComposeBehaviorsInput, type ComposeBehaviorsResult, type CreateClientEffectHandlersOptions, type CreateServerEffectHandlersOptions, type CronFields, EffectContext, EffectExecutor, type EffectExecutorOptions, EffectHandlers, EffectResult, type EntitySchema, type EventWiringEntry, ExecutionEnvironment, ImportChainLike, type LayoutStrategy, LoadResult, LoadedOrbital, LoadedSchema, MockPersistenceAdapter, type MockPersistenceConfig, type PayloadMismatch, type PayloadValidationFailure, PersistenceAdapter, type PipeStep, SchemaLoader, type ServerEffectResult, type SlotSetter, type TickHandle, TickScheduler, TraitDefinition, UnifiedLoaderOptions, applyEventWiring, buildEmitsFromTraits, composeBehaviors, index as composition, containsBindings, createClientEffectHandlers, createContextFromBindings, createMockPersistence, createServerEffectHandlers, createTestExecutor, createTickScheduler, createUnifiedLoader, cronMatches, cronMinuteKey, detectLayoutStrategy, extractBindings, formatPayloadValidationError, interpolateProps, interpolateValue, isValidCronExpression, isValidDurationString, parseCron, parseCronField, parseDurationString, pipeBehaviors, resolveCallSitePayloadCaptures, validateEventPayload, validatePayloadShapes };
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
- import { EffectExecutor, createContextFromBindings } from './chunk-YFH577FH.js';
2
- export { EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, containsBindings, createContextFromBindings, createInitialTraitState, createMinimalContext, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, extractBindings, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, interpolateProps, interpolateValue, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeCallSiteConfigToValues, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, validateEventPayload, validatePayloadShapes } from './chunk-YFH577FH.js';
1
+ import { EffectExecutor, createContextFromBindings } from './chunk-TRA44DDY.js';
2
+ export { CALLSITE_PAYLOAD_PREFIX, EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, containsBindings, createContextFromBindings, createInitialTraitState, createMinimalContext, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, extractBindings, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, interpolateProps, interpolateValue, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeCallSiteConfigToValues, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, resolveCallSitePayloadCaptures, validateEventPayload, validatePayloadShapes } from './chunk-TRA44DDY.js';
3
3
  export { cronMatches, cronMinuteKey, isValidCronExpression, parseCron, parseCronField } from './chunk-OU3ITB5S.js';
4
+ import './chunk-OQJIK6PZ.js';
5
+ export { PERF_NAMESPACE, RendererContractViolationError, adjustSchemaForMockData, aggregateSlotContent, assertIsMultiSourceSlotManager, assertIsSlotManager, bindEventBus, bindTraitStateGetter, buildMockData, buildOrbitalsByTrait, clearPerf, createSlotSetter, ensureVerificationApi, getOrbitalVerification, perfEnd, perfStart, perfStore, perfTime, prepareSchemaForPreview, pushPerfEntry, validateSlotContent, wrapCallbackForEvent } from './chunk-O5VGKPTG.js';
6
+ export { collectEmbeddedTraits, collectTraitRefsFromResolvedTrait } from './chunk-SCRAHWOC.js';
4
7
  import { __export } from './chunk-MLKGABMK.js';
5
8
  import { createLogger } from '@almadar/logger';
6
9
  import { evaluate } from '@almadar/evaluator';
@@ -87,7 +90,54 @@ function createClientEffectHandlers(options) {
87
90
  }),
88
91
  sendServer: sendServer ?? ((event, payload) => {
89
92
  sendServerEvent(orbitalName, event, payload);
90
- })
93
+ }),
94
+ // === Browser device handlers (client host path) ===
95
+ // Each throws when the underlying API is unavailable so the executor's
96
+ // runSubstrate wrapper fires `emit.failure` with `{ error }`.
97
+ browserOpenFilePicker: async (options2) => {
98
+ if (typeof window === "undefined" || !("showOpenFilePicker" in window)) {
99
+ throw new Error("File picker API is not available in this environment");
100
+ }
101
+ const host = window;
102
+ const pickerOptions = {};
103
+ if (options2?.multiple === true) pickerOptions.multiple = true;
104
+ if (typeof options2?.accept === "string" && options2.accept.length > 0) {
105
+ pickerOptions.types = [{ accept: { [options2.accept]: [] } }];
106
+ }
107
+ const handles = await host.showOpenFilePicker(pickerOptions);
108
+ const files = await Promise.all(handles.map(async (handle) => {
109
+ const file = await handle.getFile();
110
+ return { name: file.name, size: file.size, type: file.type, lastModified: file.lastModified };
111
+ }));
112
+ return { files };
113
+ },
114
+ browserClipboardRead: async () => {
115
+ if (typeof navigator === "undefined" || !navigator.clipboard) {
116
+ throw new Error("Clipboard API is not available in this environment");
117
+ }
118
+ const text = await navigator.clipboard.readText();
119
+ return { text };
120
+ },
121
+ browserClipboardWrite: async (text) => {
122
+ if (typeof navigator === "undefined" || !navigator.clipboard) {
123
+ throw new Error("Clipboard API is not available in this environment");
124
+ }
125
+ await navigator.clipboard.writeText(text);
126
+ return { text };
127
+ },
128
+ browserGeolocationCurrent: async (options2) => {
129
+ if (typeof navigator === "undefined" || !navigator.geolocation) {
130
+ throw new Error("Geolocation API is not available in this environment");
131
+ }
132
+ const position = await new Promise((resolve, reject) => {
133
+ navigator.geolocation.getCurrentPosition(resolve, reject, options2);
134
+ });
135
+ return {
136
+ latitude: position.coords.latitude,
137
+ longitude: position.coords.longitude,
138
+ accuracy: position.coords.accuracy
139
+ };
140
+ }
91
141
  };
92
142
  }
93
143
  var effectLog = createLogger("almadar:runtime:effects");
@@ -669,6 +719,41 @@ function detectLayoutStrategy(orbitals, eventWiring) {
669
719
  }
670
720
 
671
721
  // src/composition/compose-behaviors.ts
722
+ function isSchema(input) {
723
+ return "orbitals" in input && Array.isArray(input.orbitals);
724
+ }
725
+ function asDefinitions(inputs) {
726
+ return inputs.flatMap(
727
+ (input) => isSchema(input) ? input.orbitals : [input]
728
+ );
729
+ }
730
+ function mergeLedgers(inputs) {
731
+ const merged = /* @__PURE__ */ new Map();
732
+ let sawLedger = false;
733
+ for (const input of inputs) {
734
+ if (!isSchema(input) || input.ledger === void 0) continue;
735
+ sawLedger = true;
736
+ for (const [id, entry] of Object.entries(input.ledger.entries)) {
737
+ if (!merged.has(id)) merged.set(id, entry);
738
+ }
739
+ }
740
+ if (!sawLedger) return void 0;
741
+ const entries = {};
742
+ for (const [id, entry] of [...merged.entries()].sort(
743
+ ([a], [b]) => a < b ? -1 : a > b ? 1 : 0
744
+ )) {
745
+ entries[id] = entry;
746
+ }
747
+ return { schemaVersion: 1, entries };
748
+ }
749
+ function mergeSchemaVersions(inputs) {
750
+ let max;
751
+ for (const input of inputs) {
752
+ if (!isSchema(input) || input.schemaVersion === void 0) continue;
753
+ max = max === void 0 ? input.schemaVersion : Math.max(max, input.schemaVersion);
754
+ }
755
+ return max;
756
+ }
672
757
  function toKebabCase(name) {
673
758
  return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
674
759
  }
@@ -719,10 +804,11 @@ function getEntityName(orbital) {
719
804
  function composeBehaviors(input) {
720
805
  const {
721
806
  appName,
722
- orbitals: rawOrbitals,
807
+ orbitals: rawInputs,
723
808
  layoutStrategy: strategyInput,
724
809
  eventWiring
725
810
  } = input;
811
+ const rawOrbitals = asDefinitions(rawInputs);
726
812
  const wiredOrbitals = eventWiring && eventWiring.length > 0 ? applyEventWiring(rawOrbitals, eventWiring) : rawOrbitals;
727
813
  const strategy = !strategyInput || strategyInput === "auto" ? detectLayoutStrategy(wiredOrbitals, eventWiring) : strategyInput;
728
814
  const pages = generatePages(wiredOrbitals, strategy);
@@ -736,10 +822,14 @@ function composeBehaviors(input) {
736
822
  pages: page ? [page] : []
737
823
  };
738
824
  });
825
+ const ledger = mergeLedgers(rawInputs);
826
+ const schemaVersion = mergeSchemaVersions(rawInputs);
739
827
  const schema = {
740
828
  name: appName,
741
829
  version: "1.0.0",
742
- orbitals: orbitalsWithPages
830
+ orbitals: orbitalsWithPages,
831
+ ...schemaVersion !== void 0 ? { schemaVersion } : {},
832
+ ...ledger !== void 0 ? { ledger } : {}
743
833
  };
744
834
  return {
745
835
  schema,
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Lightweight seeded pseudo-random generator for mock data.
3
+ *
4
+ * Replaces @faker-js/faker in browser-facing code so the client bundle does
5
+ * not pay the ~3.7 MB faker cost. The API surface is intentionally narrow:
6
+ * only the helpers actually used by MockPersistenceAdapter.
7
+ */
8
+ /** Re-seed the generator. Same signature as `faker.seed()`. */
9
+ declare function seedRandom(value: number | undefined): void;
10
+ /** Integer in [min, max]. */
11
+ declare function randomInt({ min, max }: {
12
+ min: number;
13
+ max: number;
14
+ }): number;
15
+ /** Float in [min, max] with fixed fraction digits. */
16
+ declare function randomFloat({ min, max, fractionDigits, }: {
17
+ min: number;
18
+ max: number;
19
+ fractionDigits?: number;
20
+ }): number;
21
+ /** True/false with 50% probability. */
22
+ declare function randomBoolean(): boolean;
23
+ /** Pick one element from an array. */
24
+ declare function randomArrayElement<T>(array: ReadonlyArray<T>): T;
25
+ /** Return a shallow-shuffled copy of the array (Fisher-Yates). */
26
+ declare function shuffleArray<T>(array: ReadonlyArray<T>): T[];
27
+ /** ISO-8601 date string roughly `years` in the past. */
28
+ declare function randomPastDate({ years }?: {
29
+ years?: number;
30
+ }): Date;
31
+ /** ISO-8601 date string within the last `days`. */
32
+ declare function randomRecentDate({ days }?: {
33
+ days?: number;
34
+ }): Date;
35
+ /** Any date in the last ~100 years. */
36
+ declare function randomAnytimeDate(): Date;
37
+ /** A few random words. */
38
+ declare function randomWords(count: number): string;
39
+ /** A short sentence. */
40
+ declare function randomSentence(): string;
41
+ /** UUID v4-like string (random, not strictly compliant). */
42
+ declare function randomUuid(): string;
43
+ /** Random hex color (#rrggbb). */
44
+ declare function randomColor(): string;
45
+ /** Random password of the given length. */
46
+ declare function randomPassword(length?: number): string;
47
+ /** Random email address. */
48
+ declare function randomEmail(): string;
49
+ /** Random URL. */
50
+ declare function randomUrl(): string;
51
+ /** Random phone number. */
52
+ declare function randomPhone(): string;
53
+
54
+ export { randomAnytimeDate, randomArrayElement, randomBoolean, randomColor, randomEmail, randomFloat, randomInt, randomPassword, randomPastDate, randomPhone, randomRecentDate, randomSentence, randomUrl, randomUuid, randomWords, seedRandom, shuffleArray };
@@ -0,0 +1,2 @@
1
+ export { randomAnytimeDate, randomArrayElement, randomBoolean, randomColor, randomEmail, randomFloat, randomInt, randomPassword, randomPastDate, randomPhone, randomRecentDate, randomSentence, randomUrl, randomUuid, randomWords, seedRandom, shuffleArray } from './chunk-OQJIK6PZ.js';
2
+ import './chunk-MLKGABMK.js';
@@ -1,5 +1,5 @@
1
1
  import * as _almadar_core from '@almadar/core';
2
- import { SExpr, EventPayload, AgentContext, LlmContext, WorkspaceContext, SessionContext, MemoryContext, TraceContext, IntegrationContext, TraitConfig, BusEvent, EntityRow, FieldValue, ServiceParams, FetchResult, PatternConfig, ResolvedPatternProps, Orbital, ServiceCallResult, BusEventSource, BusEventListener, Unsubscribe as Unsubscribe$1 } from '@almadar/core';
2
+ import { TraitId, EventId, SExpr, EventPayload, AgentContext, LlmContext, WorkspaceContext, SessionContext, MemoryContext, TraceContext, IntegrationContext, TraitConfig, BusEvent, EntityRow, FieldValue, ServiceParams, FetchResult, PatternConfig, ResolvedPatternProps, Orbital, ServiceCallResult, BusEventSource, BusEventListener, Unsubscribe as Unsubscribe$1 } from '@almadar/core';
3
3
 
4
4
  /** Alias for ResolvedPatternProps to avoid breaking internal consumers */
5
5
  type PatternProps = ResolvedPatternProps;
@@ -17,8 +17,9 @@ type Unsubscribe = Unsubscribe$1;
17
17
  * Event bus interface for pub/sub communication
18
18
  */
19
19
  interface IEventBus {
20
- /** Emit an event */
21
- emit(type: string, payload?: EventPayload, source?: BusEventSource): void;
20
+ /** Emit an event. `routingKey` (V4) keys delivery by event-id when the
21
+ * schema carries ids; absent → keyed by `type` (name, legacy). */
22
+ emit(type: string, payload?: EventPayload, source?: BusEventSource, routingKey?: string): void;
22
23
  /** Subscribe to an event */
23
24
  on(type: string, listener: EventListener): Unsubscribe;
24
25
  /** Subscribe to ALL events (wildcard listener) */
@@ -70,6 +71,9 @@ interface TransitionResult {
70
71
  * Minimal trait definition for state machine processing
71
72
  */
72
73
  interface TraitDefinition {
74
+ /** V4 dual-carry id sibling of `name` — the stable state-machine lookup
75
+ * key when present (ledger-backed). Absent → keyed by name (legacy). */
76
+ id?: TraitId;
73
77
  name: string;
74
78
  states: Array<{
75
79
  name: string;
@@ -79,6 +83,8 @@ interface TraitDefinition {
79
83
  from: string | string[];
80
84
  to: string;
81
85
  event: string;
86
+ /** V4 dual-carry id sibling of `event` — optional until the Phase-7 flip. */
87
+ eventId?: EventId;
82
88
  guard?: unknown;
83
89
  effects?: SExpr[];
84
90
  /** Compensating transition when effects fail (RCG-04) */
@@ -90,7 +96,11 @@ interface TraitDefinition {
90
96
  /** Cross-trait event listeners (optional) */
91
97
  listens?: Array<{
92
98
  event: string;
99
+ /** V4 dual-carry id sibling of `event` — optional until the Phase-7 flip. */
100
+ eventId?: EventId;
93
101
  triggers: string;
102
+ /** V4 dual-carry id sibling of `triggers` — optional until the Phase-7 flip. */
103
+ triggersId?: EventId;
94
104
  payloadMapping?: EventPayload;
95
105
  }>;
96
106
  }
@@ -221,6 +231,20 @@ interface EffectHandlers {
221
231
  osWatchEnv?: (variable: string, emit?: OsEmitConfig) => void;
222
232
  /** Configure debounce for an OS event type */
223
233
  osDebounce?: (ms: number, eventType: string) => void;
234
+ /** browser/open-file-picker — resolves with `{ files }` inside `result` */
235
+ browserOpenFilePicker?: (options?: BrowserFilePickerOptions) => Promise<{
236
+ files: BrowserFileMeta[];
237
+ }>;
238
+ /** browser/clipboard-read — resolves with `{ text }` inside `result` */
239
+ browserClipboardRead?: () => Promise<{
240
+ text: string;
241
+ }>;
242
+ /** browser/clipboard-write — resolves with `{ text }` (echo) inside `result` */
243
+ browserClipboardWrite?: (text: string) => Promise<{
244
+ text: string;
245
+ }>;
246
+ /** browser/geolocation-current — resolves with the position inside `result` */
247
+ browserGeolocationCurrent?: (options?: BrowserGeolocationOptions) => Promise<BrowserGeolocationPosition>;
224
248
  /** compose/compose-all — compose multiple orbitals into one schema */
225
249
  substrateComposeAll?: (config: {
226
250
  appName: string;
@@ -244,6 +268,32 @@ interface EffectHandlers {
244
268
  * operators meaningfully fire.
245
269
  */
246
270
  type OsEmitConfig = Pick<_almadar_core.EmitConfig, 'on_message' | 'failure'>;
271
+ /** Options for `browser/open-file-picker`. */
272
+ interface BrowserFilePickerOptions {
273
+ /** Allow selecting multiple files. */
274
+ multiple?: boolean;
275
+ /** MIME type filter (e.g. "image/*"). Best-effort; host may ignore. */
276
+ accept?: string;
277
+ }
278
+ /** Metadata for a file chosen via `browser/open-file-picker`. */
279
+ interface BrowserFileMeta {
280
+ name: string;
281
+ size: number;
282
+ type: string;
283
+ lastModified: number;
284
+ }
285
+ /** Options for `browser/geolocation-current` (subset of PositionOptions). */
286
+ interface BrowserGeolocationOptions {
287
+ enableHighAccuracy?: boolean;
288
+ timeout?: number;
289
+ maximumAge?: number;
290
+ }
291
+ /** Position returned by `browser/geolocation-current`. */
292
+ interface BrowserGeolocationPosition {
293
+ latitude: number;
294
+ longitude: number;
295
+ accuracy: number;
296
+ }
247
297
  /**
248
298
  * Context for resolving bindings like @entity.field, @payload.value
249
299
  */
@@ -393,4 +443,4 @@ interface TransitionObserver {
393
443
  */
394
444
  declare const HANDLER_MANIFEST: Record<ExecutionEnvironment, string[]>;
395
445
 
396
- export { type BindingContext as B, type ConfigContext as C, type EvaluationContextExtensions as E, HANDLER_MANIFEST as H, type IEventBus as I, type PatternProps as P, type RuntimeConfig as R, type TraitDefinition as T, type Unsubscribe as U, type EffectHandlers as a, type EffectContext as b, type ExecutionEnvironment as c, type EffectResult as d, type Effect as e, type EventListener as f, type RuntimeEvent as g, type TraitState as h, type TransitionObserver as i, type TransitionResult as j };
446
+ export { type BindingContext as B, type ConfigContext as C, type EffectHandlers as E, HANDLER_MANIFEST as H, type IEventBus as I, type PatternProps as P, type RuntimeEvent as R, type TraitDefinition as T, type Unsubscribe as U, type EventListener as a, type RuntimeConfig as b, type TransitionObserver as c, type TraitState as d, type TransitionResult as e, type EvaluationContextExtensions as f, type EffectContext as g, type ExecutionEnvironment as h, type EffectResult as i, type BrowserFileMeta as j, type BrowserFilePickerOptions as k, type BrowserGeolocationOptions as l, type BrowserGeolocationPosition as m, type Effect as n };