apps 0.0.1-beta.89 → 0.0.1-beta.90

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 (55) hide show
  1. package/README.md +27 -10
  2. package/framework-reference.json +1 -1
  3. package/js/{chunk-H6NFR354.js → chunk-36UFTECB.js} +6 -8
  4. package/js/{chunk-I46RIOKQ.js → chunk-5MDA7MKL.js} +14 -13
  5. package/js/{chunk-NQW2E44U.js → chunk-6XQLA5NC.js} +579 -81
  6. package/js/{chunk-6FUJH3T4.js → chunk-7PHHWYV4.js} +6 -5
  7. package/js/{chunk-7Z3NUCTP.js → chunk-DADXWWRZ.js} +24 -6
  8. package/js/{chunk-BZFFXNWA.js → chunk-I5C7FD5Z.js} +1 -1
  9. package/js/{chunk-EKZLPXHK.js → chunk-KUCCHNVY.js} +3 -3
  10. package/js/{chunk-ZK7JDZJS.js → chunk-PYQLOLOC.js} +2 -2
  11. package/js/{chunk-ELSILABS.js → chunk-WMD4NHXZ.js} +113 -73
  12. package/js/{chunk-JJH3MBAM.js → chunk-YNJ5CZMJ.js} +3 -2
  13. package/js/{chunk-5ZVAYXLT.js → chunk-YRGL4QEF.js} +1 -1
  14. package/js/{chunk-GLXEYET6.js → chunk-YWFUWTUJ.js} +12 -7
  15. package/js/client.js +1 -1
  16. package/js/contracts.js +37 -25
  17. package/js/effect.js +8 -9
  18. package/js/graphql.js +10 -11
  19. package/js/host.js +11 -13
  20. package/js/index.js +29 -31
  21. package/js/mcp/effect.js +9 -10
  22. package/js/mcp.js +11 -12
  23. package/js/openapi.js +9 -11
  24. package/js/skills.js +6 -6
  25. package/js/ui/contracts.js +1 -1
  26. package/js/ui/serving.js +5 -6
  27. package/package.json +1 -1
  28. package/runtime.json +1 -1
  29. package/types/apps/src/contracts/app.d.ts +51 -8
  30. package/types/apps/src/contracts/cache.d.ts +1 -1
  31. package/types/apps/src/contracts/context.d.ts +37 -8
  32. package/types/apps/src/contracts/events.d.ts +2 -1
  33. package/types/apps/src/contracts/host.d.ts +800 -4
  34. package/types/apps/src/contracts/operations.d.ts +6 -3
  35. package/types/apps/src/contracts/protocol-version.d.ts +1 -1
  36. package/types/apps/src/contracts/protocols/11.d.ts +1149 -0
  37. package/types/apps/src/contracts/protocols/12.d.ts +3310 -0
  38. package/types/apps/src/contracts/protocols/current.d.ts +4445 -1633
  39. package/types/apps/src/contracts/schedules.d.ts +7 -1
  40. package/types/apps/src/contracts/ui.d.ts +11 -15
  41. package/types/apps/src/contracts/webhooks.d.ts +24 -7
  42. package/types/apps/src/contracts/workflows.d.ts +13 -17
  43. package/types/apps/src/implementation/app.d.ts +41 -14
  44. package/types/apps/src/implementation/cache.d.ts +1 -1
  45. package/types/apps/src/implementation/events.d.ts +6 -1
  46. package/types/apps/src/implementation/failure-detail.d.ts +3 -2
  47. package/types/apps/src/implementation/operations.d.ts +40 -5
  48. package/types/apps/src/implementation/router-catalog.d.ts +4 -0
  49. package/types/apps/src/implementation/schedules.d.ts +39 -8
  50. package/types/apps/src/implementation/ui-serving.d.ts +2 -2
  51. package/types/apps/src/implementation/webhooks.d.ts +15 -6
  52. package/types/apps/src/implementation/workflow-context.d.ts +6 -2
  53. package/types/apps/src/implementation/workflows.d.ts +10 -3
  54. package/types/apps/src/index.d.ts +15 -9
  55. package/js/chunk-F2G534HD.js +0 -285
@@ -1,17 +1,18 @@
1
1
  import {
2
2
  appInvocationFetch
3
- } from "./chunk-5ZVAYXLT.js";
3
+ } from "./chunk-YRGL4QEF.js";
4
4
  import {
5
5
  fromPromise,
6
6
  method,
7
7
  toPromise
8
- } from "./chunk-BZFFXNWA.js";
8
+ } from "./chunk-I5C7FD5Z.js";
9
9
  import {
10
10
  CacheAcquired,
11
11
  CacheEntry,
12
12
  CacheError,
13
- cacheLimits
14
- } from "./chunk-F2G534HD.js";
13
+ cacheLimits,
14
+ scopedSlots
15
+ } from "./chunk-6XQLA5NC.js";
15
16
  import {
16
17
  decoderOf
17
18
  } from "./chunk-GQ33QSNB.js";
@@ -301,7 +302,7 @@ var authorCache = (host, accounts, signal, telemetry, deadline) => {
301
302
  write: service("write", cache.write),
302
303
  invalidate: service("invalidate", cache.invalidate),
303
304
  forAccount: (account) => {
304
- const bound = Object.values(accounts).flatMap((value) => Array.isArray(value) ? value : [value]).find((value) => value.id === account.id);
305
+ const bound = scopedSlots(accounts).flatMap(([, value]) => Array.isArray(value) ? value : [value]).find((value) => value.id === account.id);
305
306
  if (bound === void 0) throw new CacheError({ reason: "invalid" });
306
307
  return scoped(
307
308
  { account: bound.id, method: bound.method, generation: bound.generation },
@@ -2,11 +2,11 @@ import {
2
2
  declaredOperations,
3
3
  nativeOperation,
4
4
  nativeRouter
5
- } from "./chunk-GLXEYET6.js";
5
+ } from "./chunk-YWFUWTUJ.js";
6
6
  import {
7
7
  fromPromise,
8
8
  method
9
- } from "./chunk-BZFFXNWA.js";
9
+ } from "./chunk-I5C7FD5Z.js";
10
10
  import {
11
11
  EmittedEvent,
12
12
  EventName,
@@ -17,7 +17,7 @@ import {
17
17
  normalizePlacements,
18
18
  placementFields,
19
19
  renderPlacement
20
- } from "./chunk-NQW2E44U.js";
20
+ } from "./chunk-6XQLA5NC.js";
21
21
  import {
22
22
  decoderOf,
23
23
  isSchema,
@@ -271,8 +271,8 @@ var makeEmitter = (input) => ({
271
271
  const filters = Schema_exports.decodeUnknownSync(Schema_exports.Struct(declared.filters))(
272
272
  options.filters ?? {}
273
273
  );
274
- const account = options.account ?? input.sourceAccount ?? (input.accounts.length === 1 ? input.accounts[0] : void 0) ?? null;
275
- if (account === null && input.accounts.length > 1)
274
+ const account = options.account ?? input.sourceAccount ?? (input.attributable.length === 1 ? input.attributable[0] : void 0) ?? null;
275
+ if (account === null && input.attributable.length > 1)
276
276
  throw new TypeError(
277
277
  "This invocation has several accounts; name the one the event came from with { account }"
278
278
  );
@@ -361,9 +361,12 @@ function adaptDefinition(definition) {
361
361
  );
362
362
  if (match === void 0)
363
363
  throw new Error("A schedule must reference a mutation in this app's tools");
364
+ if (schedule.scope === "app" && match.operation.approval !== void 0)
365
+ throw new Error("An app schedule must reference a mutation without an approval");
364
366
  return [
365
367
  name,
366
368
  {
369
+ ...schedule.scope === "app" ? { scope: "app" } : {},
367
370
  timing: Schema_exports.decodeUnknownSync(ScheduleTiming)(schedule.timing),
368
371
  input: Schema_exports.decodeUnknownSync(JsonValue)(schedule.input),
369
372
  tool: match.name
@@ -380,7 +383,22 @@ function adaptDefinition(definition) {
380
383
  ...schedules
381
384
  };
382
385
  }
386
+ function scopedSlots(requirements) {
387
+ if ("accounts" in requirements)
388
+ throw new TypeError(
389
+ "Declare account requirements by scope: user: { accounts } for each caller's accounts, app: { accounts } for the app's own"
390
+ );
391
+ const app = requirements.app?.accounts ?? {};
392
+ const user = requirements.user?.accounts ?? {};
393
+ for (const name of Object.keys(app))
394
+ if (Object.hasOwn(user, name))
395
+ throw new TypeError(
396
+ `The requirement ${JSON.stringify(name)} is declared as both an app and a user account; name them differently`
397
+ );
398
+ return { app, user };
399
+ }
383
400
  var defineApp = (requirements, definition) => {
401
+ const accounts = scopedSlots(requirements);
384
402
  if (typeof definition !== "function") rejectCatalogs(definition);
385
403
  const evaluate = typeof definition === "function" ? definition : async () => definition;
386
404
  const factory = fromPromise(evaluate, "factory");
@@ -398,7 +416,7 @@ var defineApp = (requirements, definition) => {
398
416
  if (iconsProblem !== void 0)
399
417
  throw new TypeError(`The app's icons are invalid: ${iconsProblem}`);
400
418
  const native = {
401
- accounts: requirements.accounts,
419
+ accounts,
402
420
  ...events === void 0 ? {} : { events },
403
421
  ...requirements.icons === void 0 || requirements.icons.length === 0 ? {} : { icons: requirements.icons },
404
422
  evaluate: (context) => factory(context).pipe(Effect_exports.map((value2) => adaptDefinition(value2)))
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ProviderError,
3
3
  maxUpstreamMessageLength
4
- } from "./chunk-F2G534HD.js";
4
+ } from "./chunk-6XQLA5NC.js";
5
5
  import {
6
6
  owned
7
7
  } from "./chunk-QWQM3CLH.js";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  getWithReads
3
- } from "./chunk-6FUJH3T4.js";
3
+ } from "./chunk-7PHHWYV4.js";
4
4
  import {
5
5
  fromPromise,
6
6
  method,
7
7
  toPromise
8
- } from "./chunk-BZFFXNWA.js";
8
+ } from "./chunk-I5C7FD5Z.js";
9
9
  import {
10
10
  CacheError
11
- } from "./chunk-F2G534HD.js";
11
+ } from "./chunk-6XQLA5NC.js";
12
12
  import {
13
13
  wrap
14
14
  } from "./chunk-GQ33QSNB.js";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  fixedRouter
3
- } from "./chunk-I46RIOKQ.js";
3
+ } from "./chunk-5MDA7MKL.js";
4
4
  import {
5
5
  nativeOperation,
6
6
  operationDeclaration,
7
7
  routerDeclaration
8
- } from "./chunk-GLXEYET6.js";
8
+ } from "./chunk-YWFUWTUJ.js";
9
9
 
10
10
  // src/implementation/protocol-operations.ts
11
11
  var protocolOperations = (operations, kinds = {}) => {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  authorCache,
3
3
  unavailableCache
4
- } from "./chunk-6FUJH3T4.js";
4
+ } from "./chunk-7PHHWYV4.js";
5
5
  import {
6
6
  accountSecrets,
7
7
  boundFailureMessage,
@@ -12,10 +12,10 @@ import {
12
12
  parseSkillLoadFailed,
13
13
  readCatalog,
14
14
  routerSkills
15
- } from "./chunk-I46RIOKQ.js";
15
+ } from "./chunk-5MDA7MKL.js";
16
16
  import {
17
17
  appInvocationFetch
18
- } from "./chunk-5ZVAYXLT.js";
18
+ } from "./chunk-YRGL4QEF.js";
19
19
  import {
20
20
  folderSkillsEffect
21
21
  } from "./chunk-XBG7HHXC.js";
@@ -26,12 +26,12 @@ import {
26
26
  makeEmitter,
27
27
  toEffectApp,
28
28
  withPlacements
29
- } from "./chunk-7Z3NUCTP.js";
29
+ } from "./chunk-DADXWWRZ.js";
30
30
  import {
31
31
  declaredOperations,
32
32
  locate,
33
33
  nativeOperation
34
- } from "./chunk-GLXEYET6.js";
34
+ } from "./chunk-YWFUWTUJ.js";
35
35
  import {
36
36
  accountProviderError,
37
37
  appCode,
@@ -39,7 +39,7 @@ import {
39
39
  httpProviderError,
40
40
  parseProviderError,
41
41
  toPromise
42
- } from "./chunk-BZFFXNWA.js";
42
+ } from "./chunk-I5C7FD5Z.js";
43
43
  import {
44
44
  AccountCheckResult,
45
45
  DeclaredProvider,
@@ -91,7 +91,7 @@ import {
91
91
  reservedTablePrefix,
92
92
  sqlBindingsLimit,
93
93
  workflowDurationMillis
94
- } from "./chunk-NQW2E44U.js";
94
+ } from "./chunk-6XQLA5NC.js";
95
95
  import {
96
96
  AppSkills,
97
97
  SkillFile
@@ -514,19 +514,25 @@ var inputInvalid = (error, input) => {
514
514
  };
515
515
 
516
516
  // src/implementation/webhooks.ts
517
+ var withoutUser = ({
518
+ user: _user,
519
+ ...context
520
+ }) => context;
517
521
  var safe = (work, error) => Effect_exports.suspend(work).pipe(
518
522
  Effect_exports.catchCause(
519
523
  (cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(error)
520
524
  )
521
525
  );
522
- var dispatchWebhook = (definition, command, context, accounts) => Effect_exports.gen(function* () {
526
+ var sourceRequirement = (account) => "app" in account ? { scope: "app", name: account.app } : { scope: "user", name: account.user };
527
+ var dispatchWebhook = (definition, command, context, slots) => Effect_exports.gen(function* () {
523
528
  const hooks = definition.webhooks ?? {};
524
529
  if (command.operation === "webhooks") {
525
530
  return yield* Effect_exports.forEach(
526
531
  Object.entries(hooks),
527
532
  ([name, hook2]) => safe(
528
533
  () => Effect_exports.gen(function* () {
529
- if (!Object.hasOwn(accounts, hook2.account))
534
+ const source2 = sourceRequirement(hook2.account);
535
+ if (!Object.hasOwn(slots[source2.scope], source2.name))
530
536
  return yield* new HostDeclarationInvalid();
531
537
  const describe = (schema) => {
532
538
  const imported = importedJsonSchema(schema);
@@ -546,7 +552,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
546
552
  };
547
553
  return yield* Schema_exports.decodeUnknownEffect(HostedWebhook)({
548
554
  name,
549
- account: hook2.account,
555
+ account: source2.name,
550
556
  configSchema,
551
557
  ...setup === void 0 ? {} : { setup }
552
558
  });
@@ -557,14 +563,15 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
557
563
  }
558
564
  const hook = Object.hasOwn(hooks, command.name) ? hooks[command.name] : void 0;
559
565
  if (hook === void 0) return yield* new HostOperationNotFound();
560
- const selected = accounts[hook.account];
561
- const source = Array.isArray(selected) ? selected.find((account2) => account2.id === command.sourceAccount) : selected;
562
- if (source === void 0 || source.id !== command.sourceAccount)
563
- return yield* new HostInputInvalid();
564
- const bound = context.accounts[hook.account];
565
- const account = Array.isArray(bound) ? bound.find(
566
- (value) => typeof value === "object" && value !== null && "id" in value && value.id === source.id
567
- ) : bound;
566
+ const source = sourceRequirement(hook.account);
567
+ const scope = source.scope === "app" ? context.app : context.user;
568
+ if (scope === void 0) return yield* new HostAccountsInvalid();
569
+ const bound = Object.hasOwn(scope.accounts, source.name) ? scope.accounts[source.name] : void 0;
570
+ const account = (Array.isArray(bound) ? bound : [bound]).find(
571
+ (value) => typeof value === "object" && value !== null && "id" in value && value.id === command.sourceAccount
572
+ );
573
+ if (account === void 0) return yield* new HostInputInvalid();
574
+ const hookContext = source.scope === "app" ? withoutUser(context) : context;
568
575
  const config = yield* safe(
569
576
  () => Schema_exports.decodeUnknownEffect(hook.config)(command.config),
570
577
  new HostInputInvalid()
@@ -581,7 +588,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
581
588
  callbackUrl: command.callbackUrl,
582
589
  secret: command.secret
583
590
  };
584
- const invoke = (callback, value) => safe(() => callback(context, value), new HostOperationFailed());
591
+ const invoke = (callback, value) => safe(() => callback(hookContext, value), new HostOperationFailed());
585
592
  if (command.operation === "webhook-complete") {
586
593
  if (hook.setup === void 0) return yield* new HostInputInvalid();
587
594
  return yield* safe(
@@ -1153,7 +1160,7 @@ function providerDeclaration(provider) {
1153
1160
  `Account provider "${provider.name}" has an invalid declaration`
1154
1161
  );
1155
1162
  }
1156
- function requirements(slots, sql, events, icons) {
1163
+ function declaredSlots(slots) {
1157
1164
  return Effect_exports.gen(function* () {
1158
1165
  const accounts = /* @__PURE__ */ new Map();
1159
1166
  for (const [slot, selection] of Object.entries(slots)) {
@@ -1164,8 +1171,13 @@ function requirements(slots, sql, events, icons) {
1164
1171
  ...provider.health === void 0 ? {} : { health: true }
1165
1172
  });
1166
1173
  }
1174
+ return Object.fromEntries(accounts);
1175
+ });
1176
+ }
1177
+ function requirements(slots, sql, events, icons) {
1178
+ return Effect_exports.gen(function* () {
1167
1179
  return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
1168
- accounts: Object.fromEntries(accounts),
1180
+ accounts: { app: yield* declaredSlots(slots.app), user: yield* declaredSlots(slots.user) },
1169
1181
  capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
1170
1182
  ...sql ? { sql: true } : {},
1171
1183
  ...events === void 0 || Object.keys(events).length === 0 ? {} : {
@@ -1200,55 +1212,65 @@ function withoutGrants({ hosts: _hosts, ...provider }) {
1200
1212
  )
1201
1213
  };
1202
1214
  }
1215
+ function bindScope(slots, declarations, selected) {
1216
+ return Effect_exports.gen(function* () {
1217
+ if (Object.keys(selected).some((slot) => !Object.hasOwn(slots, slot))) {
1218
+ return yield* Effect_exports.fail(new HostAccountsInvalid());
1219
+ }
1220
+ const bound = /* @__PURE__ */ new Map();
1221
+ for (const [slot, selection] of Object.entries(slots)) {
1222
+ const requirement = Object.hasOwn(declarations, slot) ? declarations[slot] : void 0;
1223
+ const supplied = Object.hasOwn(selected, slot) ? selected[slot] : void 0;
1224
+ if (requirement === void 0 || supplied === void 0)
1225
+ return yield* Effect_exports.fail(new HostAccountsInvalid());
1226
+ const provider = selection instanceof ManyAccounts ? selection.provider : selection;
1227
+ const many = selection instanceof ManyAccounts;
1228
+ if (many !== Array.isArray(supplied)) return yield* Effect_exports.fail(new HostAccountsInvalid());
1229
+ const accounts = Array.isArray(supplied) ? supplied : [supplied];
1230
+ const ids = /* @__PURE__ */ new Set();
1231
+ const values = [];
1232
+ for (const account of accounts) {
1233
+ if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
1234
+ ids.add(account.id);
1235
+ if (canonical(withoutGrants(account.provider)) !== canonical(withoutGrants(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
1236
+ return yield* Effect_exports.fail(new HostAccountsInvalid());
1237
+ const method = provider.auth[account.method];
1238
+ if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1239
+ const fields = yield* Schema_exports.decodeUnknownEffect(
1240
+ method._tag === "secrets" ? method.fields : method.response
1241
+ )(account.fields);
1242
+ const granted = Object.hasOwn(account.provider.auth, account.method) ? account.provider.auth[account.method]?.request : void 0;
1243
+ values.push(withPlacements({ id: account.id, method: account.method, fields }, granted));
1244
+ }
1245
+ if (many) bound.set(slot, values);
1246
+ else {
1247
+ const account = values[0];
1248
+ if (account === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1249
+ bound.set(slot, account);
1250
+ }
1251
+ }
1252
+ return Object.fromEntries(bound);
1253
+ });
1254
+ }
1203
1255
  function bindAccounts(slots, declarations, context) {
1204
1256
  return safe2(
1205
1257
  () => Effect_exports.gen(function* () {
1206
1258
  const selected = yield* Schema_exports.decodeUnknownEffect(ResolvedAccounts)(
1207
1259
  Redacted_exports.value(context.accounts)
1208
1260
  );
1209
- if (Object.keys(selected).some((slot) => !Object.hasOwn(slots, slot))) {
1210
- return yield* Effect_exports.fail(new HostAccountsInvalid());
1211
- }
1212
- const bound = /* @__PURE__ */ new Map();
1213
- for (const [slot, selection] of Object.entries(slots)) {
1214
- const requirement = declarations.accounts[slot];
1215
- const supplied = Object.hasOwn(selected, slot) ? selected[slot] : void 0;
1216
- if (requirement === void 0 || supplied === void 0)
1217
- return yield* Effect_exports.fail(new HostAccountsInvalid());
1218
- const provider = selection instanceof ManyAccounts ? selection.provider : selection;
1219
- const many = selection instanceof ManyAccounts;
1220
- if (many !== Array.isArray(supplied))
1221
- return yield* Effect_exports.fail(new HostAccountsInvalid());
1222
- const accounts = Array.isArray(supplied) ? supplied : [supplied];
1223
- const ids = /* @__PURE__ */ new Set();
1224
- const values = [];
1225
- for (const account of accounts) {
1226
- if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
1227
- ids.add(account.id);
1228
- if (canonical(withoutGrants(account.provider)) !== canonical(withoutGrants(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
1229
- return yield* Effect_exports.fail(new HostAccountsInvalid());
1230
- const method = provider.auth[account.method];
1231
- if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1232
- const fields = yield* Schema_exports.decodeUnknownEffect(
1233
- method._tag === "secrets" ? method.fields : method.response
1234
- )(account.fields);
1235
- const granted = Object.hasOwn(account.provider.auth, account.method) ? account.provider.auth[account.method]?.request : void 0;
1236
- values.push(
1237
- withPlacements({ id: account.id, method: account.method, fields }, granted)
1238
- );
1239
- }
1240
- if (many) bound.set(slot, values);
1241
- else {
1242
- const account = values[0];
1243
- if (account === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1244
- bound.set(slot, account);
1245
- }
1246
- }
1247
- return { accounts: Object.fromEntries(bound) };
1261
+ const app = yield* bindScope(slots.app, declarations.accounts.app, selected.app);
1262
+ if (selected.user === void 0) return { app: { accounts: app } };
1263
+ const user = yield* bindScope(slots.user, declarations.accounts.user, selected.user);
1264
+ return { app: { accounts: app }, user: { accounts: user } };
1248
1265
  }),
1249
1266
  new HostAccountsInvalid()
1250
1267
  );
1251
1268
  }
1269
+ var userAccountIds = (bound) => Object.values(bound.user?.accounts ?? {}).flatMap(
1270
+ (selected) => (Array.isArray(selected) ? selected : [selected]).map(
1271
+ (account) => account.id
1272
+ )
1273
+ );
1252
1274
  var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
1253
1275
  Effect_exports.sync(() => {
1254
1276
  const controller = new AbortController();
@@ -1451,14 +1473,19 @@ function dispatch(app, request, context, signal, emitted) {
1451
1473
  fetch: yield* appInvocationFetch(fetching.signal),
1452
1474
  elicit: makeElicit(delivery, invocationSignal, telemetry.context)
1453
1475
  };
1454
- const accountIds = Object.values(bound.accounts).flatMap(
1455
- (selected) => (Array.isArray(selected) ? selected : [selected]).map(
1456
- (account) => account.id
1457
- )
1458
- );
1476
+ const attributable = userAccountIds(bound);
1477
+ const accountIds = [
1478
+ ...Object.values(bound.app.accounts).flatMap(
1479
+ (selected) => (Array.isArray(selected) ? selected : [selected]).map(
1480
+ (account) => account.id
1481
+ )
1482
+ ),
1483
+ ...attributable
1484
+ ];
1459
1485
  const emitter = (sourceAccount) => makeEmitter({
1460
1486
  events: native.events ?? {},
1461
1487
  accounts: accountIds,
1488
+ attributable,
1462
1489
  ...sourceAccount === void 0 ? {} : { sourceAccount },
1463
1490
  emitted
1464
1491
  });
@@ -1592,14 +1619,15 @@ function dispatch(app, request, context, signal, emitted) {
1592
1619
  {
1593
1620
  files,
1594
1621
  cache: bound.cache,
1595
- accounts: bound.accounts,
1622
+ app: bound.app,
1623
+ ...bound.user === void 0 ? {} : { user: bound.user },
1596
1624
  workflows: workflowControls,
1597
1625
  signal: bound.signal,
1598
1626
  fetch: bound.fetch,
1599
1627
  sql: session2.writer,
1600
1628
  events: emitter("sourceAccount" in request ? request.sourceAccount : void 0)
1601
1629
  },
1602
- Redacted_exports.value(context.accounts)
1630
+ native.accounts
1603
1631
  );
1604
1632
  }
1605
1633
  const toolName = request.operation === "call" ? request.tool : request.name;
@@ -1724,16 +1752,28 @@ function dispatch(app, request, context, signal, emitted) {
1724
1752
  }
1725
1753
  function checkAccount(slots, declared, requirement, context, signal, deadline) {
1726
1754
  return Effect_exports.gen(function* () {
1727
- const selection = Object.hasOwn(slots, requirement) ? slots[requirement] : void 0;
1728
- const slot = Object.hasOwn(declared.accounts, requirement) ? declared.accounts[requirement] : void 0;
1755
+ const scope = Object.hasOwn(slots.app, requirement) ? "app" : Object.hasOwn(slots.user, requirement) ? "user" : void 0;
1756
+ if (scope === void 0) return yield* new HostAccountsInvalid();
1757
+ const selection = slots[scope][requirement];
1758
+ const slot = Object.hasOwn(declared.accounts[scope], requirement) ? declared.accounts[scope][requirement] : void 0;
1729
1759
  if (selection === void 0 || slot === void 0) return yield* new HostAccountsInvalid();
1730
1760
  const provider = selection instanceof ManyAccounts ? selection.provider : selection;
1731
1761
  const health = provider.health;
1732
1762
  if (health === void 0) return yield* new HostOperationNotFound();
1733
- const { accounts } = yield* bindAccounts(
1734
- { [requirement]: provider },
1735
- { accounts: { [requirement]: { ...slot, cardinality: "one" } } },
1736
- context
1763
+ const accounts = yield* safe2(
1764
+ () => Effect_exports.gen(function* () {
1765
+ const selected = yield* Schema_exports.decodeUnknownEffect(ResolvedAccounts)(
1766
+ Redacted_exports.value(context.accounts)
1767
+ );
1768
+ const supplied = selected[scope];
1769
+ if (supplied === void 0) return yield* new HostAccountsInvalid();
1770
+ return yield* bindScope(
1771
+ { [requirement]: provider },
1772
+ { [requirement]: { ...slot, cardinality: "one" } },
1773
+ supplied
1774
+ );
1775
+ }),
1776
+ new HostAccountsInvalid()
1737
1777
  ).pipe(Effect_exports.withSpan("app.accounts.bind"));
1738
1778
  const account = accounts[requirement];
1739
1779
  if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
@@ -14,8 +14,9 @@ import {
14
14
  // src/contracts/ui.ts
15
15
  var UiContext = Schema_exports.Struct({
16
16
  deployment: Schema_exports.NonEmptyString,
17
- profile: Schema_exports.optional(Schema_exports.NonEmptyString),
18
- expectedProfileRevision: Schema_exports.optional(Schema_exports.Int)
17
+ accounts: Schema_exports.optional(
18
+ Schema_exports.Record(Schema_exports.NonEmptyString, Schema_exports.Array(Schema_exports.NonEmptyString))
19
+ )
19
20
  });
20
21
  var UiOperation = Schema_exports.Struct({
21
22
  ...UiContext.fields,
@@ -5,7 +5,7 @@ import {
5
5
  networkRefusalHeader,
6
6
  networkRefusalStatus,
7
7
  supportedFetchOptions
8
- } from "./chunk-F2G534HD.js";
8
+ } from "./chunk-6XQLA5NC.js";
9
9
  import {
10
10
  invocationFetch
11
11
  } from "./chunk-QWQM3CLH.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  fromPromise
3
- } from "./chunk-BZFFXNWA.js";
3
+ } from "./chunk-I5C7FD5Z.js";
4
4
  import {
5
5
  HostedTool,
6
6
  RouterKey,
7
7
  RouterMeta,
8
8
  reservedRouterKeys
9
- } from "./chunk-NQW2E44U.js";
9
+ } from "./chunk-6XQLA5NC.js";
10
10
  import {
11
11
  decoderOf,
12
12
  schemaArgument
@@ -47,10 +47,13 @@ var approvedOperation = (operation, approval) => {
47
47
  value: (context) => fromPromise(async () => approval(context), "approval")()
48
48
  });
49
49
  };
50
- var withApproval = (operation, approval) => ({
51
- ...operation,
52
- [NativeOperation]: approvedOperation(operation[NativeOperation], approval)
53
- });
50
+ var withApproval = (operation, approval) => (
51
+ // SAFETY: `Approved` is a type-only mark; the native operation now carries the approval.
52
+ {
53
+ ...operation,
54
+ [NativeOperation]: approvedOperation(operation[NativeOperation], approval)
55
+ }
56
+ );
54
57
  var toolAnnotations = (operation) => nativeOperation(operation)?.annotations;
55
58
  var make = (kind, options, run) => operationDeclaration({
56
59
  ...operationOptions({ ...options, input: schemaArgument(options.input, `The ${kind} input`) }),
@@ -62,7 +65,9 @@ var make = (kind, options, run) => operationDeclaration({
62
65
  run: (context, input) => fromPromise(run, "handler")(context, input)
63
66
  });
64
67
  var query = (options, run) => make("query", options, run);
65
- var mutation = (options, run) => make("mutation", options, run);
68
+ function mutation(options, run) {
69
+ return make("mutation", options, run);
70
+ }
66
71
 
67
72
  // src/implementation/router.ts
68
73
  var routerDeclaration = (node) => ({
package/js/client.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  UiContext,
4
4
  UiDeploymentChanged,
5
5
  UiFailed
6
- } from "./chunk-JJH3MBAM.js";
6
+ } from "./chunk-YNJ5CZMJ.js";
7
7
  import {
8
8
  AsyncResult_exports,
9
9
  AtomRegistry_exports,