@almadar/shell-runtime 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.
Files changed (127) hide show
  1. package/dist/chunk-4SEK5ER2.js +8 -0
  2. package/dist/chunk-57SBCUSM.js +62 -0
  3. package/dist/chunk-625EP7W2.js +108 -0
  4. package/dist/chunk-64IH2SMY.js +22 -0
  5. package/dist/chunk-7SDV3QWR.js +67 -0
  6. package/dist/chunk-7WB6VWRK.js +798 -0
  7. package/dist/chunk-A2JJT4GA.js +56 -0
  8. package/dist/chunk-BAS26HBN.js +10 -0
  9. package/dist/chunk-BOVU4TCQ.js +65 -0
  10. package/dist/chunk-BY5G4225.js +6 -0
  11. package/dist/chunk-DFDNHVDW.js +284 -0
  12. package/dist/chunk-ELBLT2HZ.js +1 -0
  13. package/dist/chunk-EZZYLTWY.js +1 -0
  14. package/dist/chunk-FWA5K7Q2.js +48 -0
  15. package/dist/chunk-HC6ERSAH.js +55 -0
  16. package/dist/chunk-HLOUDLPI.js +48 -0
  17. package/dist/chunk-I3TKINSO.js +398 -0
  18. package/dist/chunk-IOPUS6Q5.js +15 -0
  19. package/dist/chunk-LKWYCYX5.js +22 -0
  20. package/dist/chunk-LYFIQPXX.js +1 -0
  21. package/dist/chunk-LZIOTBFX.js +1 -0
  22. package/dist/chunk-MU335ZA4.js +63 -0
  23. package/dist/chunk-MZKIL5IN.js +74 -0
  24. package/dist/chunk-N7HYNKK6.js +83 -0
  25. package/dist/chunk-NTFQ36UN.js +52 -0
  26. package/dist/chunk-NU6LVKGS.js +15 -0
  27. package/dist/chunk-O57GKTYU.js +30 -0
  28. package/dist/chunk-P2N6K2IV.js +20 -0
  29. package/dist/chunk-P53CKOME.js +1 -0
  30. package/dist/chunk-QCJWPXLH.js +40 -0
  31. package/dist/chunk-SKLMWHQD.js +109 -0
  32. package/dist/chunk-SOQDEPME.js +131 -0
  33. package/dist/chunk-UBN5JJKZ.js +26 -0
  34. package/dist/chunk-UD2CXYSJ.js +244 -0
  35. package/dist/chunk-UP6GGGAN.js +34 -0
  36. package/dist/chunk-V4EMDPCO.js +33 -0
  37. package/dist/chunk-VNGXRYFF.js +9 -0
  38. package/dist/chunk-WGCWJOT2.js +21 -0
  39. package/dist/chunk-X6W44WHO.js +26 -0
  40. package/dist/chunk-XXWNMJI6.js +15 -0
  41. package/dist/chunk-ZUSM4VW4.js +197 -0
  42. package/dist/client/EventTransport.d.ts +147 -0
  43. package/dist/client/EventTransport.js +1 -0
  44. package/dist/client/awaiting.d.ts +28 -0
  45. package/dist/client/awaiting.js +1 -0
  46. package/dist/client/channel-transport.d.ts +69 -0
  47. package/dist/client/channel-transport.js +1 -0
  48. package/dist/client/circuit-store.d.ts +87 -0
  49. package/dist/client/circuit-store.js +3 -0
  50. package/dist/client/client-kernel.d.ts +134 -0
  51. package/dist/client/client-kernel.js +1 -0
  52. package/dist/client/declared-input-dispatch.d.ts +22 -0
  53. package/dist/client/declared-input-dispatch.js +1 -0
  54. package/dist/client/inbound-dispatch.d.ts +24 -0
  55. package/dist/client/inbound-dispatch.js +1 -0
  56. package/dist/client/local-fold.d.ts +33 -0
  57. package/dist/client/local-fold.js +1 -0
  58. package/dist/client/render-sigils.d.ts +24 -0
  59. package/dist/client/render-sigils.js +1 -0
  60. package/dist/client/state-book.d.ts +30 -0
  61. package/dist/client/state-book.js +1 -0
  62. package/dist/client/trait-mount-error.d.ts +9 -0
  63. package/dist/client/trait-mount-error.js +1 -0
  64. package/dist/client/trait-types.d.ts +67 -0
  65. package/dist/client/trait-types.js +1 -0
  66. package/dist/credentials/env-vars.d.ts +18 -0
  67. package/dist/credentials/env-vars.js +1 -0
  68. package/dist/credentials/scope.d.ts +51 -0
  69. package/dist/credentials/scope.js +1 -0
  70. package/dist/credentials/vault.d.ts +142 -0
  71. package/dist/credentials/vault.js +1 -0
  72. package/dist/effects/in-flight-calls.d.ts +36 -0
  73. package/dist/effects/in-flight-calls.js +1 -0
  74. package/dist/effects/on-device-model.d.ts +22 -0
  75. package/dist/effects/on-device-model.js +1 -0
  76. package/dist/events/EventBus.d.ts +87 -0
  77. package/dist/events/EventBus.js +1 -0
  78. package/dist/events/emit-stamp.d.ts +47 -0
  79. package/dist/events/emit-stamp.js +1 -0
  80. package/dist/index.d.ts +43 -0
  81. package/dist/index.js +41 -0
  82. package/dist/kernel/decode.d.ts +13 -0
  83. package/dist/kernel/decode.js +1 -0
  84. package/dist/kernel/engine.d.ts +195 -0
  85. package/dist/kernel/engine.js +9 -0
  86. package/dist/kernel/frame-applier.d.ts +44 -0
  87. package/dist/kernel/frame-applier.js +1 -0
  88. package/dist/kernel/host.d.ts +206 -0
  89. package/dist/kernel/host.js +6 -0
  90. package/dist/kernel/lane.d.ts +7 -0
  91. package/dist/kernel/lane.js +1 -0
  92. package/dist/kernel/os-fetch-port.d.ts +7 -0
  93. package/dist/kernel/os-fetch-port.js +3 -0
  94. package/dist/kernel/os-port.d.ts +155 -0
  95. package/dist/kernel/os-port.js +1 -0
  96. package/dist/kernel/program-effects.d.ts +48 -0
  97. package/dist/kernel/program-effects.js +1 -0
  98. package/dist/kernel/secret-ports.d.ts +139 -0
  99. package/dist/kernel/secret-ports.js +2 -0
  100. package/dist/kernel/wire.d.ts +104 -0
  101. package/dist/kernel/wire.js +1 -0
  102. package/dist/loader/fetch-loader.d.ts +26 -0
  103. package/dist/loader/fetch-loader.js +1 -0
  104. package/dist/loader/lazy-page.d.ts +12 -0
  105. package/dist/loader/lazy-page.js +1 -0
  106. package/dist/loader/schema-loader.d.ts +144 -0
  107. package/dist/loader/schema-loader.js +1 -0
  108. package/dist/persistence/native-memory.d.ts +28 -0
  109. package/dist/persistence/native-memory.js +1 -0
  110. package/dist/runtime/entities/declaredCollections.d.ts +6 -0
  111. package/dist/runtime/entities/declaredCollections.js +1 -0
  112. package/dist/runtime/evaluation/local-store-transport.d.ts +59 -0
  113. package/dist/runtime/evaluation/local-store-transport.js +14 -0
  114. package/dist/runtime/evaluation/residence-transport.d.ts +15 -0
  115. package/dist/runtime/evaluation/residence-transport.js +1 -0
  116. package/dist/runtime/evaluation/routed-persistence.d.ts +9 -0
  117. package/dist/runtime/evaluation/routed-persistence.js +1 -0
  118. package/dist/runtime/events/identity/routing.d.ts +33 -0
  119. package/dist/runtime/events/identity/routing.js +1 -0
  120. package/dist/runtime/types.d.ts +374 -0
  121. package/dist/runtime/types.js +1 -0
  122. package/dist/service/default-call-service.d.ts +23 -0
  123. package/dist/service/default-call-service.js +2 -0
  124. package/dist/service/service-provider.d.ts +37 -0
  125. package/dist/service/service-provider.js +1 -0
  126. package/package.json +49 -3
  127. package/README.md +0 -3
@@ -0,0 +1,34 @@
1
+ import { isPageReference, isRoutePage, themeDataKey } from '@almadar/core';
2
+
3
+ // src/client/render-sigils.ts
4
+ var DEFAULT_THEME_KEY = "minimalist-light";
5
+ function inlineNavItems(pages) {
6
+ const items = [];
7
+ for (const page of pages) {
8
+ if (isPageReference(page)) continue;
9
+ const p = page;
10
+ if (!isRoutePage(p) || typeof p.label !== "string" || p.path.includes(":")) continue;
11
+ const item = { href: p.path, label: p.label };
12
+ if (typeof p.icon === "string") item.icon = p.icon;
13
+ if (p.roles !== void 0) item.roles = [...p.roles];
14
+ items.push(item);
15
+ }
16
+ return items;
17
+ }
18
+ function appNavItems(orbitals) {
19
+ const items = [];
20
+ const seen = /* @__PURE__ */ new Set();
21
+ for (const orbital of orbitals) {
22
+ for (const item of inlineNavItems(orbital.pages ?? [])) {
23
+ if (seen.has(item.href)) continue;
24
+ seen.add(item.href);
25
+ items.push(item);
26
+ }
27
+ }
28
+ return items;
29
+ }
30
+ function sigilThemeKey(orbitalTheme, appThemeKey) {
31
+ return themeDataKey(orbitalTheme) || appThemeKey || DEFAULT_THEME_KEY;
32
+ }
33
+
34
+ export { DEFAULT_THEME_KEY, appNavItems, inlineNavItems, sigilThemeKey };
@@ -0,0 +1,33 @@
1
+ // src/runtime/evaluation/residence-transport.ts
2
+ function createResidenceTransport(options) {
3
+ const { local, remote, browserEntities } = options;
4
+ const route = (orbitalName, request) => {
5
+ if (request.residence === "browser") return local;
6
+ if (request.residence === "server") {
7
+ if (remote === void 0) throw new Error(`residence: a ${orbitalName} ${request.event} leg needs server data, and this host has no server`);
8
+ return remote;
9
+ }
10
+ return remote ?? local;
11
+ };
12
+ return {
13
+ async register(schema) {
14
+ const result = await local.register(schema);
15
+ return remote ? remote.register(schema) : result;
16
+ },
17
+ async unregister() {
18
+ await local.unregister();
19
+ await remote?.unregister();
20
+ },
21
+ async send(orbitalName, request) {
22
+ return route(orbitalName, request).send(orbitalName, request);
23
+ },
24
+ async resolveRows(reference) {
25
+ const owner = browserEntities.has(reference.entityType) ? local : remote;
26
+ if (owner?.resolveRows === void 0) throw new Error(`residence: no transport resolves ${reference.entityType} row sets`);
27
+ return owner.resolveRows(reference);
28
+ },
29
+ ...remote?.subscribe ? { subscribe: remote.subscribe.bind(remote) } : {}
30
+ };
31
+ }
32
+
33
+ export { createResidenceTransport };
@@ -0,0 +1,9 @@
1
+ // src/credentials/env-vars.ts
2
+ var CREDENTIAL_MASTER_KEY_ENV = "ALMADAR_CREDENTIAL_MASTER_KEY";
3
+ var CREDENTIAL_PREVIOUS_MASTER_KEY_ENV = "ALMADAR_CREDENTIAL_MASTER_KEY_PREVIOUS";
4
+ var STORE_BOOTSTRAP_ENV_VARS = /* @__PURE__ */ new Set([CREDENTIAL_MASTER_KEY_ENV, CREDENTIAL_PREVIOUS_MASTER_KEY_ENV]);
5
+ function allCredentialEnvVars() {
6
+ return new Set(STORE_BOOTSTRAP_ENV_VARS);
7
+ }
8
+
9
+ export { CREDENTIAL_MASTER_KEY_ENV, CREDENTIAL_PREVIOUS_MASTER_KEY_ENV, STORE_BOOTSTRAP_ENV_VARS, allCredentialEnvVars };
@@ -0,0 +1,21 @@
1
+ // src/kernel/program-effects.ts
2
+ var PROGRAM_EFFECTS = [
3
+ "behavior/catalog",
4
+ "behavior/describe",
5
+ "behavior/source",
6
+ "behavior/resolve",
7
+ "behavior/dependencies",
8
+ "program/read",
9
+ "program/print",
10
+ "program/eval",
11
+ "program/validate",
12
+ "program/prove",
13
+ "program/os-grants",
14
+ "program/compose",
15
+ "program/step"
16
+ ];
17
+ function isProgramEffect(name) {
18
+ return PROGRAM_EFFECTS.includes(name);
19
+ }
20
+
21
+ export { PROGRAM_EFFECTS, isProgramEffect };
@@ -0,0 +1,26 @@
1
+ import { decodeServerProgressWire, decodeNextWire, decodeResolveProgressWire, decodeFiredTick } from '@almadar/core/kernel-wire';
2
+ export { decodeIoRequestWire } from '@almadar/core/kernel-wire';
3
+
4
+ // src/kernel/decode.ts
5
+ function decodeProgress(json) {
6
+ return decodeServerProgressWire(JSON.parse(json));
7
+ }
8
+ function decodeNext(json) {
9
+ const value = JSON.parse(json);
10
+ return value === null ? null : decodeNextWire(value);
11
+ }
12
+ function decodeResolveProgress(json) {
13
+ return decodeResolveProgressWire(JSON.parse(json));
14
+ }
15
+ function decodeDueTicks(json) {
16
+ const value = JSON.parse(json);
17
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("tickPass: the kernel answered a non-object");
18
+ const byOrbital = {};
19
+ for (const [orbital, ticks] of Object.entries(value)) {
20
+ if (!Array.isArray(ticks)) throw new Error(`tickPass: the kernel answered a non-list for orbital ${orbital}`);
21
+ byOrbital[orbital] = ticks.map(decodeFiredTick);
22
+ }
23
+ return byOrbital;
24
+ }
25
+
26
+ export { decodeDueTicks, decodeNext, decodeProgress, decodeResolveProgress };
@@ -0,0 +1,15 @@
1
+ // src/loader/lazy-page.ts
2
+ async function loadLazyPage(loader, page, importerPath) {
3
+ const loaded = await loader.load(page.orbRef, importerPath);
4
+ if (!loaded.success) return loaded;
5
+ const { schema, sourcePath } = loaded.data;
6
+ if (!schema.orbitals.some((o) => o.name === page.orbital)) {
7
+ return {
8
+ success: false,
9
+ error: `Lazy page ${page.path} expects orbital "${page.orbital}" in ${sourcePath}, found: ${schema.orbitals.map((o) => o.name).join(", ")}`
10
+ };
11
+ }
12
+ return { success: true, data: schema };
13
+ }
14
+
15
+ export { loadLazyPage };
@@ -0,0 +1,197 @@
1
+ import { resolveCredentialRef, getEffectiveCredentialStore, getModeControl } from './chunk-HLOUDLPI.js';
2
+ import { credentialStorageKey, resolveCredentialStatusIdentity, credentialStatusConnected } from '@almadar/core';
3
+
4
+ function userCredentialKey(principal, name) {
5
+ return credentialStorageKey({ name, principal });
6
+ }
7
+ function envTailsOf(env) {
8
+ return (names) => {
9
+ const tails = [];
10
+ for (const name of names) {
11
+ const value = env[name];
12
+ if (value === void 0 || value === "") continue;
13
+ const chars = Array.from(value);
14
+ tails.push(chars.length >= 8 ? { name, last4: chars.slice(-4).join("") } : { name });
15
+ }
16
+ return tails;
17
+ };
18
+ }
19
+ var installedSecretsHost = {
20
+ async store() {
21
+ return getEffectiveCredentialStore();
22
+ },
23
+ async resolve(name, principal) {
24
+ return resolveCredentialRef(name, void 0, principal);
25
+ }
26
+ };
27
+ function createSecretStore(now = Date.now, host = installedSecretsHost, tokenPost) {
28
+ const environmentMinted = /* @__PURE__ */ new Map();
29
+ const storeMinted = /* @__PURE__ */ new WeakMap();
30
+ const cacheFor = (store) => {
31
+ if (store === null) return environmentMinted;
32
+ const held = storeMinted.get(store);
33
+ if (held !== void 0) return held;
34
+ const cache = /* @__PURE__ */ new Map();
35
+ storeMinted.set(store, cache);
36
+ return cache;
37
+ };
38
+ const slot = (name, principal) => credentialStorageKey({ name, ...principal !== void 0 ? { principal } : {} });
39
+ return {
40
+ async get(name, principal) {
41
+ const store = await host.store();
42
+ const minted = cacheFor(store);
43
+ const key = slot(name, principal);
44
+ const held = minted.get(key);
45
+ if (held !== void 0) {
46
+ if (held.expiresAt > now()) return held.value;
47
+ minted.delete(key);
48
+ }
49
+ if (store !== null && store.enabled && tokenPost !== void 0) {
50
+ const fresh = await store.resolveFresh(name, principal, tokenPost);
51
+ if (fresh !== void 0) return fresh;
52
+ }
53
+ return host.resolve(name, principal);
54
+ },
55
+ async set(name, value, ttlMs, principal) {
56
+ const minted = cacheFor(await host.store());
57
+ const key = slot(name, principal);
58
+ if (ttlMs <= 0) minted.delete(key);
59
+ else minted.set(key, { value, expiresAt: now() + ttlMs });
60
+ },
61
+ async rotate(name, value, principal) {
62
+ const store = await host.store();
63
+ if (store === null) throw new Error("this host keeps no credential store to rotate into");
64
+ cacheFor(store).delete(slot(name, principal));
65
+ await store.replace(name, value, principal);
66
+ },
67
+ async persist(name, value, principal, label) {
68
+ const store = await host.store();
69
+ if (store === null || !store.enabled) throw new Error("this host keeps no credential store to persist into");
70
+ cacheFor(store).delete(slot(name, principal));
71
+ await store.persist(name, value, principal, label);
72
+ },
73
+ async label(name, principal) {
74
+ return (await host.store())?.label(name, principal);
75
+ },
76
+ async durable() {
77
+ const store = await host.store();
78
+ return store !== null && store.enabled;
79
+ },
80
+ async forget(name, principal) {
81
+ const store = await host.store();
82
+ const minted = cacheFor(store);
83
+ const key = slot(name, principal);
84
+ minted.delete(key);
85
+ await store?.remove(name, principal);
86
+ }
87
+ };
88
+ }
89
+ function createCredentialConnectPort(post) {
90
+ return async (grant) => {
91
+ const store = getEffectiveCredentialStore();
92
+ if (store === null || !store.enabled) return { error: { kind: "unavailable", message: "this host holds no credential store that can connect" } };
93
+ return store.connect(grant, post);
94
+ };
95
+ }
96
+ function createCredentialAdminPort() {
97
+ const installed = () => {
98
+ const store = getEffectiveCredentialStore();
99
+ if (store === null) throw new Error("this host keeps no credential store");
100
+ return store;
101
+ };
102
+ return {
103
+ async list() {
104
+ return getEffectiveCredentialStore()?.listing() ?? null;
105
+ },
106
+ async read(name) {
107
+ return getEffectiveCredentialStore()?.resolve(name) ?? null;
108
+ },
109
+ async write(service, name, value) {
110
+ await installed().set(service, name, value);
111
+ },
112
+ async remove(name) {
113
+ return installed().remove(name);
114
+ },
115
+ async rotate() {
116
+ return installed().rotate();
117
+ },
118
+ async mode() {
119
+ return getModeControl()?.mode ?? null;
120
+ },
121
+ async setMode(mode) {
122
+ const control = getModeControl();
123
+ if (control === null) throw new Error("No integration manager is installed on this host");
124
+ if (mode !== "mock" && mode !== "real") throw new Error(`mode must be "mock" or "real", got "${mode}"`);
125
+ control.setMode(mode);
126
+ return control.mode;
127
+ }
128
+ };
129
+ }
130
+ var systemRandom = (bytes) => crypto.getRandomValues(new Uint8Array(bytes));
131
+ var RANDOM_BYTES_MAX = 1024;
132
+ function binary(bytes) {
133
+ let text = "";
134
+ for (const byte of bytes) text += String.fromCharCode(byte);
135
+ return text;
136
+ }
137
+ function base64Standard(bytes) {
138
+ return btoa(binary(bytes));
139
+ }
140
+ function base64Url(bytes) {
141
+ return base64Standard(bytes).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
142
+ }
143
+ function randomBytesPayload(ports, bytes, key) {
144
+ if (key !== void 0 && (typeof key !== "string" || key === "")) {
145
+ throw new Error(`call key must evaluate to a non-empty string, got ${String(key)}`);
146
+ }
147
+ if (typeof bytes !== "number" || !Number.isInteger(bytes) || bytes < 1 || bytes > RANDOM_BYTES_MAX) {
148
+ throw new Error(`random-bytes: the byte count must be an integer from 1 to ${RANDOM_BYTES_MAX}, got ${String(bytes)}`);
149
+ }
150
+ const value = base64Url(ports.random(bytes));
151
+ return key === void 0 ? { value } : { value, key };
152
+ }
153
+ function signedIn(head, principal) {
154
+ if (principal === void 0) throw new Error(`${head}: nobody is signed in`);
155
+ return principal;
156
+ }
157
+ function credentialName(head, credential) {
158
+ if (typeof credential !== "string") throw new Error(`${head}: the credential must be a secret knob's name`);
159
+ return credential;
160
+ }
161
+ async function credentialStatusPayload(ports, credential, principal) {
162
+ const identity = resolveCredentialStatusIdentity(credential, principal);
163
+ const connected = credentialStatusConnected(await ports.secrets.get(identity.name, identity.principal), identity.principal);
164
+ const label = connected ? await ports.secrets.label?.(identity.name, identity.principal) ?? "" : "";
165
+ return { connected, label };
166
+ }
167
+ async function credentialForgetPayload(ports, credential, principal) {
168
+ const who = signedIn("credential-forget", principal);
169
+ const name = credentialName("credential-forget", credential);
170
+ await ports.secrets.forget(name, who);
171
+ return { connected: false, label: "" };
172
+ }
173
+ function createSecretPorts(options = {}) {
174
+ return {
175
+ random: options.random ?? systemRandom,
176
+ secrets: options.secrets ?? createSecretStore(Date.now, installedSecretsHost, options.tokenPost),
177
+ credentials: options.credentials ?? createCredentialAdminPort(),
178
+ env: options.env ?? ((names) => envTailsOf(process.env)(names)),
179
+ ...options.tokenPost !== void 0 ? { connect: createCredentialConnectPort(options.tokenPost) } : {}
180
+ };
181
+ }
182
+ var browserSecrets = {
183
+ async get(name) {
184
+ throw new Error(`credential ${name} is not available in a browser`);
185
+ },
186
+ async set(name) {
187
+ throw new Error(`credential ${name} cannot be stored in a browser`);
188
+ },
189
+ async forget(name) {
190
+ throw new Error(`credential ${name} cannot be forgotten in a browser`);
191
+ }
192
+ };
193
+ function createBrowserSecretPorts() {
194
+ return { random: systemRandom, secrets: browserSecrets };
195
+ }
196
+
197
+ export { RANDOM_BYTES_MAX, base64Standard, base64Url, createBrowserSecretPorts, createCredentialAdminPort, createCredentialConnectPort, createSecretPorts, createSecretStore, credentialForgetPayload, credentialStatusPayload, envTailsOf, randomBytesPayload, systemRandom, userCredentialKey };
@@ -0,0 +1,147 @@
1
+ import { OrbitalSchema, EventRequest, EventResponse, RowSetRef, RowQueryPage, EmittedEvent, ServerTopology } from '@almadar/core';
2
+
3
+ /**
4
+ * EventTransport — the client → orbital event transport port (plan P5,
5
+ * `docs/Almadar_Runtime_Stateless_Stateful_PLAN.md` §4.2).
6
+ *
7
+ * Promotes `@almadar/ui`'s `ServerBridgeTransport` interface +
8
+ * `createHttpTransport` into `@almadar/runtime` so there is ONE owner of
9
+ * the HTTP request/response leg instead of two (this package's own
10
+ * `ServerBridge` class and the ui provider). `@almadar/ui`'s provider will
11
+ * be switched onto this port at the W5b build checkpoint (see the plan);
12
+ * until then this file has no consumers outside this package.
13
+ *
14
+ * The wire shapes are `@almadar/core`'s existing `EventRequest` /
15
+ * `EventResponse` — no shadow types.
16
+ *
17
+ * @packageDocumentation
18
+ */
19
+
20
+ /**
21
+ * `true` = stateless topology: the server holds no circuit state between
22
+ * requests, so every `send()` request must carry `traits`/`entityByTrait`.
23
+ * `false` = the server (or an in-process evaluator) holds the state itself.
24
+ *
25
+ * Derivation mirrors `@almadar/ui`'s `ServerBridgeProvider` EXACTLY
26
+ * (`providers/ServerBridge.tsx`, both the initial-state fallback and the
27
+ * post-register `.then` callback — the same mapping was duplicated at two
28
+ * call sites there, which is the `stateSource` string-branching this port
29
+ * retires): `'stateful'` → false, `'stateless'` OR an absent/undeclared
30
+ * topology (older servers) → true. An absent topology defaulting to
31
+ * "stateless" is the ui's existing assumption, carried over unchanged, not
32
+ * a new judgment call made here.
33
+ */
34
+ declare function deriveCarriesCircuitState(topology: ServerTopology | undefined): boolean;
35
+ interface EventTransportRegisterResult {
36
+ success: boolean;
37
+ /** See `deriveCarriesCircuitState`. Computed once here, not re-derived by callers. */
38
+ carriesCircuitState: boolean;
39
+ }
40
+ /**
41
+ * Who a server push was addressed to: `peers` — another client's change
42
+ * (live push); `origin` — this client's own running request, live (a
43
+ * call-service's `emit.onMessage`).
44
+ */
45
+ type PushTarget = 'peers' | 'origin';
46
+ interface EventTransport {
47
+ /** Register a schema with the transport's target (server, or an in-process evaluator). */
48
+ register(schema: OrbitalSchema): Promise<EventTransportRegisterResult>;
49
+ unregister(): Promise<void>;
50
+ /** Play one event through the orbital named `orbitalName`. */
51
+ send(orbitalName: string, request: EventRequest): Promise<EventResponse>;
52
+ /**
53
+ * A row-set reference resolved by the host that holds the rows, for the viewer the transport is signed in as (the
54
+ * host applies `@read`): the rows that still match, in the reference's order. Absent when the transport has no
55
+ * such route (an in-process evaluator resolves against its own store).
56
+ */
57
+ resolveRows?(reference: RowSetRef): Promise<RowQueryPage>;
58
+ /**
59
+ * Subscribe to server-pushed cascade events (e.g. another client's
60
+ * persist-envelope emits, Almadar_Live_Push.md). Absent when the
61
+ * transport has no server to push from (in-process). `params` augments
62
+ * the push channel's query string (e.g. a caller-supplied per-tab
63
+ * `clientId` for the server's origin-exclusion) — the transport itself
64
+ * carries no notion of "tab identity", that is a client-role concern
65
+ * (plan P4).
66
+ */
67
+ subscribe?(onPush: (emitted: EmittedEvent, target: PushTarget) => void, params?: Record<string, string>): () => void;
68
+ /**
69
+ * The host runs the whole program, browser-stored entities included (an extension's worker): a
70
+ * view of it keeps no browser store of its own and sends every leg to the host.
71
+ */
72
+ readonly hostsBrowserStore?: boolean;
73
+ /**
74
+ * Hear the results of dispatches the host ran without any view asking (a declared input, a
75
+ * follow-on call's outcome), so an open view shows them. The view applies the result; it never
76
+ * runs the dispatch again. `params` addresses this view on a push channel, as for `subscribe`.
77
+ */
78
+ subscribeHostDispatches?(onDispatch: HostDispatchListener, params?: Record<string, string>): () => void;
79
+ }
80
+ /** A dispatch the host ran on its own, with its result. */
81
+ type HostDispatchListener = (orbitalName: string, request: EventRequest, response: EventResponse) => void;
82
+ /**
83
+ * Supplies the bearer token the hosting server authenticates with. Resolved
84
+ * per request (tokens expire); `undefined` sends the request unauthenticated
85
+ * (dev servers with an auth bypass, standalone playground). Moved verbatim
86
+ * from `@almadar/ui`'s `providers/ServerBridge.tsx`.
87
+ */
88
+ type AccessTokenProvider = () => Promise<string | undefined>;
89
+ /** The host freed this client's session after its live stream dropped: mount again with the frames the client holds (EXEC-DIST-9). */
90
+ declare class SessionEndedError extends Error {
91
+ constructor(message: string);
92
+ }
93
+ /** The host answered a dispatch with a non-2xx status: a transport or auth failure, never an event response. */
94
+ declare class TransportStatusError extends Error {
95
+ readonly status: number;
96
+ readonly bodyText: string;
97
+ /** The `{ error, code }` body when the answer carried one. */
98
+ readonly refusal: RefusalBody | undefined;
99
+ constructor(status: number, bodyText: string);
100
+ }
101
+ interface RefusalBody {
102
+ code?: string;
103
+ error?: string;
104
+ }
105
+ interface HttpTransportOptions {
106
+ serverUrl: string;
107
+ getAccessToken?: AccessTokenProvider;
108
+ /** Custom fetch function (for testing or custom auth). */
109
+ fetch?: typeof fetch;
110
+ /**
111
+ * Gzip JSON request bodies of at least `COMPRESSED_BODY_MIN_BYTES` (`Content-Encoding: gzip`).
112
+ * Browsers never compress request bodies, so a registered schema otherwise goes up raw. Only
113
+ * for servers that inflate request bodies (Express's JSON parser does).
114
+ */
115
+ compressRequests?: boolean;
116
+ }
117
+ /** Bodies below this stay plain: compressing them costs more than it saves. */
118
+ declare const COMPRESSED_BODY_MIN_BYTES: number;
119
+ /** A JSON request body, gzipped (`encoding: 'gzip'`) when `compress` is set and it is large enough to be worth it. */
120
+ declare function encodeJsonBody(value: object, compress: boolean): Promise<{
121
+ body: string | Uint8Array<ArrayBuffer>;
122
+ encoding?: 'gzip';
123
+ }>;
124
+ /** HTTP transport — POSTs to a server speaking the canonical playground-runtime contract. */
125
+ declare function createHttpTransport(options: HttpTransportOptions): EventTransport;
126
+ /** Evaluates one event against an orbital with no wire in between — the unified `evaluateOrbitalEvent` (a separate, in-progress unit) is a valid `OrbitalEvaluator`. */
127
+ type OrbitalEvaluator = (orbitalName: string, request: EventRequest) => Promise<EventResponse>;
128
+ interface InProcessTransportOptions {
129
+ onRegister?: (schema: OrbitalSchema) => Promise<void> | void;
130
+ onUnregister?: () => Promise<void> | void;
131
+ /**
132
+ * In-process evaluation never crosses a wire, so nothing about circuit
133
+ * state is "carried" in the stateless-topology sense — `false` by
134
+ * default, mirroring `@almadar/ui`'s `BrowserPlayground` today: its
135
+ * in-process `register` never declares a `topology`, and the provider's
136
+ * fallback for a custom transport is `'in-process'` (not
137
+ * `'stateless-http'`).
138
+ */
139
+ carriesCircuitState?: boolean;
140
+ /** Resolves a row-set reference on the in-process kernel (`KernelEngine.resolveRows`), `@read` applied there. */
141
+ resolveRows?: (reference: RowSetRef) => Promise<RowQueryPage>;
142
+ }
143
+ /** In-process transport — the evaluator is INJECTED (e.g. the unified `evaluateOrbitalEvent`, owned elsewhere). */
144
+ declare function createInProcessTransport(evaluate: OrbitalEvaluator, options?: InProcessTransportOptions): EventTransport;
145
+
146
+ export { COMPRESSED_BODY_MIN_BYTES, SessionEndedError, TransportStatusError, createHttpTransport, createInProcessTransport, deriveCarriesCircuitState, encodeJsonBody };
147
+ export type { AccessTokenProvider, EventTransport, EventTransportRegisterResult, HostDispatchListener, HttpTransportOptions, InProcessTransportOptions, OrbitalEvaluator, PushTarget };
@@ -0,0 +1 @@
1
+ export { COMPRESSED_BODY_MIN_BYTES, SessionEndedError, TransportStatusError, createHttpTransport, createInProcessTransport, deriveCarriesCircuitState, encodeJsonBody } from '../chunk-UD2CXYSJ.js';
@@ -0,0 +1,28 @@
1
+ import { AwaitingTrait } from '@almadar/core';
2
+
3
+ /**
4
+ * Which traits are awaiting a server round trip right now — the kernel contract
5
+ * behind awaiting-server skeletons (`AwaitingTrait`, `@almadar/core`). The
6
+ * client kernel begins an entry right before a server leg's send and ends it
7
+ * when the leg folds or fails; local/hybrid traits and tick legs never enter.
8
+ * Subscriptions are per trait, so only the slots that trait owns re-render.
9
+ */
10
+
11
+ declare class AwaitingRegistry {
12
+ private readonly entries;
13
+ private readonly listeners;
14
+ private readonly anyListeners;
15
+ private version;
16
+ begin(list: readonly AwaitingTrait[]): void;
17
+ end(traits: readonly string[]): void;
18
+ get(trait: string): AwaitingTrait | undefined;
19
+ list(): AwaitingTrait[];
20
+ subscribe(trait: string, listener: () => void): () => void;
21
+ /** Any trait's awaiting change (an empty slot does not know which trait will fill it). */
22
+ subscribeAll(listener: () => void): () => void;
23
+ /** Bumped on every change — a stable snapshot key for `useSyncExternalStore`. */
24
+ getVersion(): number;
25
+ private emit;
26
+ }
27
+
28
+ export { AwaitingRegistry };
@@ -0,0 +1 @@
1
+ export { AwaitingRegistry } from '../chunk-HC6ERSAH.js';
@@ -0,0 +1,69 @@
1
+ import { EventRequest, EventResponse, EmittedEvent } from '@almadar/core';
2
+ import { PushTarget, EventTransport } from './EventTransport.js';
3
+
4
+ /**
5
+ * An EventTransport over a message channel, for a program hosted in another browser context (an
6
+ * extension's service worker, a web worker, an iframe). The view half plays events and receives
7
+ * pushes; the host half serves any EventTransport on the channel and pushes to its views. The
8
+ * channel is two functions, so any postMessage-style port fits behind it.
9
+ */
10
+
11
+ type ChannelMessage = {
12
+ almadarChannel: 'register';
13
+ id: number;
14
+ schemaName: string;
15
+ } | {
16
+ almadarChannel: 'registered';
17
+ id: number;
18
+ held: boolean;
19
+ } | {
20
+ almadarChannel: 'send';
21
+ id: number;
22
+ orbitalName: string;
23
+ request: EventRequest;
24
+ } | {
25
+ almadarChannel: 'reply';
26
+ id: number;
27
+ response: EventResponse;
28
+ } | {
29
+ almadarChannel: 'push';
30
+ emitted: EmittedEvent;
31
+ target: PushTarget;
32
+ } | {
33
+ almadarChannel: 'dispatched';
34
+ orbitalName: string;
35
+ request: EventRequest;
36
+ response: EventResponse;
37
+ };
38
+ interface TransportChannel {
39
+ post(message: ChannelMessage): void;
40
+ onMessage(listener: (message: ChannelMessage) => void): () => void;
41
+ /** The other end went away for good (a stopped extension worker's port); absent for channels that cannot close. */
42
+ onClose?(listener: () => void): () => void;
43
+ }
44
+ interface ChannelTransportOptions {
45
+ /** The host on the other end keeps the program's browser-stored entities (see `EventTransport.hostsBrowserStore`). */
46
+ hostsBrowserStore?: boolean;
47
+ }
48
+ /** The view half: an EventTransport whose program lives on the other end of the channel. */
49
+ declare function createChannelTransport(channel: TransportChannel, options?: ChannelTransportOptions): EventTransport;
50
+ interface ServedChannel {
51
+ /** Push a host-side event to the view (e.g. one a declared input caused while no view was asking). */
52
+ push(emitted: EmittedEvent, target: PushTarget): void;
53
+ /** Send the view the result of a dispatch the host ran on its own. */
54
+ pushDispatch(orbitalName: string, request: EventRequest, response: EventResponse): void;
55
+ stop(): void;
56
+ }
57
+ /** The host half: serve `transport` on `channel` for the program named `schemaName`. */
58
+ declare function serveChannel(channel: TransportChannel, transport: EventTransport, options: {
59
+ schemaName: string;
60
+ }): ServedChannel;
61
+ /**
62
+ * A channel that listens from the moment it is wrapped and keeps what arrives until something
63
+ * subscribes, then hands it over in order: a host that is still starting (an extension worker
64
+ * waking up) serves the channel late without losing the view's first messages.
65
+ */
66
+ declare function holdUntilServed(channel: TransportChannel): TransportChannel;
67
+
68
+ export { createChannelTransport, holdUntilServed, serveChannel };
69
+ export type { ChannelMessage, ChannelTransportOptions, ServedChannel, TransportChannel };
@@ -0,0 +1 @@
1
+ export { createChannelTransport, holdUntilServed, serveChannel } from '../chunk-SKLMWHQD.js';