@exponential_app/engine 0.0.0-stage → 0.1.1

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 (85) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +54 -0
  3. package/README.md +35 -2
  4. package/dist/capabilities.js +29 -0
  5. package/dist/capabilities.js.map +9 -0
  6. package/dist/chunks/index-3nf9f7pv.js +315 -0
  7. package/dist/chunks/index-3nf9f7pv.js.map +10 -0
  8. package/dist/chunks/index-3rgr16n2.js +443 -0
  9. package/dist/chunks/index-3rgr16n2.js.map +9 -0
  10. package/dist/chunks/index-79swfbsm.js +366 -0
  11. package/dist/chunks/index-79swfbsm.js.map +10 -0
  12. package/dist/chunks/index-knntt4cb.js +259 -0
  13. package/dist/chunks/index-knntt4cb.js.map +10 -0
  14. package/dist/chunks/index-m2845dn6.js +72 -0
  15. package/dist/chunks/index-m2845dn6.js.map +10 -0
  16. package/dist/chunks/index-pqpnz4ns.js +2213 -0
  17. package/dist/chunks/index-pqpnz4ns.js.map +9 -0
  18. package/dist/chunks/index-q4zws02e.js +2301 -0
  19. package/dist/chunks/index-q4zws02e.js.map +10 -0
  20. package/dist/chunks/index-s3xjr701.js +170 -0
  21. package/dist/chunks/index-s3xjr701.js.map +10 -0
  22. package/dist/chunks/index-sk8b0dh4.js +126 -0
  23. package/dist/chunks/index-sk8b0dh4.js.map +10 -0
  24. package/dist/chunks/index-tvsykgcv.js +3015 -0
  25. package/dist/chunks/index-tvsykgcv.js.map +19 -0
  26. package/dist/chunks/index-v0m7r4y3.js +6869 -0
  27. package/dist/chunks/index-v0m7r4y3.js.map +13 -0
  28. package/dist/consent.js +24 -0
  29. package/dist/consent.js.map +9 -0
  30. package/dist/index.js +654 -0
  31. package/dist/index.js.map +12 -0
  32. package/dist/lifecycle.js +11 -0
  33. package/dist/lifecycle.js.map +9 -0
  34. package/dist/outbox.js +27 -0
  35. package/dist/outbox.js.map +9 -0
  36. package/dist/pdf.js +15 -0
  37. package/dist/pdf.js.map +9 -0
  38. package/dist/providers.js +26 -0
  39. package/dist/providers.js.map +9 -0
  40. package/dist/runner.js +24 -0
  41. package/dist/runner.js.map +9 -0
  42. package/dist/tools.js +38 -0
  43. package/dist/tools.js.map +9 -0
  44. package/dist/types/domain-contract/src/app-records.d.ts +3148 -0
  45. package/dist/types/domain-contract/src/app-share.d.ts +222 -0
  46. package/dist/types/domain-contract/src/apps.d.ts +612 -0
  47. package/dist/types/eengine/fixtures/providers.json +55 -0
  48. package/dist/types/eengine/src/broker.d.ts +80 -0
  49. package/dist/types/eengine/src/capabilities.d.ts +88 -0
  50. package/dist/types/eengine/src/consent.d.ts +50 -0
  51. package/dist/types/eengine/src/index.d.ts +12 -0
  52. package/dist/types/eengine/src/instance.d.ts +131 -0
  53. package/dist/types/eengine/src/lifecycle.d.ts +64 -0
  54. package/dist/types/eengine/src/outbox.d.ts +3 -0
  55. package/dist/types/eengine/src/pdf.d.ts +36 -0
  56. package/dist/types/eengine/src/providers.d.ts +38 -0
  57. package/dist/types/eengine/src/runner.d.ts +82 -0
  58. package/dist/types/eengine/src/stores.d.ts +125 -0
  59. package/dist/types/eengine/src/synced.d.ts +59 -0
  60. package/dist/types/eengine/src/tools.d.ts +79 -0
  61. package/dist/types/eengine/src/web/index.d.ts +20 -0
  62. package/dist/types/eengine/src/web/mcp.d.ts +27 -0
  63. package/dist/types/eengine/src/web/platform.d.ts +91 -0
  64. package/dist/types/eengine/src/web/stores.d.ts +125 -0
  65. package/dist/types/emcp/fixtures/automations.json +521 -0
  66. package/dist/types/emcp/fixtures/hub.json +498 -0
  67. package/dist/types/emcp/src/access.d.ts +55 -0
  68. package/dist/types/emcp/src/audit.d.ts +22 -0
  69. package/dist/types/emcp/src/automations.d.ts +111 -0
  70. package/dist/types/emcp/src/exposes.d.ts +242 -0
  71. package/dist/types/emcp/src/hub.d.ts +63 -0
  72. package/dist/types/emcp/src/index.d.ts +7 -0
  73. package/dist/types/emcp/src/pure.d.ts +11 -0
  74. package/dist/types/emcp/src/upstream.d.ts +288 -0
  75. package/dist/types/emcp/src/vault.d.ts +34 -0
  76. package/dist/web/index.js +791 -0
  77. package/dist/web/index.js.map +13 -0
  78. package/fixtures/bundle.json +1165 -0
  79. package/fixtures/capabilities.json +434 -0
  80. package/fixtures/consent.json +146 -0
  81. package/fixtures/lifecycle.json +125 -0
  82. package/fixtures/outbox.json +22 -0
  83. package/fixtures/providers.json +55 -0
  84. package/fixtures/runner.json +2167 -0
  85. package/package.json +92 -4
package/dist/index.js ADDED
@@ -0,0 +1,654 @@
1
+ import {
2
+ CAPABILITIES2,
3
+ RESERVED_CAPABILITY_NAMES2,
4
+ scopeIdValid2,
5
+ capabilityNameValid2,
6
+ capabilityDef2,
7
+ scopeDef2,
8
+ parseCapabilityCall2,
9
+ urlOrigin2,
10
+ brokerDecide2,
11
+ agentToolList2,
12
+ brokerAuditRow2
13
+ } from "./chunks/index-tvsykgcv.js";
14
+ import {
15
+ CONSENT_COPY2,
16
+ GRANTS_RECORD_VERSION2,
17
+ consentAnswer2,
18
+ grantWrite2,
19
+ grantsRecord2,
20
+ grantsOnPackage2,
21
+ consentSheet2,
22
+ manageSheet2
23
+ } from "./chunks/index-knntt4cb.js";
24
+ import {
25
+ STOPPED2,
26
+ lifecycleStep2
27
+ } from "./chunks/index-m2845dn6.js";
28
+ import {
29
+ PROVIDER_KEYS2,
30
+ FORBIDDEN_HOST_KEYS2,
31
+ NETWORK_POLICIES2,
32
+ IDENTITY_KINDS2,
33
+ AGENT_PROVIDERS2,
34
+ validateHostConfig2,
35
+ engineViewer2,
36
+ engineRecordRefusal2,
37
+ networkAllows2
38
+ } from "./chunks/index-sk8b0dh4.js";
39
+ import {
40
+ outboxWrites2,
41
+ outboxRequest2,
42
+ outboxRows2,
43
+ outboxOutcome2,
44
+ outboxVerb2,
45
+ outboxFlush2,
46
+ outboxReflected2,
47
+ outboxPrune2,
48
+ outboxPendingLabel2,
49
+ outboxMode2
50
+ } from "./chunks/index-v0m7r4y3.js";
51
+ import {
52
+ wrapLines2,
53
+ pdfNumber2,
54
+ pdfImage2,
55
+ renderPdf2
56
+ } from "./chunks/index-3nf9f7pv.js";
57
+ import {
58
+ CAPABILITY_TOOLS2,
59
+ MIME_BY_EXTENSION2,
60
+ toolDef2,
61
+ nativeCaller2,
62
+ schemaViolation2,
63
+ validateToolArguments2,
64
+ base64Encode2,
65
+ base64Decode2,
66
+ sniffMime2,
67
+ mimeFor2,
68
+ newNotificationId2,
69
+ toolResult2,
70
+ toolError2,
71
+ bridgeCall2,
72
+ pdfFileName2
73
+ } from "./chunks/index-79swfbsm.js";
74
+ import {
75
+ RUNNER_COPY2,
76
+ RUNNER_BUNDLE2,
77
+ RUNNER_SHELL2,
78
+ runnerConfig2,
79
+ runnerHasPermissions2,
80
+ runnerPackage2,
81
+ runnerFailure2,
82
+ runnerToast2
83
+ } from "./chunks/index-q4zws02e.js";
84
+ import {
85
+ StoreError2,
86
+ applyBatch2,
87
+ LocalRecordStore2,
88
+ MemoryPersistence2,
89
+ MemoryRecordStore2,
90
+ MemoryVault2,
91
+ MemoryBlobStore2,
92
+ localDeviceId2
93
+ } from "./chunks/index-s3xjr701.js";
94
+ // packages/eengine/src/broker.ts
95
+ var refused = (verdict) => ({ refused: { code: verdict.verdict === `unknown` ? `UNKNOWN_TOOL` : `FORBIDDEN`, message: verdict.reason ?? `` } });
96
+
97
+ class Broker {
98
+ setup;
99
+ grantsNow;
100
+ foreground = false;
101
+ persisted = Promise.resolve();
102
+ constructor(setup) {
103
+ this.setup = setup;
104
+ this.grantsNow = { ...setup.grants };
105
+ }
106
+ get appId() {
107
+ return this.setup.appId;
108
+ }
109
+ get manifest() {
110
+ return this.setup.manifest;
111
+ }
112
+ get capabilities() {
113
+ return this.setup.capabilities;
114
+ }
115
+ grants() {
116
+ return { ...this.grantsNow };
117
+ }
118
+ setForeground(foreground) {
119
+ this.foreground = foreground;
120
+ }
121
+ provided() {
122
+ return this.setup.capabilities.map((c) => c.name);
123
+ }
124
+ record(client, call, verdict, outcome) {
125
+ this.setup.audit?.record(brokerAuditRow2({ appId: this.setup.appId, client, call, verdict, outcome }));
126
+ }
127
+ async run(client, call, verdict) {
128
+ const capability = this.setup.capabilities.find((c) => c.name === verdict.capability);
129
+ if (!capability || !verdict.tool) {
130
+ this.record(client, call, verdict, `unreachable`);
131
+ return { refused: { code: `FORBIDDEN`, message: `unavailable` } };
132
+ }
133
+ const { result, outcome } = await bridgeCall2({
134
+ tool: `${capability.name}_${verdict.tool}`,
135
+ arguments: call.arguments ?? {},
136
+ context: { app: this.setup.appId, screens: this.setup.screens },
137
+ blobs: this.setup.blobs,
138
+ native: (tool, args) => capability.call(tool.slice(tool.indexOf(`_`) + 1), args)
139
+ });
140
+ this.record(client, call, verdict, outcome);
141
+ return { result };
142
+ }
143
+ call(from, client, name, args) {
144
+ const call = { from, name, arguments: args };
145
+ const verdict = brokerDecide2({ manifest: this.setup.manifest, grants: this.grantsNow, provided: this.provided(), foreground: this.foreground, call });
146
+ if (verdict.verdict === `call`)
147
+ return this.run(client, call, verdict);
148
+ if (verdict.verdict === `ask`) {
149
+ const entry = this.setup.manifest.find((m) => m.id === verdict.scope) ?? { id: verdict.scope ?? ``, why: `` };
150
+ const { components, data } = consentSheet2(this.setup.appName, entry);
151
+ return Promise.resolve({ ask: verdict, sheet: { scope: entry.id, components, data } });
152
+ }
153
+ this.record(client, call, verdict, null);
154
+ return Promise.resolve(refused(verdict));
155
+ }
156
+ answer(from, client, name, args, verdict, answer) {
157
+ const call = { from, name, arguments: args };
158
+ if (!verdict.scope)
159
+ return Promise.resolve(refused(verdict));
160
+ const next = consentAnswer2(this.grantsNow, verdict.scope, answer);
161
+ this.grantsNow = next.grants;
162
+ this.persist(next.grants);
163
+ const decided = { ...verdict, verdict: next.verdict, reason: next.reason };
164
+ if (next.verdict === `call`)
165
+ return this.run(client, call, decided);
166
+ this.record(client, call, decided, null);
167
+ return Promise.resolve(refused(decided));
168
+ }
169
+ setGrant(via, gesture, scope, value) {
170
+ const next = grantWrite2(this.setup.manifest, this.grantsNow, { via, gesture, scope, value });
171
+ if (next.refused)
172
+ return next.refused;
173
+ this.grantsNow = next.grants;
174
+ this.persist(next.grants);
175
+ return null;
176
+ }
177
+ permissionsSheet() {
178
+ return manageSheet2(this.setup.manifest, this.grantsNow);
179
+ }
180
+ persist(grants) {
181
+ const { key, value } = grantsRecord2(this.setup.appId, this.setup.signer, this.setup.manifest, grants);
182
+ this.persisted = this.persisted.then(() => this.setup.vault.write(key, value)).catch(() => {});
183
+ }
184
+ }
185
+ // packages/eengine/src/instance.ts
186
+ import {
187
+ kindComputed,
188
+ kindRefs,
189
+ kindTransitions,
190
+ navigateTarget,
191
+ packageScreens,
192
+ parseRecordsSource,
193
+ parseSource,
194
+ recordPolicy,
195
+ recordsValue,
196
+ bridgePackage,
197
+ validatePackage,
198
+ verifyPackageFile
199
+ } from "@exponential_app/eui/host";
200
+ class LoadError extends Error {
201
+ kind;
202
+ issues;
203
+ constructor(kind, issues) {
204
+ super(`${kind}: ${issues.map((i) => `${i.path || `/`} ${i.message}`).join(`; `)}`);
205
+ this.kind = kind;
206
+ this.issues = issues;
207
+ this.name = `LoadError`;
208
+ }
209
+ }
210
+ var screenKey = (app) => `eengine/screen/${app}`;
211
+ var isObject = (v) => !!v && typeof v === `object` && !Array.isArray(v);
212
+ var packageOf = (file) => isObject(file) && isObject(file.package) ? file.package : file;
213
+ var brokered = (answer) => {
214
+ if (!(`result` in answer))
215
+ return answer;
216
+ const { result } = answer;
217
+ if (result.isError)
218
+ return { refused: { code: `failed`, message: result.content[0]?.text ?? `failed` } };
219
+ return { value: result.structuredContent ?? null };
220
+ };
221
+ var failure = (code, error) => isObject(error) && typeof error.code === `string` && typeof error.message === `string` ? { code: error.code, message: error.message } : { code, message: error instanceof Error ? error.message : String(error) };
222
+ var parseLast = (stored) => {
223
+ if (!stored)
224
+ return null;
225
+ try {
226
+ const v = JSON.parse(stored);
227
+ return isObject(v) && typeof v.screen === `string` && isObject(v.params) ? { screen: v.screen, params: v.params } : null;
228
+ } catch {
229
+ return null;
230
+ }
231
+ };
232
+
233
+ class AppInstance {
234
+ config;
235
+ pkg;
236
+ appId;
237
+ signer;
238
+ broker;
239
+ stateNow = STOPPED2;
240
+ outboxNow = [];
241
+ lastScreen;
242
+ constructor(config, pkg, appId, signer, broker, lastScreen) {
243
+ this.config = config;
244
+ this.pkg = pkg;
245
+ this.appId = appId;
246
+ this.signer = signer;
247
+ this.broker = broker;
248
+ this.lastScreen = lastScreen;
249
+ }
250
+ static async load(config, file) {
251
+ const verification = await verifyPackageFile(file);
252
+ if (verification.status === `invalid`)
253
+ throw new LoadError(`signature`, verification.issues);
254
+ const pkg = bridgePackage(packageOf(file));
255
+ const issues = validatePackage(pkg);
256
+ if (issues.length)
257
+ throw new LoadError(`invalid`, issues);
258
+ const p = pkg;
259
+ const appId = typeof p.id === `string` ? p.id : ``;
260
+ const signer = verification.status === `valid` ? verification.author.key : null;
261
+ const manifest = Array.isArray(p.capabilities) ? p.capabilities : [];
262
+ const key = grantsRecord2(appId, signer ?? ``, manifest, {}).key;
263
+ const [storedGrants, lastScreen] = await Promise.all([config.vault.read(key).catch(() => null), config.vault.read(screenKey(appId)).catch(() => null)]);
264
+ const broker = new Broker({
265
+ appId,
266
+ appName: typeof p.name === `string` ? p.name : appId,
267
+ signer: signer ?? ``,
268
+ manifest,
269
+ grants: grantsOnPackage2(storedGrants, signer ?? ``, manifest),
270
+ capabilities: config.capabilities,
271
+ vault: config.vault,
272
+ blobs: config.blobs,
273
+ screens: packageScreens(p).map((s) => s.template),
274
+ audit: config.audit ?? null
275
+ });
276
+ return new AppInstance(config, p, appId, signer, broker, lastScreen);
277
+ }
278
+ get manifest() {
279
+ return this.broker.manifest;
280
+ }
281
+ grants() {
282
+ return this.broker.grants();
283
+ }
284
+ get state() {
285
+ return this.stateNow;
286
+ }
287
+ get outbox() {
288
+ return this.outboxNow;
289
+ }
290
+ get mode() {
291
+ return outboxMode2(!!this.config.sync);
292
+ }
293
+ me() {
294
+ return engineViewer2(this.config.identity).id ?? ``;
295
+ }
296
+ now() {
297
+ return this.config.clock?.() ?? new Date().toISOString();
298
+ }
299
+ async answerConsent(name, args, verdict, answer) {
300
+ return brokered(await this.broker.answer(`ui`, null, name, args, verdict, answer));
301
+ }
302
+ setGrant(via, gesture, scope, value) {
303
+ return this.broker.setGrant(via, gesture, scope, value);
304
+ }
305
+ permissionsSheet() {
306
+ return this.broker.permissionsSheet();
307
+ }
308
+ async event(event) {
309
+ const { state, effects } = lifecycleStep2(this.stateNow, event, { pkg: { id: this.appId, screens: this.pkg.screens }, lastScreen: parseLast(this.lastScreen) });
310
+ this.stateNow = state;
311
+ this.broker.setForeground(state.phase === `foreground`);
312
+ for (const effect of effects) {
313
+ if (effect.effect === `open`)
314
+ this.config.window.open(this.appId, effect.screen, effect.params, `replace`);
315
+ else if (effect.effect === `persist`) {
316
+ this.lastScreen = JSON.stringify({ screen: effect.screen, params: effect.params });
317
+ await this.config.vault.write(screenKey(this.appId), this.lastScreen).catch(() => {});
318
+ } else if (effect.effect === `flush`)
319
+ await this.flush();
320
+ }
321
+ return effects;
322
+ }
323
+ async recordsValue(source) {
324
+ const parsed = parseSource(source);
325
+ const query = parsed ? parseRecordsSource(parsed) : null;
326
+ if (!query)
327
+ return;
328
+ if (query.app !== null)
329
+ return null;
330
+ let rows = await this.config.storage.rows(this.appId);
331
+ if (this.outboxNow.length)
332
+ rows = outboxRows2(rows, this.outboxNow, this.me());
333
+ const records = this.pkg.records;
334
+ const def = query.from && isObject(records) ? records[query.from] : undefined;
335
+ const viewer = engineViewer2(this.config.identity);
336
+ return recordsValue(rows, query, {
337
+ me: viewer.id,
338
+ now: this.now(),
339
+ names: {},
340
+ computed: kindComputed(records, query.from),
341
+ refs: kindRefs(records, query.from),
342
+ transitions: kindTransitions(def),
343
+ role: viewer.role
344
+ });
345
+ }
346
+ subscribe(on) {
347
+ return this.config.storage.subscribe(this.appId, () => on());
348
+ }
349
+ async call(name, args, newIds = []) {
350
+ const a = isObject(args) ? args : {};
351
+ switch (name) {
352
+ case `records_upsert`:
353
+ return this.write(`upsert`, a, newIds);
354
+ case `records_delete`:
355
+ return this.write(`delete`, a, newIds);
356
+ case `records_batch`:
357
+ return this.write(`batch`, a, newIds);
358
+ case `app_navigate`: {
359
+ const target = navigateTarget(this.pkg, args);
360
+ if (`error` in target)
361
+ return { refused: { code: `BAD_REQUEST`, message: target.error } };
362
+ this.config.window.open(this.appId, target.screen, target.params, `replace`);
363
+ this.stateNow = { ...this.stateNow, screen: target.screen, params: target.params };
364
+ return { value: null };
365
+ }
366
+ default:
367
+ return brokered(await this.broker.call(`ui`, null, name, args));
368
+ }
369
+ }
370
+ async refusal(writes) {
371
+ const rows = await this.config.storage.rows(this.appId).catch(() => []);
372
+ const records = isObject(this.pkg.records) ? this.pkg.records : {};
373
+ for (const w of writes) {
374
+ const row = rows.find((r) => r.id === w.id);
375
+ const op = w.op;
376
+ const kind = w.op === `delete` ? row?.kind : w.kind;
377
+ const policy = recordPolicy(kind ? records[kind] : undefined);
378
+ const refusal = engineRecordRefusal2(this.config.identity, policy, op, w.op === `create` ? null : row ? { authorId: row.authorId ?? null, createdBy: row.createdBy } : null);
379
+ if (refusal)
380
+ return refusal;
381
+ }
382
+ return null;
383
+ }
384
+ async write(call, args, newIds) {
385
+ const writes = outboxWrites2(call, args, newIds);
386
+ const refusal = await this.refusal(writes);
387
+ if (refusal)
388
+ return { refused: { code: `FORBIDDEN`, message: refusal } };
389
+ const entry = { writeId: this.config.newId?.() ?? crypto.randomUUID(), appId: this.appId, call, writes, at: this.now(), state: `pending` };
390
+ const answer = call === `upsert` ? { id: writes[0]?.id } : call === `delete` ? null : { ids: writes.map((w) => w.id) };
391
+ if (this.mode === `direct`) {
392
+ try {
393
+ await this.config.storage.write(this.appId, batchOf(entry), this.me());
394
+ return { value: answer };
395
+ } catch (error) {
396
+ return { refused: failure(`STORE`, error) };
397
+ }
398
+ }
399
+ this.outboxNow = [...this.outboxNow, entry];
400
+ if (this.stateNow.phase === `foreground`)
401
+ await this.flush();
402
+ return { value: answer };
403
+ }
404
+ async flush() {
405
+ const sync = this.config.sync;
406
+ if (!sync)
407
+ return;
408
+ const results = {};
409
+ for (const entry of this.outboxNow.filter((e) => e.state === `pending`)) {
410
+ const { call, input } = outboxRequest2(entry);
411
+ const result = await sync.push(this.appId, call, input).catch(() => ({ transport: true }));
412
+ results[entry.writeId] = result;
413
+ if (outboxOutcome2(entry, result) === `retry`)
414
+ break;
415
+ }
416
+ if (!Object.keys(results).length)
417
+ return;
418
+ const now = this.now();
419
+ const after = outboxFlush2(this.outboxNow, results, now).after;
420
+ const rows = await this.config.storage.rows(this.appId).catch(() => []);
421
+ this.outboxNow = outboxPrune2(after, rows, now);
422
+ }
423
+ }
424
+ function batchOf(entry) {
425
+ return {
426
+ writeId: entry.writeId,
427
+ writes: entry.writes.map((w) => w.op === `delete` ? { op: `delete`, id: w.id } : { op: `upsert`, id: w.id, kind: w.kind, data: w.data, create: w.op === `create` }),
428
+ at: entry.at
429
+ };
430
+ }
431
+ function createsOf(name, args) {
432
+ if (!isObject(args))
433
+ return 0;
434
+ if (name === `records_upsert`)
435
+ return typeof args.id === `string` ? 0 : 1;
436
+ if (name === `records_batch` && Array.isArray(args.writes))
437
+ return args.writes.filter((w) => isObject(w) && w.op !== `delete` && typeof w.id !== `string`).length;
438
+ return 0;
439
+ }
440
+ // packages/eengine/src/synced.ts
441
+ class SyncedRecordStore {
442
+ log;
443
+ transport;
444
+ now;
445
+ listener;
446
+ queue;
447
+ flushing = null;
448
+ again = false;
449
+ awaited = new Set;
450
+ outcomes = new Map;
451
+ synced = new Map;
452
+ constructor(log, transport, now, listener, queue) {
453
+ this.log = log;
454
+ this.transport = transport;
455
+ this.now = now;
456
+ this.listener = listener;
457
+ this.queue = queue;
458
+ }
459
+ static async open(log, transport, now, listener = null) {
460
+ return new SyncedRecordStore(log, transport, now, listener, await log.entries());
461
+ }
462
+ entries() {
463
+ return [...this.queue];
464
+ }
465
+ pendingLabel(app) {
466
+ return outboxPendingLabel2(this.queue, app);
467
+ }
468
+ rows(app) {
469
+ return this.synced.get(app) ?? [];
470
+ }
471
+ visibleRows(app, me) {
472
+ const entries = this.queue.filter((e) => e.appId === app);
473
+ return entries.length === 0 ? this.rows(app) : outboxRows2(this.rows(app), entries, me);
474
+ }
475
+ async submit(entry, online) {
476
+ await this.log.push(entry);
477
+ const awaits = online && !this.queue.some((e) => e.state === `pending`);
478
+ if (awaits)
479
+ this.awaited.add(entry.writeId);
480
+ this.queue.push(entry);
481
+ this.listener?.changed?.();
482
+ if (!awaits)
483
+ return { queued: true };
484
+ await this.flush();
485
+ if (this.flushing)
486
+ await this.flushing;
487
+ this.awaited.delete(entry.writeId);
488
+ const outcome = this.outcomes.get(entry.writeId);
489
+ this.outcomes.delete(entry.writeId);
490
+ return outcome ?? { queued: true };
491
+ }
492
+ async flush() {
493
+ if (this.flushing) {
494
+ this.again = true;
495
+ return;
496
+ }
497
+ this.flushing = this.drain().finally(() => {
498
+ this.flushing = null;
499
+ });
500
+ await this.flushing;
501
+ }
502
+ async drain() {
503
+ for (;; ) {
504
+ const entry = this.queue.find((e) => e.state === `pending`);
505
+ const stop = entry ? await this.replay(entry) : true;
506
+ if (!stop)
507
+ continue;
508
+ const pending = this.queue.some((e) => e.state === `pending`);
509
+ const go = this.again && pending;
510
+ this.again = false;
511
+ if (!go)
512
+ return;
513
+ }
514
+ }
515
+ async replay(entry) {
516
+ const { call, input } = outboxRequest2(entry);
517
+ const pushed = await this.send(entry.appId, call, input);
518
+ const outcome = outboxOutcome2(entry, pushed.result);
519
+ let answer = { queued: true };
520
+ if (outcome === `done`) {
521
+ const at = this.now();
522
+ await this.log.ack(entry.writeId, at);
523
+ this.queue = this.queue.map((e) => e.writeId === entry.writeId ? { ...e, state: `acked`, ackedAt: at } : e);
524
+ answer = { done: pushed.answer ?? null };
525
+ } else if (outcome === `dropped` || outcome === `refused`) {
526
+ await this.log.remove([entry.writeId]);
527
+ this.queue = this.queue.filter((e) => e.writeId !== entry.writeId);
528
+ if (outcome === `refused`)
529
+ answer = { refused: { message: pushed.message ?? null, invalid: pushed.invalid ?? false } };
530
+ }
531
+ if (this.awaited.delete(entry.writeId))
532
+ this.outcomes.set(entry.writeId, answer);
533
+ else if (outcome === `refused`)
534
+ this.listener?.refused?.(entry, outboxVerb2(entry), pushed);
535
+ if (outcome === `done`)
536
+ await this.prune();
537
+ this.listener?.changed?.();
538
+ return outcome === `retry`;
539
+ }
540
+ send(app, call, input) {
541
+ if (this.transport.send)
542
+ return this.transport.send(app, call, input);
543
+ return this.transport.push(app, call, input).then((result) => ({ result }));
544
+ }
545
+ async setRows(app, rows) {
546
+ this.synced.set(app, rows);
547
+ await this.prune();
548
+ }
549
+ async prune() {
550
+ const now = this.now();
551
+ const gone = [];
552
+ for (const app of new Set(this.queue.filter((e) => e.state !== `pending`).map((e) => e.appId))) {
553
+ const rows = this.synced.get(app);
554
+ if (!rows)
555
+ continue;
556
+ const entries = this.queue.filter((e) => e.appId === app);
557
+ const kept = new Set(outboxPrune2(entries, rows, now).map((e) => e.writeId));
558
+ gone.push(...entries.filter((e) => !kept.has(e.writeId)).map((e) => e.writeId));
559
+ }
560
+ if (gone.length === 0)
561
+ return;
562
+ await this.log.remove(gone);
563
+ this.queue = this.queue.filter((e) => !gone.includes(e.writeId));
564
+ this.listener?.changed?.();
565
+ }
566
+ }
567
+ export {
568
+ AGENT_PROVIDERS2 as AGENT_PROVIDERS,
569
+ AppInstance,
570
+ Broker,
571
+ CAPABILITIES2 as CAPABILITIES,
572
+ CAPABILITY_TOOLS2 as CAPABILITY_TOOLS,
573
+ CONSENT_COPY2 as CONSENT_COPY,
574
+ FORBIDDEN_HOST_KEYS2 as FORBIDDEN_HOST_KEYS,
575
+ GRANTS_RECORD_VERSION2 as GRANTS_RECORD_VERSION,
576
+ IDENTITY_KINDS2 as IDENTITY_KINDS,
577
+ LoadError,
578
+ LocalRecordStore2 as LocalRecordStore,
579
+ MIME_BY_EXTENSION2 as MIME_BY_EXTENSION,
580
+ MemoryBlobStore2 as MemoryBlobStore,
581
+ MemoryPersistence2 as MemoryPersistence,
582
+ MemoryRecordStore2 as MemoryRecordStore,
583
+ MemoryVault2 as MemoryVault,
584
+ NETWORK_POLICIES2 as NETWORK_POLICIES,
585
+ PROVIDER_KEYS2 as PROVIDER_KEYS,
586
+ RESERVED_CAPABILITY_NAMES2 as RESERVED_CAPABILITY_NAMES,
587
+ RUNNER_BUNDLE2 as RUNNER_BUNDLE,
588
+ RUNNER_COPY2 as RUNNER_COPY,
589
+ RUNNER_SHELL2 as RUNNER_SHELL,
590
+ STOPPED2 as STOPPED,
591
+ StoreError2 as StoreError,
592
+ SyncedRecordStore,
593
+ agentToolList2 as agentToolList,
594
+ applyBatch2 as applyBatch,
595
+ base64Decode2 as base64Decode,
596
+ base64Encode2 as base64Encode,
597
+ batchOf,
598
+ bridgeCall2 as bridgeCall,
599
+ brokerAuditRow2 as brokerAuditRow,
600
+ brokerDecide2 as brokerDecide,
601
+ capabilityDef2 as capabilityDef,
602
+ capabilityNameValid2 as capabilityNameValid,
603
+ consentAnswer2 as consentAnswer,
604
+ consentSheet2 as consentSheet,
605
+ createsOf,
606
+ engineRecordRefusal2 as engineRecordRefusal,
607
+ engineViewer2 as engineViewer,
608
+ grantWrite2 as grantWrite,
609
+ grantsOnPackage2 as grantsOnPackage,
610
+ grantsRecord2 as grantsRecord,
611
+ lifecycleStep2 as lifecycleStep,
612
+ localDeviceId2 as localDeviceId,
613
+ manageSheet2 as manageSheet,
614
+ mimeFor2 as mimeFor,
615
+ nativeCaller2 as nativeCaller,
616
+ networkAllows2 as networkAllows,
617
+ newNotificationId2 as newNotificationId,
618
+ outboxFlush2 as outboxFlush,
619
+ outboxMode2 as outboxMode,
620
+ outboxOutcome2 as outboxOutcome,
621
+ outboxPendingLabel2 as outboxPendingLabel,
622
+ outboxPrune2 as outboxPrune,
623
+ outboxReflected2 as outboxReflected,
624
+ outboxRequest2 as outboxRequest,
625
+ outboxRows2 as outboxRows,
626
+ outboxVerb2 as outboxVerb,
627
+ outboxWrites2 as outboxWrites,
628
+ packageOf,
629
+ parseCapabilityCall2 as parseCapabilityCall,
630
+ pdfFileName2 as pdfFileName,
631
+ pdfImage2 as pdfImage,
632
+ pdfNumber2 as pdfNumber,
633
+ renderPdf2 as renderPdf,
634
+ runnerConfig2 as runnerConfig,
635
+ runnerFailure2 as runnerFailure,
636
+ runnerHasPermissions2 as runnerHasPermissions,
637
+ runnerPackage2 as runnerPackage,
638
+ runnerToast2 as runnerToast,
639
+ schemaViolation2 as schemaViolation,
640
+ scopeDef2 as scopeDef,
641
+ scopeIdValid2 as scopeIdValid,
642
+ screenKey,
643
+ sniffMime2 as sniffMime,
644
+ toolDef2 as toolDef,
645
+ toolError2 as toolError,
646
+ toolResult2 as toolResult,
647
+ urlOrigin2 as urlOrigin,
648
+ validateHostConfig2 as validateHostConfig,
649
+ validateToolArguments2 as validateToolArguments,
650
+ wrapLines2 as wrapLines
651
+ };
652
+
653
+ //# debugId=4B8F99E4043BD1B764756E2164756E21
654
+ //# sourceMappingURL=index.js.map