@almadar/shell-runtime 0.0.0-stage → 0.1.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 (180) hide show
  1. package/dist/chunk-2JU7Y4KU.js +21 -0
  2. package/dist/chunk-46RWK2B5.js +28 -0
  3. package/dist/chunk-4J2QEIUV.js +78 -0
  4. package/dist/chunk-4SEK5ER2.js +8 -0
  5. package/dist/chunk-4ZICQ5PM.js +192 -0
  6. package/dist/chunk-53IPZXDP.js +76 -0
  7. package/dist/chunk-5D63EMO5.js +16 -0
  8. package/dist/chunk-64IH2SMY.js +22 -0
  9. package/dist/chunk-7SDV3QWR.js +67 -0
  10. package/dist/chunk-CPSQXEJ6.js +55 -0
  11. package/dist/chunk-CQP5XAX6.js +173 -0
  12. package/dist/chunk-CROS2GEX.js +49 -0
  13. package/dist/chunk-D4XJTBLB.js +217 -0
  14. package/dist/chunk-D5USD2EX.js +232 -0
  15. package/dist/chunk-DYOJGLIX.js +25 -0
  16. package/dist/chunk-ELBLT2HZ.js +1 -0
  17. package/dist/chunk-EV56K4GB.js +63 -0
  18. package/dist/chunk-EZZYLTWY.js +1 -0
  19. package/dist/chunk-FQ6IZMIU.js +10 -0
  20. package/dist/chunk-FWA5K7Q2.js +48 -0
  21. package/dist/chunk-HC6ERSAH.js +55 -0
  22. package/dist/chunk-HLOUDLPI.js +48 -0
  23. package/dist/chunk-HMK6YMQS.js +135 -0
  24. package/dist/chunk-HNOAZWFH.js +19 -0
  25. package/dist/chunk-IHQLE5M7.js +62 -0
  26. package/dist/chunk-IOPUS6Q5.js +15 -0
  27. package/dist/chunk-JFWFDUTR.js +35 -0
  28. package/dist/chunk-LZIOTBFX.js +1 -0
  29. package/dist/chunk-MHYSHSRG.js +54 -0
  30. package/dist/chunk-MLKGABMK.js +7 -0
  31. package/dist/chunk-MZKIL5IN.js +74 -0
  32. package/dist/chunk-NAECVIAR.js +322 -0
  33. package/dist/chunk-NATGCIVM.js +583 -0
  34. package/dist/chunk-O57GKTYU.js +30 -0
  35. package/dist/chunk-ODJCZ27I.js +50 -0
  36. package/dist/chunk-P53CKOME.js +1 -0
  37. package/dist/chunk-Q2H75UYT.js +92 -0
  38. package/dist/chunk-Q7JK4KY7.js +9 -0
  39. package/dist/chunk-QELZ6TEJ.js +208 -0
  40. package/dist/chunk-QQRDUMB2.js +40 -0
  41. package/dist/chunk-RBUMDYFS.js +681 -0
  42. package/dist/chunk-REPX5QPI.js +57 -0
  43. package/dist/chunk-SAS5KKCR.js +43 -0
  44. package/dist/chunk-SKLMWHQD.js +109 -0
  45. package/dist/chunk-SOQDEPME.js +131 -0
  46. package/dist/chunk-SWPDU752.js +28 -0
  47. package/dist/chunk-T775TUCD.js +18 -0
  48. package/dist/chunk-UBN5JJKZ.js +26 -0
  49. package/dist/chunk-UJHOUZAL.js +36 -0
  50. package/dist/chunk-UP6GGGAN.js +34 -0
  51. package/dist/chunk-VMOBW7RK.js +21 -0
  52. package/dist/chunk-VNMG7NKY.js +69 -0
  53. package/dist/chunk-WNPNNYXY.js +22 -0
  54. package/dist/chunk-XB5GYODW.js +28 -0
  55. package/dist/chunk-XXWNMJI6.js +15 -0
  56. package/dist/chunk-YL2SO5TP.js +334 -0
  57. package/dist/chunk-YO4LWS3I.js +606 -0
  58. package/dist/chunk-ZAQSS47X.js +157 -0
  59. package/dist/chunk-ZCQUUJIF.js +129 -0
  60. package/dist/client/EventTransport.d.ts +131 -0
  61. package/dist/client/EventTransport.js +2 -0
  62. package/dist/client/ServerBridge.d.ts +126 -0
  63. package/dist/client/ServerBridge.js +3 -0
  64. package/dist/client/awaiting.d.ts +28 -0
  65. package/dist/client/awaiting.js +2 -0
  66. package/dist/client/channel-transport.d.ts +69 -0
  67. package/dist/client/channel-transport.js +2 -0
  68. package/dist/client/circuit-store.d.ts +76 -0
  69. package/dist/client/circuit-store.js +4 -0
  70. package/dist/client/client-kernel.d.ts +113 -0
  71. package/dist/client/client-kernel.js +1 -0
  72. package/dist/client/declared-input-dispatch.d.ts +5 -0
  73. package/dist/client/declared-input-dispatch.js +2 -0
  74. package/dist/client/inbound-dispatch.d.ts +5 -0
  75. package/dist/client/inbound-dispatch.js +2 -0
  76. package/dist/client/local-fold.d.ts +26 -0
  77. package/dist/client/local-fold.js +2 -0
  78. package/dist/client/render-sigils.d.ts +24 -0
  79. package/dist/client/render-sigils.js +2 -0
  80. package/dist/client/state-book.d.ts +37 -0
  81. package/dist/client/state-book.js +2 -0
  82. package/dist/client/trait-mount-error.d.ts +9 -0
  83. package/dist/client/trait-mount-error.js +2 -0
  84. package/dist/client/trait-types.d.ts +67 -0
  85. package/dist/client/trait-types.js +1 -0
  86. package/dist/credentials/env-vars.d.ts +14 -0
  87. package/dist/credentials/env-vars.js +3 -0
  88. package/dist/credentials/scope.d.ts +50 -0
  89. package/dist/credentials/scope.js +2 -0
  90. package/dist/credentials/seed.d.ts +21 -0
  91. package/dist/credentials/seed.js +2 -0
  92. package/dist/credentials/store.d.ts +110 -0
  93. package/dist/credentials/store.js +2 -0
  94. package/dist/effects/in-flight-calls.d.ts +36 -0
  95. package/dist/effects/in-flight-calls.js +2 -0
  96. package/dist/effects/on-device-model.d.ts +22 -0
  97. package/dist/effects/on-device-model.js +2 -0
  98. package/dist/events/EventBus.d.ts +90 -0
  99. package/dist/events/EventBus.js +2 -0
  100. package/dist/events/emit-stamp.d.ts +47 -0
  101. package/dist/events/emit-stamp.js +2 -0
  102. package/dist/index-hT1xCdTq.d.ts +46 -0
  103. package/dist/index.d.ts +60 -0
  104. package/dist/index.js +59 -0
  105. package/dist/kernel/beacon.d.ts +32 -0
  106. package/dist/kernel/beacon.js +2 -0
  107. package/dist/kernel/decode.d.ts +15 -0
  108. package/dist/kernel/decode.js +2 -0
  109. package/dist/kernel/engine.d.ts +94 -0
  110. package/dist/kernel/engine.js +11 -0
  111. package/dist/kernel/frame-applier.d.ts +43 -0
  112. package/dist/kernel/frame-applier.js +2 -0
  113. package/dist/kernel/host.d.ts +95 -0
  114. package/dist/kernel/host.js +9 -0
  115. package/dist/kernel/http.d.ts +302 -0
  116. package/dist/kernel/http.js +6 -0
  117. package/dist/kernel/lane.d.ts +28 -0
  118. package/dist/kernel/lane.js +2 -0
  119. package/dist/kernel/oauth-effects.d.ts +25 -0
  120. package/dist/kernel/oauth-effects.js +7 -0
  121. package/dist/kernel/oauth-port.d.ts +31 -0
  122. package/dist/kernel/oauth-port.js +2 -0
  123. package/dist/kernel/os-port.d.ts +133 -0
  124. package/dist/kernel/os-port.js +2 -0
  125. package/dist/kernel/program-effects.d.ts +65 -0
  126. package/dist/kernel/program-effects.js +2 -0
  127. package/dist/kernel/wire.d.ts +66 -0
  128. package/dist/kernel/wire.js +1 -0
  129. package/dist/loader/http-loader.d.ts +111 -0
  130. package/dist/loader/http-loader.js +2 -0
  131. package/dist/loader/lazy-page.d.ts +12 -0
  132. package/dist/loader/lazy-page.js +2 -0
  133. package/dist/loader/schema-loader.d.ts +160 -0
  134. package/dist/loader/schema-loader.js +1 -0
  135. package/dist/persistence/native-memory.d.ts +28 -0
  136. package/dist/persistence/native-memory.js +2 -0
  137. package/dist/runtime/effects/composition/compose-behaviors.d.ts +58 -0
  138. package/dist/runtime/effects/composition/compose-behaviors.js +4 -0
  139. package/dist/runtime/effects/composition/event-wiring.d.ts +38 -0
  140. package/dist/runtime/effects/composition/event-wiring.js +2 -0
  141. package/dist/runtime/effects/composition/index.d.ts +5 -0
  142. package/dist/runtime/effects/composition/index.js +6 -0
  143. package/dist/runtime/effects/composition/layout-strategy.d.ts +35 -0
  144. package/dist/runtime/effects/composition/layout-strategy.js +2 -0
  145. package/dist/runtime/effects/composition/pipe.d.ts +25 -0
  146. package/dist/runtime/effects/composition/pipe.js +2 -0
  147. package/dist/runtime/entities/mockStoreSeed.d.ts +56 -0
  148. package/dist/runtime/entities/mockStoreSeed.js +3 -0
  149. package/dist/runtime/entities/seedBrowserStore.d.ts +28 -0
  150. package/dist/runtime/entities/seedBrowserStore.js +2 -0
  151. package/dist/runtime/entities/std-mock-seed.d.ts +87 -0
  152. package/dist/runtime/entities/std-mock-seed.js +2 -0
  153. package/dist/runtime/evaluation/local-store-transport.d.ts +68 -0
  154. package/dist/runtime/evaluation/local-store-transport.js +18 -0
  155. package/dist/runtime/evaluation/residence-transport.d.ts +15 -0
  156. package/dist/runtime/evaluation/residence-transport.js +2 -0
  157. package/dist/runtime/evaluation/routed-persistence.d.ts +9 -0
  158. package/dist/runtime/evaluation/routed-persistence.js +2 -0
  159. package/dist/runtime/events/identity/routing.d.ts +84 -0
  160. package/dist/runtime/events/identity/routing.js +2 -0
  161. package/dist/runtime/time/TickScheduler.d.ts +77 -0
  162. package/dist/runtime/time/TickScheduler.js +3 -0
  163. package/dist/runtime/time/cron.d.ts +25 -0
  164. package/dist/runtime/time/cron.js +2 -0
  165. package/dist/runtime/time/duration.d.ts +20 -0
  166. package/dist/runtime/time/duration.js +2 -0
  167. package/dist/runtime/traits/OrbitalTraitParsing.d.ts +34 -0
  168. package/dist/runtime/traits/OrbitalTraitParsing.js +2 -0
  169. package/dist/runtime/traits/listen-targets.d.ts +16 -0
  170. package/dist/runtime/traits/listen-targets.js +3 -0
  171. package/dist/runtime/traits/trait-index.d.ts +35 -0
  172. package/dist/runtime/traits/trait-index.js +3 -0
  173. package/dist/runtime/types.d.ts +574 -0
  174. package/dist/runtime/types.js +2 -0
  175. package/dist/service/default-call-service.d.ts +23 -0
  176. package/dist/service/default-call-service.js +3 -0
  177. package/dist/service/service-provider.d.ts +37 -0
  178. package/dist/service/service-provider.js +2 -0
  179. package/package.json +46 -3
  180. package/README.md +0 -3
@@ -0,0 +1,583 @@
1
+ import { isProgramEffect } from './chunk-HNOAZWFH.js';
2
+ import { systemRandom, base64Standard, sendBeaconRequest, streamHttp, sendHttp, checkOAuthReply } from './chunk-YO4LWS3I.js';
3
+ import { untilAborted } from './chunk-MZKIL5IN.js';
4
+ import { OnDeviceModelFailure, promptOnDevice, embedOnDevice } from './chunk-FWA5K7Q2.js';
5
+ import { WriteDeclinedError, isJsonObject, QueryDeclinedError, TabHostFailure, OrbitalEventRequestSchema, credentialStatusConnected } from '@almadar/core';
6
+
7
+ function issuePayload(issue) {
8
+ const payload = { code: issue.code, message: issue.message };
9
+ if (issue.path !== void 0) payload.path = issue.path;
10
+ if (issue.line !== void 0) payload.line = issue.line;
11
+ if (issue.column !== void 0) payload.column = issue.column;
12
+ return payload;
13
+ }
14
+ function toJson(value) {
15
+ return JSON.parse(JSON.stringify(value));
16
+ }
17
+ async function settle(work) {
18
+ try {
19
+ return { ok: await work() };
20
+ } catch (error) {
21
+ return { error: error instanceof Error ? error.message : String(error) };
22
+ }
23
+ }
24
+ function serviceParams(args) {
25
+ if (args === null) return void 0;
26
+ if (!isJsonObject(args)) throw new Error("call-service: the arguments are not an object");
27
+ return args;
28
+ }
29
+ function failureMessage(error) {
30
+ return error instanceof Error ? error.message : String(error);
31
+ }
32
+ async function callService(ports, request, scope) {
33
+ const { service, method, args, key, caller, site } = request;
34
+ const identity = caller !== void 0 ? { principal: caller.principal, ...caller.role !== void 0 ? { role: caller.role } : {} } : {};
35
+ const orbital = site?.orbital ?? scope.orbital;
36
+ const onMessage = site?.emit.onMessage;
37
+ const message = (payload) => {
38
+ if (site === void 0 || onMessage === void 0) return;
39
+ ports.deliverLive({ orbital, trait: site.trait, event: onMessage }, payload, scope.originClientId);
40
+ };
41
+ const call = async (signal, outsideRequest) => {
42
+ const host = site !== void 0 ? ports.servicePorts({ orbital, trait: site.trait }, scope.user, message, outsideRequest === true ? void 0 : scope.assertReentry) : void 0;
43
+ const context = caller !== void 0 || signal !== void 0 || host !== void 0 || outsideRequest !== void 0 ? { ...identity, ...host !== void 0 ? { host } : {}, ...signal !== void 0 ? { signal } : {}, ...outsideRequest !== void 0 ? { outsideRequest } : {} } : void 0;
44
+ const result = await ports.callService(service, method, serviceParams(args), context);
45
+ return result === null ? null : toJson(result);
46
+ };
47
+ const deferred = site?.followOn === true ? ports.deferCallOutcome() : void 0;
48
+ if (site !== void 0 && deferred !== void 0) {
49
+ startDeferredCall(deferred, site, key, call, { ports, orbital, scope });
50
+ return { kind: "serviceDeferred" };
51
+ }
52
+ const run = async () => {
53
+ if (key === void 0) return { kind: "service", result: { ok: await call() } };
54
+ const outcome = await ports.inFlightCalls.run(key, (signal) => untilAborted(signal, call(signal)));
55
+ return outcome.cancelled ? { kind: "serviceCancelled" } : { kind: "service", result: { ok: outcome.value } };
56
+ };
57
+ try {
58
+ return await (scope.outsideEventQueue !== void 0 ? scope.outsideEventQueue(run) : run());
59
+ } catch (error) {
60
+ return { kind: "service", result: { error: failureMessage(error) } };
61
+ }
62
+ }
63
+ function startDeferredCall(defer, site, key, call, context) {
64
+ const { ports, orbital, scope } = context;
65
+ const deliver = (event, payload) => defer({
66
+ orbital,
67
+ traitName: site.trait,
68
+ event,
69
+ payload,
70
+ entityId: scope.entityId,
71
+ originClientId: scope.originClientId,
72
+ user: scope.user,
73
+ locale: scope.locale
74
+ });
75
+ const outcome = key === void 0 ? call(void 0, true).then((value) => ({ cancelled: false, value })) : ports.inFlightCalls.run(key, (signal) => untilAborted(signal, call(signal, true)));
76
+ void outcome.then(
77
+ (settled) => {
78
+ if (settled.cancelled) {
79
+ if (site.emit.cancelled !== void 0 && key !== void 0) deliver(site.emit.cancelled, { key });
80
+ } else if (site.emit.success !== void 0) {
81
+ deliver(site.emit.success, keyed(settled.value === null ? void 0 : toEventPayload(settled.value), key));
82
+ }
83
+ },
84
+ (error) => {
85
+ if (site.emit.failure !== void 0) deliver(site.emit.failure, keyed({ error: failureMessage(error) }, key));
86
+ }
87
+ );
88
+ }
89
+ function keyed(payload, key) {
90
+ return payload !== void 0 && key !== void 0 ? { ...payload, key } : payload;
91
+ }
92
+ function toEventPayload(value) {
93
+ return isJsonObject(value) ? value : void 0;
94
+ }
95
+ async function substrate(ports, request, scope) {
96
+ const { key, site } = request;
97
+ const sink = ports.deferCallOutcome();
98
+ const complete = ports.substrateCompletion;
99
+ if (key === void 0 || site === void 0 || sink === void 0 || complete === void 0) return substrateInPlace(ports, request, scope);
100
+ const source = site.emit.onMessage !== void 0 ? ports.substrateStream?.(request.op, request.args, scope) : void 0;
101
+ if (ports.inFlightCalls.inFlight(key)) return { kind: "substrate", result: { error: { message: source !== void 0 ? `key ${key} already has a stream open` : `key ${key} already has a completion pending`, errors: [] } } };
102
+ const deliver = (fired) => {
103
+ if (fired !== null) sink({ orbital: site.orbital ?? scope.orbital, traitName: site.trait, event: fired.event, payload: isJsonObject(fired.payload) ? fired.payload : void 0, entityId: site.entityId, originClientId: scope.originClientId, user: scope.user, locale: scope.locale });
104
+ };
105
+ const failed = (error) => deliver(complete(site, key, request.op, request.args, { error: { message: failureMessage(error), errors: [] } }));
106
+ if (source !== void 0 && ports.substrateMessage !== void 0) {
107
+ const message = ports.substrateMessage;
108
+ void ports.inFlightCalls.run(key, (signal) => new Promise((resolve) => {
109
+ let unsubscribe;
110
+ let ended = false;
111
+ const end = () => {
112
+ ended = true;
113
+ unsubscribe?.();
114
+ signal.removeEventListener("abort", end);
115
+ resolve();
116
+ };
117
+ signal.addEventListener("abort", end, { once: true });
118
+ unsubscribe = source.subscribe((value) => {
119
+ if (signal.aborted) return;
120
+ const fired = message(site, key, value);
121
+ deliver(fired);
122
+ }, end);
123
+ if (ended) unsubscribe();
124
+ })).catch(failed);
125
+ return { kind: "serviceDeferred" };
126
+ }
127
+ const pending = ports.inFlightCalls.run(key, (signal) => untilAborted(signal, substrateInPlace(ports, request, { ...scope, assertReentry: void 0 })));
128
+ void pending.then((outcome) => {
129
+ if (outcome.cancelled || outcome.value.kind !== "substrate") return;
130
+ deliver(complete(site, key, request.op, request.args, outcome.value.result));
131
+ }, failed);
132
+ return { kind: "serviceDeferred" };
133
+ }
134
+ async function substrateInPlace(ports, request, scope) {
135
+ if (request.op === "program/live") return { kind: "substrate", result: { error: { message: "program/live streams to its onMessage route: give it a key and an onMessage route", errors: [] } } };
136
+ const handler = ports.programEffect();
137
+ const failure = (message, errors = []) => {
138
+ const detail = { message, errors };
139
+ return { kind: "substrate", result: { error: detail } };
140
+ };
141
+ if (request.op === "program/dispatch" || request.op === "program/inputs") {
142
+ const lent = ports.servicePorts({ orbital: scope.orbital, trait: "" }, scope.user, () => {
143
+ }, scope.assertReentry);
144
+ try {
145
+ const delivered = await deliverAgentAsk(request.op, request.args, lent);
146
+ if (delivered.ok) return { kind: "substrate", result: { ok: delivered.result } };
147
+ return failure(delivered.error, delivered.errors ?? []);
148
+ } catch (error) {
149
+ return failure(error instanceof Error ? error.message : String(error));
150
+ }
151
+ }
152
+ if (handler === void 0) return failure(`no program host configured for ${request.op}`);
153
+ if (!isProgramEffect(request.op)) return failure(`no program host configured for ${request.op}`);
154
+ try {
155
+ const user = scope.user;
156
+ const outcome = await handler(request.op, request.args, user !== void 0 ? { principal: user.id, ...user.role !== void 0 ? { role: user.role } : {} } : void 0);
157
+ if (outcome.ok) return { kind: "substrate", result: { ok: toJson(outcome.result) } };
158
+ return failure(outcome.error, (outcome.errors ?? []).map((issue) => toJson(issuePayload(issue))));
159
+ } catch (error) {
160
+ return failure(error instanceof Error ? error.message : String(error));
161
+ }
162
+ }
163
+ function present(value) {
164
+ if (value === void 0 || value === null || value === "") return false;
165
+ if (Array.isArray(value)) return value.length > 0;
166
+ if (isJsonObject(value)) return Object.keys(value).length > 0;
167
+ return true;
168
+ }
169
+ async function deliverAgentAsk(op, args, host) {
170
+ const [first, second, third] = args;
171
+ if (op === "program/inputs") {
172
+ const steps = args.length === 1 && isJsonObject(first) ? first["trace"] : void 0;
173
+ if (typeof steps !== "number") return { ok: false, error: "program/inputs: the host is asked for { trace } only" };
174
+ if (host.trace === void 0) return { ok: false, error: "program/inputs: this host keeps no dispatch trace" };
175
+ return { ok: true, result: host.trace(steps) };
176
+ }
177
+ if (args.length === 1 && isJsonObject(first)) {
178
+ const { inbound, body, headers } = first;
179
+ if (typeof inbound !== "string" || typeof body !== "string" || !isJsonObject(headers)) return { ok: false, error: "program/dispatch: the host is asked for { inbound, body, headers }" };
180
+ if (host.deliverInbound === void 0) return { ok: false, error: "program/dispatch: this host does not deliver inbound requests" };
181
+ const named = {};
182
+ for (const [key, value] of Object.entries(headers)) if (typeof value === "string") named[key] = value;
183
+ const answer = await host.deliverInbound(inbound, { headers: named, rawBody: body });
184
+ return { ok: true, result: { status: answer.status, body: answer.body } };
185
+ }
186
+ if (typeof first !== "string" || second === void 0 || !isJsonObject(second)) return { ok: false, error: "program/dispatch: the host is asked for a qualified address and a payload record" };
187
+ const payload = second;
188
+ if (isJsonObject(third)) {
189
+ if (host.dispatchRequest === void 0) return { ok: false, error: "program/dispatch: this host does not serve event requests" };
190
+ const stream = third["stream"] === true;
191
+ if (stream && host.supportsDispatchStream !== true) return { ok: false, error: "program/dispatch: this host does not answer stream items" };
192
+ const fields = { payload };
193
+ for (const key of ["event", "entityId", "targetTrait", "clientId", "locale", "delivery", "dispatchLog", "mount"]) {
194
+ const value = third[key];
195
+ if (present(value)) fields[key] = value;
196
+ }
197
+ const traits = third["traits"];
198
+ if (traits !== void 0 && traits !== null) fields["traits"] = traits;
199
+ if (isJsonObject(third["viewer"])) fields["user"] = third["viewer"];
200
+ const parsed = OrbitalEventRequestSchema.safeParse(fields);
201
+ if (!parsed.success) {
202
+ const message = `program/dispatch: not an event request: ${parsed.error.message}`;
203
+ return { ok: false, error: message, errors: [{ code: "INVALID_REQUEST", message, status: 400 }] };
204
+ }
205
+ const orbital = typeof third["orbital"] === "string" ? third["orbital"] : "";
206
+ const answered = await host.dispatchRequest(orbital, parsed.data, third["input"] === true, stream);
207
+ if (!answered.ok) return { ok: false, error: answered.error, errors: [{ code: answered.code, message: answered.error, status: answered.status }] };
208
+ if (!stream) return { ok: true, result: toJson(answered.response) };
209
+ if (answered.streamItems === void 0) return { ok: false, error: "program/dispatch: this host does not answer stream items" };
210
+ return { ok: true, result: toJson({ ...answered.response, items: answered.streamItems }) };
211
+ }
212
+ const event = first.lastIndexOf(".");
213
+ const trait = first.lastIndexOf(".", event - 1);
214
+ if (event < 0 || trait < 0) return { ok: false, error: `program/dispatch: '${first}' is not a qualified address` };
215
+ const response = await host.dispatchInput(first.slice(0, trait), { targetTrait: first.slice(trait + 1, event), event: first.slice(event + 1), payload });
216
+ return { ok: true, result: toJson(response) };
217
+ }
218
+ var HTTP_UNAVAILABLE = "HTTP_KERNEL_UNAVAILABLE: this host was given no http ports";
219
+ function httpAnswer(exchange) {
220
+ return { kind: "http", result: exchange.kind === "reply" ? { ok: exchange.response } : { error: exchange.failure } };
221
+ }
222
+ async function http(ports, request, scope) {
223
+ const exchangePorts = ports.http;
224
+ if (exchangePorts === void 0) return { kind: "http", result: { error: { kind: "failed", message: HTTP_UNAVAILABLE } } };
225
+ const { key, site } = request;
226
+ const orbital = site?.orbital ?? scope.orbital;
227
+ const onMessage = site?.emit.onMessage;
228
+ const onEvent = (event) => {
229
+ if (site === void 0 || onMessage === void 0) return;
230
+ ports.deliverLive({ orbital, trait: site.trait, event: onMessage }, { ...event }, scope.originClientId);
231
+ };
232
+ const send = (signal) => request.kind === "httpStream" ? streamHttp(exchangePorts, request.request, { framing: request.framing, key: key ?? null }, onEvent, signal) : sendHttp(exchangePorts, request.request, signal, request.delayMs);
233
+ const run = async () => {
234
+ if (key === void 0) return httpAnswer(await send());
235
+ const outcome = await ports.inFlightCalls.run(key, (signal) => untilAborted(signal, send(signal)));
236
+ return outcome.cancelled ? { kind: "serviceCancelled" } : httpAnswer(outcome.value);
237
+ };
238
+ try {
239
+ return await (scope.outsideEventQueue !== void 0 ? scope.outsideEventQueue(run) : run());
240
+ } catch (error) {
241
+ return { kind: "http", result: { error: { kind: "failed", message: failureMessage(error) } } };
242
+ }
243
+ }
244
+ async function httpBeacon(ports, request, scope) {
245
+ const exchangePorts = ports.http;
246
+ if (exchangePorts === void 0) return { kind: "httpBeacon", result: { ok: { via: "unavailable", message: HTTP_UNAVAILABLE } } };
247
+ const { key } = request;
248
+ const send = async (signal) => ({ kind: "httpBeacon", result: await sendBeaconRequest(exchangePorts, request.request, signal) });
249
+ const run = async () => {
250
+ if (key === void 0) return send();
251
+ const outcome = await ports.inFlightCalls.run(key, (signal) => untilAborted(signal, send(signal)));
252
+ return outcome.cancelled ? { kind: "serviceCancelled" } : outcome.value;
253
+ };
254
+ try {
255
+ return await (scope.outsideEventQueue !== void 0 ? scope.outsideEventQueue(run) : run());
256
+ } catch (error) {
257
+ return { kind: "httpBeacon", result: { error: { kind: "failed", message: failureMessage(error) } } };
258
+ }
259
+ }
260
+ async function onDeviceModel(ports, request, scope) {
261
+ const { key } = request;
262
+ const ask = async (signal) => request.kind === "prompt" ? { kind: "prompt", result: { ok: await promptOnDevice(ports.onDevice, request.text, request.schema, key ?? null, signal) } } : { kind: "embed", result: { ok: await embedOnDevice(ports.onDevice, request.texts, key ?? null, signal) } };
263
+ const run = async () => {
264
+ if (key === void 0) return ask();
265
+ const outcome = await ports.inFlightCalls.run(key, (signal) => untilAborted(signal, ask(signal)));
266
+ return outcome.cancelled ? { kind: "serviceCancelled" } : outcome.value;
267
+ };
268
+ try {
269
+ return await (scope.outsideEventQueue !== void 0 ? scope.outsideEventQueue(run) : run());
270
+ } catch (error) {
271
+ const failure = error instanceof OnDeviceModelFailure ? { kind: error.kind, message: error.message } : { kind: "failed", message: failureMessage(error) };
272
+ return request.kind === "prompt" ? { kind: "prompt", result: { error: failure } } : { kind: "embed", result: { error: failure } };
273
+ }
274
+ }
275
+ var NO_TAB_HOST = "browser/tab: no host answers browser tabs";
276
+ async function tab(ports, request, scope) {
277
+ const { ask, key } = request;
278
+ const port = ports.tabs;
279
+ if (port === void 0) return { kind: "tab", result: { error: { kind: "unavailable", message: NO_TAB_HOST } } };
280
+ const deliver = (payload) => {
281
+ if (ask.kind !== "watch") return;
282
+ const target = ask.deliver;
283
+ const lent = ports.servicePorts({ orbital: target.orbital, trait: target.trait }, scope.user, () => {
284
+ });
285
+ void lent.dispatchInput(target.orbital, { targetTrait: target.trait, event: target.event, payload });
286
+ };
287
+ const perform = async (signal) => {
288
+ try {
289
+ return { kind: "tab", result: { ok: await port.perform(ask, { ...signal !== void 0 ? { signal } : {}, deliver }) } };
290
+ } catch (error) {
291
+ if (error instanceof TabHostFailure) return { kind: "tab", result: { error: { kind: error.kind, message: error.message } } };
292
+ return { kind: "tab", result: { error: { kind: "failed", message: failureMessage(error) } } };
293
+ }
294
+ };
295
+ const run = async () => {
296
+ if (key === void 0) return perform();
297
+ const outcome = await ports.inFlightCalls.run(key, (signal) => untilAborted(signal, perform(signal)));
298
+ return outcome.cancelled ? { kind: "serviceCancelled" } : outcome.value;
299
+ };
300
+ return scope.outsideEventQueue !== void 0 ? scope.outsideEventQueue(run) : run();
301
+ }
302
+ async function pageFacts(ports, request) {
303
+ return { kind: "pageFacts", result: await settle(async () => ports.pageFacts?.(request.fields) ?? { available: false, hostname: "", referrer: "", screenWidth: null }) };
304
+ }
305
+ async function osAnswer(ports, request, scope) {
306
+ const { os } = ports;
307
+ if (os === void 0) return { kind: "os", result: { error: { kind: "denied", message: `${request.op}: no os host configured` } } };
308
+ const { op, args, key, site } = request;
309
+ const completions = ports.osCompletions;
310
+ const sink = ports.deferCallOutcome();
311
+ const message = ports.substrateMessage;
312
+ if (key !== void 0 && site !== void 0 && completions !== void 0 && sink !== void 0 && message !== void 0 && os.stream !== void 0 && completions.streams(op)) {
313
+ const orbital = site.orbital ?? scope.orbital;
314
+ const lease = ports.inFlightCalls.reserve(key);
315
+ if (lease === void 0) return { kind: "os", result: { error: { kind: "invalid", message: `${op}: key ${key} already has a stream open` } } };
316
+ const stop = () => {
317
+ os.cancel?.(key);
318
+ lease.release();
319
+ };
320
+ lease.signal.addEventListener("abort", stop, { once: true });
321
+ const deliver = (fired) => {
322
+ if (fired === null || lease.signal.aborted) return false;
323
+ sink({ orbital, traitName: site.trait, event: fired.event, payload: isJsonObject(fired.payload) ? fired.payload : void 0, entityId: site.entityId, originClientId: scope.originClientId, user: scope.user, locale: scope.locale });
324
+ return true;
325
+ };
326
+ const started = await os.stream(op, args, key, (value) => deliver(message(site, key, value)), (error) => {
327
+ lease.release();
328
+ lease.signal.removeEventListener("abort", stop);
329
+ deliver(completions.event(site, key, { error }));
330
+ });
331
+ if ("error" in started) {
332
+ lease.release();
333
+ lease.signal.removeEventListener("abort", stop);
334
+ }
335
+ return { kind: "os", result: started };
336
+ }
337
+ if (key !== void 0 && site !== void 0 && completions !== void 0 && sink !== void 0 && os.defer !== void 0 && completions.defers(op)) {
338
+ const orbital = site.orbital ?? scope.orbital;
339
+ const lease = ports.inFlightCalls.reserve(key);
340
+ if (lease === void 0) return { kind: "os", result: { error: { kind: "invalid", message: `${op}: key ${key} already has a completion pending` } } };
341
+ const cancel = () => {
342
+ os.cancel?.(key);
343
+ lease.release();
344
+ };
345
+ lease.signal.addEventListener("abort", cancel, { once: true });
346
+ const started = os.defer(op, args, key, (outcome) => {
347
+ lease.release();
348
+ lease.signal.removeEventListener("abort", cancel);
349
+ if (lease.signal.aborted) return;
350
+ const fired = completions.event(site, key, outcome);
351
+ if (fired === null) return;
352
+ sink({
353
+ orbital,
354
+ traitName: site.trait,
355
+ event: fired.event,
356
+ payload: isJsonObject(fired.payload) ? fired.payload : void 0,
357
+ entityId: site.entityId,
358
+ originClientId: scope.originClientId,
359
+ user: scope.user,
360
+ locale: scope.locale
361
+ });
362
+ });
363
+ if ("error" in started) {
364
+ lease.release();
365
+ lease.signal.removeEventListener("abort", cancel);
366
+ }
367
+ return "error" in started ? { kind: "os", result: started } : { kind: "serviceDeferred" };
368
+ }
369
+ return { kind: "os", result: await os.answer(op, args) };
370
+ }
371
+ async function secret(ports, request) {
372
+ const store = ports.http?.secrets;
373
+ if (store === void 0) return { kind: "secret", result: { error: HTTP_UNAVAILABLE } };
374
+ return { kind: "secret", result: await settle(async () => await store.get(request.name, request.principal) ?? null) };
375
+ }
376
+ async function secretSet(ports, request) {
377
+ const store = ports.http?.secrets;
378
+ if (store === void 0) return { kind: "secretSet", result: { error: HTTP_UNAVAILABLE } };
379
+ return { kind: "secretSet", result: await settle(async () => {
380
+ await store.set(request.name, request.value, request.ttlMs, request.principal);
381
+ return null;
382
+ }) };
383
+ }
384
+ async function secretRotate(ports, request) {
385
+ const store = ports.http?.secrets;
386
+ if (store === void 0) return { kind: "secretRotate", result: { error: HTTP_UNAVAILABLE } };
387
+ const rotate = store.rotate;
388
+ if (rotate === void 0) return { kind: "secretRotate", result: { error: "this host keeps no rotatable credentials" } };
389
+ return { kind: "secretRotate", result: await settle(async () => {
390
+ await rotate.call(store, request.name, request.value, request.principal);
391
+ return null;
392
+ }) };
393
+ }
394
+ function random(ports, request) {
395
+ const source = ports.http?.random ?? systemRandom;
396
+ try {
397
+ return { kind: "random", result: { ok: base64Standard(source(request.bytes)) } };
398
+ } catch (error) {
399
+ return { kind: "random", result: { error: failureMessage(error) } };
400
+ }
401
+ }
402
+ async function credentialStatus(ports, request) {
403
+ const store = ports.http?.secrets;
404
+ if (store === void 0) return { kind: "credentialStatus", result: { error: HTTP_UNAVAILABLE } };
405
+ return { kind: "credentialStatus", result: await settle(async () => {
406
+ const connected = credentialStatusConnected(await store.get(request.name, request.principal), request.principal);
407
+ const label = connected ? await store.label?.(request.name, request.principal) : void 0;
408
+ return { connected, ...label !== void 0 ? { label } : {} };
409
+ }) };
410
+ }
411
+ async function credentialForget(ports, request) {
412
+ const store = ports.http?.secrets;
413
+ if (store === void 0) return { kind: "credentialForget", result: { error: HTTP_UNAVAILABLE } };
414
+ return { kind: "credentialForget", result: await settle(async () => {
415
+ await store.forget(request.name, request.principal);
416
+ return null;
417
+ }) };
418
+ }
419
+ async function credentialAdmin(ports, work) {
420
+ const port = ports.http?.credentials;
421
+ if (port === void 0) return { error: HTTP_UNAVAILABLE };
422
+ return settle(() => work(port));
423
+ }
424
+ async function oauth(ports, request) {
425
+ const port = ports.http?.oauth;
426
+ if (port === void 0) return { kind: "oauth", result: { error: "this host keeps no OAuth state" } };
427
+ return { kind: "oauth", result: await settle(async () => checkOAuthReply(await port.answer(request.ask, request.principal))) };
428
+ }
429
+ function rowData(value) {
430
+ if (!isJsonObject(value)) throw new Error("persist: the row is not an object");
431
+ return value;
432
+ }
433
+ async function queryRows(persistence, request) {
434
+ const { entityType, query, project } = request;
435
+ try {
436
+ if (project === "ids") {
437
+ if (!persistence.queryIds) return { kind: "queryUnsupported", reason: "no-ids-capability" };
438
+ return { kind: "idPage", result: { ok: await persistence.queryIds(entityType, query) } };
439
+ }
440
+ if (!persistence.queryPage) return { kind: "queryUnsupported", reason: "no-query-capability" };
441
+ return { kind: "page", result: { ok: await persistence.queryPage(entityType, query) } };
442
+ } catch (error) {
443
+ if (error instanceof QueryDeclinedError) return { kind: "queryUnsupported", reason: error.reason };
444
+ return { kind: project === "ids" ? "idPage" : "page", result: { error: failureMessage(error) } };
445
+ }
446
+ }
447
+ async function commitRows(persistence, request) {
448
+ if (!persistence.commitRows) return { kind: "committed", result: { error: "this store does not commit rows" } };
449
+ try {
450
+ return { kind: "committed", result: { ok: await persistence.commitRows(request.rows) } };
451
+ } catch (error) {
452
+ return { kind: "committed", result: { error: failureMessage(error) } };
453
+ }
454
+ }
455
+ async function writeRows(persistence, request) {
456
+ const { batch } = request;
457
+ try {
458
+ if (!persistence.writeBatch) return { kind: "writeUnsupported", reason: "no-write-capability" };
459
+ return { kind: "wrote", result: { ok: await persistence.writeBatch(batch) } };
460
+ } catch (error) {
461
+ if (error instanceof WriteDeclinedError) return { kind: "writeUnsupported", reason: error.reason };
462
+ return { kind: "wrote", result: { error: failureMessage(error) } };
463
+ }
464
+ }
465
+ function declareCapabilities(persistence, declare, entityTypes) {
466
+ for (const entityType of entityTypes) {
467
+ const query = persistence.queryPage ? persistence.queryCapabilities?.(entityType) : void 0;
468
+ const write = persistence.writeWhere || persistence.writeBatch || persistence.commitRows ? persistence.writeCapabilities?.(entityType) : void 0;
469
+ if (query === void 0 && write === void 0) continue;
470
+ declare(entityType, JSON.stringify(query ?? null), JSON.stringify(write ?? null));
471
+ }
472
+ }
473
+ async function answerRequest(ports, request, scope) {
474
+ const { persistence } = ports;
475
+ switch (request.kind) {
476
+ case "readRow":
477
+ return {
478
+ kind: "row",
479
+ result: await settle(async () => {
480
+ const row = await persistence.getById(request.entityType, request.id);
481
+ return row;
482
+ })
483
+ };
484
+ case "listRows":
485
+ return {
486
+ kind: "rows",
487
+ result: await settle(async () => await persistence.list(request.entityType))
488
+ };
489
+ case "queryRows":
490
+ return queryRows(persistence, request);
491
+ case "writeRows":
492
+ return writeRows(persistence, request);
493
+ case "commitRows":
494
+ return commitRows(persistence, request);
495
+ case "createRow":
496
+ return {
497
+ kind: "row",
498
+ result: await settle(async () => {
499
+ const data = rowData(request.data);
500
+ const { id } = await persistence.create(request.entityType, data);
501
+ return await persistence.getById(request.entityType, id) ?? { ...data, id };
502
+ })
503
+ };
504
+ case "writeRow":
505
+ return {
506
+ kind: "row",
507
+ result: await settle(async () => {
508
+ const data = rowData(request.data);
509
+ const existing = await persistence.getById(request.entityType, request.id);
510
+ if (existing === null) await persistence.create(request.entityType, { ...data, id: request.id });
511
+ else await persistence.update(request.entityType, request.id, { ...data, id: request.id });
512
+ return await persistence.getById(request.entityType, request.id) ?? { ...existing, ...data, id: request.id };
513
+ })
514
+ };
515
+ case "deleteRow":
516
+ return {
517
+ kind: "deleted",
518
+ result: await settle(async () => {
519
+ await persistence.delete(request.entityType, request.id);
520
+ return null;
521
+ })
522
+ };
523
+ case "callService":
524
+ return callService(ports, request, scope);
525
+ case "cancelCall":
526
+ ports.inFlightCalls.cancel(request.key);
527
+ ports.os?.cancel?.(request.key);
528
+ return { kind: "cancelled", result: { ok: null } };
529
+ case "substrate":
530
+ return substrate(ports, request, scope);
531
+ case "http":
532
+ case "httpStream":
533
+ return http(ports, request, scope);
534
+ case "httpBeacon":
535
+ return httpBeacon(ports, request, scope);
536
+ case "pageFacts":
537
+ return pageFacts(ports, request);
538
+ case "prompt":
539
+ case "embed":
540
+ return onDeviceModel(ports, request, scope);
541
+ case "tab":
542
+ return tab(ports, request, scope);
543
+ case "secret":
544
+ return secret(ports, request);
545
+ case "secretSet":
546
+ return secretSet(ports, request);
547
+ case "secretRotate":
548
+ return secretRotate(ports, request);
549
+ case "random":
550
+ return random(ports, request);
551
+ case "os":
552
+ return osAnswer(ports, request, scope);
553
+ case "clock":
554
+ return { kind: "clock", result: { ok: (ports.now ?? Date.now)() } };
555
+ case "deliver":
556
+ return { kind: "deliver", result: { error: { kind: "down", id: request.envelope.id } } };
557
+ case "credentialStatus":
558
+ return credentialStatus(ports, request);
559
+ case "credentialForget":
560
+ return credentialForget(ports, request);
561
+ case "credentialStoreList":
562
+ return { kind: request.kind, result: await credentialAdmin(ports, (port) => port.list()) };
563
+ case "credentialStoreRead":
564
+ return { kind: request.kind, result: await credentialAdmin(ports, (port) => port.read(request.name)) };
565
+ case "credentialStoreWrite":
566
+ return { kind: request.kind, result: await credentialAdmin(ports, async (port) => {
567
+ await port.write(request.service, request.name, request.value);
568
+ return null;
569
+ }) };
570
+ case "credentialStoreRemove":
571
+ return { kind: request.kind, result: await credentialAdmin(ports, (port) => port.remove(request.name)) };
572
+ case "credentialStoreRotate":
573
+ return { kind: request.kind, result: await credentialAdmin(ports, (port) => port.rotate()) };
574
+ case "credentialModeRead":
575
+ return { kind: request.kind, result: await credentialAdmin(ports, (port) => port.mode()) };
576
+ case "credentialModeWrite":
577
+ return { kind: request.kind, result: await credentialAdmin(ports, (port) => port.setMode(request.mode)) };
578
+ case "oauth":
579
+ return oauth(ports, request);
580
+ }
581
+ }
582
+
583
+ export { answerRequest, declareCapabilities, writeRows };
@@ -0,0 +1,30 @@
1
+ // src/runtime/evaluation/routed-persistence.ts
2
+ function pushedDown(method, name, entityType) {
3
+ if (method === void 0) throw new Error(`${name} is not supported by the store that holds ${entityType}`);
4
+ return method;
5
+ }
6
+ function routeByEntity(storedEntities, stored, other) {
7
+ const of = (entityType) => storedEntities.has(entityType) ? stored : other;
8
+ return {
9
+ create: (entityType, data) => of(entityType).create(entityType, data),
10
+ update: (entityType, id, data) => of(entityType).update(entityType, id, data),
11
+ delete: (entityType, id) => of(entityType).delete(entityType, id),
12
+ getById: (entityType, id) => of(entityType).getById(entityType, id),
13
+ list: (entityType) => of(entityType).list(entityType),
14
+ bindCollection: (entityType, collection) => of(entityType).bindCollection?.(entityType, collection),
15
+ queryPage: (entityType, query) => pushedDown(of(entityType).queryPage, "queryPage", entityType).call(of(entityType), entityType, query),
16
+ queryIds: (entityType, query) => pushedDown(of(entityType).queryIds, "queryIds", entityType).call(of(entityType), entityType, query),
17
+ queryCapabilities: (entityType) => pushedDown(of(entityType).queryCapabilities, "queryCapabilities", entityType).call(of(entityType), entityType),
18
+ writeCapabilities: (entityType) => pushedDown(of(entityType).writeCapabilities, "writeCapabilities", entityType).call(of(entityType), entityType),
19
+ writeWhere: (op) => pushedDown(of(op.entityType).writeWhere, "writeWhere", op.entityType).call(of(op.entityType), op),
20
+ writeBatch: async (batch) => {
21
+ const homes = new Set(batch.ops.map((op) => of(op.entityType)));
22
+ if (homes.size > 1) throw new Error("A batch spans the browser store and the in-memory rows; a batch runs in one store");
23
+ const [home] = homes;
24
+ if (home === void 0) return [];
25
+ return pushedDown(home.writeBatch, "writeBatch", batch.ops[0]?.entityType ?? "").call(home, batch);
26
+ }
27
+ };
28
+ }
29
+
30
+ export { routeByEntity };
@@ -0,0 +1,50 @@
1
+ import { StateBook } from './chunk-Q2H75UYT.js';
2
+ import { AwaitingRegistry } from './chunk-HC6ERSAH.js';
3
+
4
+ // src/client/circuit-store.ts
5
+ function createMemoryCircuitStore(traits = [], observer) {
6
+ const states = new StateBook(traits, observer);
7
+ const frames = /* @__PURE__ */ new Map();
8
+ const listeners = /* @__PURE__ */ new Set();
9
+ let version = 0;
10
+ return {
11
+ states,
12
+ frames,
13
+ callsitePayloads: /* @__PURE__ */ new Map(),
14
+ awaiting: new AwaitingRegistry(),
15
+ snapshot(trait, entityId, frameKey) {
16
+ const key = frameKey ?? trait;
17
+ const frame = frames.get(key);
18
+ return {
19
+ state: states.getState(trait, entityId)?.currentState ?? "",
20
+ frame: frame !== void 0 ? { ...frame } : void 0
21
+ };
22
+ },
23
+ restore(trait, entityId, snap, frameKey, cause) {
24
+ const key = frameKey ?? trait;
25
+ if (snap.state !== "") {
26
+ states.rollbackState(trait, snap.state, entityId, cause);
27
+ }
28
+ if (snap.frame === void 0) {
29
+ frames.delete(key);
30
+ } else {
31
+ frames.set(key, { ...snap.frame });
32
+ }
33
+ },
34
+ notify() {
35
+ version += 1;
36
+ for (const listener of listeners) listener();
37
+ },
38
+ subscribe(listener) {
39
+ listeners.add(listener);
40
+ return () => {
41
+ listeners.delete(listener);
42
+ };
43
+ },
44
+ getVersion() {
45
+ return version;
46
+ }
47
+ };
48
+ }
49
+
50
+ export { createMemoryCircuitStore };
@@ -0,0 +1 @@
1
+