apps 0.0.1-beta.1 → 0.0.1-beta.100

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 (211) hide show
  1. package/README.md +112 -72
  2. package/framework-reference.json +1 -1
  3. package/js/browser-XIPJGLH2.js +65 -0
  4. package/js/chunk-2CURR5Y7.js +264 -0
  5. package/js/chunk-2LSGC7XY.js +42 -0
  6. package/js/{chunk-YEJOQEII.js → chunk-4PIQKACY.js} +65 -10
  7. package/js/chunk-4UPC36ZL.js +5185 -0
  8. package/js/{chunk-4LPG6RCH.js → chunk-4X2UI4R2.js} +7 -27
  9. package/js/chunk-5C6RAGAS.js +335 -0
  10. package/js/chunk-62NVUKED.js +39 -0
  11. package/js/chunk-74H25C4X.js +95 -0
  12. package/js/chunk-7HG422GB.js +90 -0
  13. package/js/chunk-7STIP5CS.js +171 -0
  14. package/js/{chunk-QKHR7BMF.js → chunk-ACQXVKVQ.js} +87 -51
  15. package/js/{chunk-OHRT55C4.js → chunk-DILSCQPJ.js} +226 -265
  16. package/js/chunk-ILYCJ3HV.js +449 -0
  17. package/js/chunk-K6TSCYAO.js +712 -0
  18. package/js/{chunk-EVJUVWN2.js → chunk-KLSEU35Y.js} +463 -218
  19. package/js/chunk-OD3KFKZD.js +1617 -0
  20. package/js/chunk-OWN3DP2W.js +88 -0
  21. package/js/{chunk-ZTFQHGEB.js → chunk-PBGPES67.js} +3 -5
  22. package/js/chunk-QI66R4FP.js +786 -0
  23. package/js/chunk-RN4YB4JT.js +1922 -0
  24. package/js/{chunk-ZCAMUXSG.js → chunk-URKOTNDA.js} +795 -177
  25. package/js/{chunk-NCYXZN2G.js → chunk-UVL56Z6E.js} +390 -23
  26. package/js/{chunk-2HHMABB6.js → chunk-VAI3EVCS.js} +700 -78
  27. package/js/chunk-VCYWAA4N.js +49 -0
  28. package/js/{chunk-HDJH3RPR.js → chunk-YDW7DX3A.js} +4 -4
  29. package/js/chunk-YWVISRZD.js +268 -0
  30. package/js/{chunk-FW5HBOIK.js → chunk-ZKDXML77.js} +19272 -18299
  31. package/js/client.js +148 -100
  32. package/js/contracts.js +208 -24
  33. package/js/effect.js +18 -19
  34. package/js/es-DIULA3ZF.js +39371 -0
  35. package/js/graphql.js +62 -58
  36. package/js/host.js +83 -60
  37. package/js/index.js +381 -263
  38. package/js/mcp/effect.js +21 -21
  39. package/js/mcp.js +117 -74
  40. package/js/openapi.js +4613 -42691
  41. package/js/react.js +2 -3
  42. package/js/skills/effect.js +6 -4
  43. package/js/skills.js +233 -70
  44. package/js/storage/facet.js +1 -540
  45. package/js/ui/auth/contracts.js +8 -9
  46. package/js/ui/auth.js +16 -14
  47. package/js/ui/contracts.js +9 -8
  48. package/js/ui/serving.js +8609 -227
  49. package/package.json +3 -8
  50. package/runtime.json +1 -1
  51. package/types/app-cache/src/contracts/cache.d.ts +60 -2
  52. package/types/app-cache/src/index.d.ts +92 -2
  53. package/types/app-data/src/contracts/database.d.ts +33 -6
  54. package/types/apps/src/contracts/api-response-error.d.ts +4 -0
  55. package/types/apps/src/contracts/app.d.ts +63 -17
  56. package/types/apps/src/contracts/cache.d.ts +24 -1
  57. package/types/apps/src/contracts/context.d.ts +60 -17
  58. package/types/apps/src/contracts/elicitation.d.ts +23 -7
  59. package/types/apps/src/contracts/events.d.ts +94 -0
  60. package/types/apps/src/contracts/failure.d.ts +54 -0
  61. package/types/apps/src/contracts/graphql.d.ts +2 -1
  62. package/types/apps/src/contracts/host.d.ts +1325 -534
  63. package/types/apps/src/contracts/icons.d.ts +28 -0
  64. package/types/apps/src/contracts/live.d.ts +2 -0
  65. package/types/apps/src/contracts/mcp.d.ts +97 -20
  66. package/types/apps/src/contracts/network.d.ts +120 -0
  67. package/types/apps/src/contracts/openapi-compile.d.ts +82 -3
  68. package/types/apps/src/contracts/openapi-document.d.ts +1 -1
  69. package/types/apps/src/contracts/openapi.d.ts +51 -9
  70. package/types/apps/src/contracts/operations.d.ts +14 -12
  71. package/types/apps/src/contracts/placement.d.ts +102 -0
  72. package/types/apps/src/contracts/protocol-version.d.ts +6 -0
  73. package/types/apps/src/contracts/protocols/1.d.ts +2241 -0
  74. package/types/apps/src/contracts/protocols/10.d.ts +1450 -0
  75. package/types/apps/src/contracts/protocols/11.d.ts +1149 -0
  76. package/types/apps/src/contracts/protocols/12.d.ts +3310 -0
  77. package/types/apps/src/contracts/protocols/2.d.ts +711 -0
  78. package/types/apps/src/contracts/protocols/3.d.ts +776 -0
  79. package/types/apps/src/contracts/protocols/4.d.ts +1306 -0
  80. package/types/apps/src/contracts/protocols/5.d.ts +1200 -0
  81. package/types/apps/src/contracts/protocols/6.d.ts +1629 -0
  82. package/types/apps/src/contracts/protocols/7.d.ts +1785 -0
  83. package/types/apps/src/contracts/protocols/8.d.ts +1182 -0
  84. package/types/apps/src/contracts/protocols/9.d.ts +1104 -0
  85. package/types/apps/src/contracts/protocols/current.d.ts +6857 -0
  86. package/types/apps/src/contracts/protocols/oauth-6.d.ts +74 -0
  87. package/types/apps/src/contracts/protocols/oauth.d.ts +134 -0
  88. package/types/apps/src/contracts/provider-error.d.ts +9 -0
  89. package/types/apps/src/contracts/provider.d.ts +140 -10
  90. package/types/apps/src/contracts/router.d.ts +59 -0
  91. package/types/apps/src/contracts/schedules.d.ts +7 -1
  92. package/types/apps/src/contracts/schema.d.ts +21 -0
  93. package/types/apps/src/contracts/shared-catalog.d.ts +11 -0
  94. package/types/apps/src/contracts/skills.d.ts +60 -14
  95. package/types/apps/src/contracts/sql.d.ts +63 -0
  96. package/types/apps/src/contracts/ui-auth.d.ts +6 -14
  97. package/types/apps/src/contracts/ui.d.ts +70 -30
  98. package/types/apps/src/contracts/webhooks.d.ts +24 -7
  99. package/types/apps/src/contracts/workflows.d.ts +89 -36
  100. package/types/apps/src/facet.d.ts +4 -5
  101. package/types/apps/src/graphql.d.ts +1 -3
  102. package/types/apps/src/host.d.ts +5 -0
  103. package/types/apps/src/implementation/account-router.d.ts +13 -0
  104. package/types/apps/src/implementation/app.d.ts +44 -16
  105. package/types/apps/src/implementation/authoring.d.ts +25 -5
  106. package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
  107. package/types/apps/src/implementation/cache.d.ts +32 -3
  108. package/types/apps/src/implementation/catalog-cache.d.ts +43 -5
  109. package/types/apps/src/implementation/elicitation.d.ts +18 -15
  110. package/types/apps/src/implementation/events.d.ts +64 -0
  111. package/types/apps/src/implementation/failure-detail.d.ts +48 -0
  112. package/types/apps/src/implementation/graphql-catalog.d.ts +4 -7
  113. package/types/apps/src/implementation/graphql.d.ts +4 -3
  114. package/types/apps/src/implementation/input-problems.d.ts +6 -2
  115. package/types/apps/src/implementation/invocation-timing.d.ts +18 -0
  116. package/types/apps/src/implementation/live.d.ts +2 -2
  117. package/types/apps/src/implementation/mcp-call.d.ts +6 -5
  118. package/types/apps/src/implementation/mcp-catalog.d.ts +7 -8
  119. package/types/apps/src/implementation/mcp-client.d.ts +49 -25
  120. package/types/apps/src/implementation/mcp-tools.d.ts +2 -1
  121. package/types/apps/src/implementation/mcp.d.ts +52 -25
  122. package/types/apps/src/implementation/network.d.ts +16 -0
  123. package/types/apps/src/implementation/openapi-compile.d.ts +30 -8
  124. package/types/apps/src/implementation/openapi-document.d.ts +46 -21
  125. package/types/apps/src/implementation/openapi-names.d.ts +23 -0
  126. package/types/apps/src/implementation/openapi-request.d.ts +10 -3
  127. package/types/apps/src/implementation/openapi-source.d.ts +30 -8
  128. package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
  129. package/types/apps/src/implementation/operations.d.ts +84 -10
  130. package/types/apps/src/implementation/optimistic.d.ts +1 -1
  131. package/types/apps/src/implementation/placement.d.ts +60 -0
  132. package/types/apps/src/implementation/protocol-operations.d.ts +6 -4
  133. package/types/apps/src/implementation/provider-error.d.ts +28 -1
  134. package/types/apps/src/implementation/provider.d.ts +26 -6
  135. package/types/apps/src/implementation/query-commit.d.ts +1 -1
  136. package/types/apps/src/implementation/router-catalog.d.ts +227 -0
  137. package/types/apps/src/implementation/router.d.ts +78 -0
  138. package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
  139. package/types/apps/src/implementation/schedules.d.ts +39 -8
  140. package/types/apps/src/implementation/schema.d.ts +111 -15
  141. package/types/apps/src/implementation/skills.d.ts +18 -24
  142. package/types/apps/src/implementation/sql.d.ts +71 -0
  143. package/types/apps/src/implementation/swagger-client.d.ts +28 -0
  144. package/types/apps/src/implementation/ui-account-notice.d.ts +9 -0
  145. package/types/apps/src/implementation/ui-auth.d.ts +12 -6
  146. package/types/apps/src/implementation/ui-client.d.ts +3 -3
  147. package/types/apps/src/implementation/ui-document.d.ts +5 -0
  148. package/types/apps/src/implementation/ui-errors.d.ts +1 -1
  149. package/types/apps/src/implementation/ui-serving.d.ts +31 -12
  150. package/types/apps/src/implementation/ui-watch.d.ts +1 -1
  151. package/types/apps/src/implementation/upstream-error.d.ts +7 -0
  152. package/types/apps/src/implementation/webhooks.d.ts +15 -6
  153. package/types/apps/src/implementation/workflow-context.d.ts +17 -5
  154. package/types/apps/src/implementation/workflows.d.ts +11 -4
  155. package/types/apps/src/index.d.ts +71 -21
  156. package/types/apps/src/mcp.d.ts +25 -5
  157. package/types/apps/src/openapi.d.ts +11 -6
  158. package/types/apps/src/react.d.ts +1 -1
  159. package/types/apps/src/skills.d.ts +13 -8
  160. package/types/apps/src/ui-auth.d.ts +2 -2
  161. package/types/apps/src/ui-serving.d.ts +1 -1
  162. package/types/telemetry/src/app-records.d.ts +42 -0
  163. package/types/telemetry/src/browser-operations.d.ts +7 -4
  164. package/types/telemetry/src/browser.d.ts +8 -3
  165. package/types/telemetry/src/config.d.ts +2 -2
  166. package/types/telemetry/src/index.d.ts +2 -1
  167. package/types/telemetry/src/layer.d.ts +10 -4
  168. package/types/telemetry/src/measurements.d.ts +1 -1
  169. package/types/telemetry/src/ownership.d.ts +60 -0
  170. package/types/telemetry/src/recorded-failure.d.ts +29 -0
  171. package/types/telemetry/src/relay.d.ts +16 -6
  172. package/types/telemetry/src/span-attributes.d.ts +17 -1
  173. package/types/telemetry/src/transport.d.ts +8 -1
  174. package/types/utils/src/api-error.d.ts +55 -0
  175. package/types/utils/src/connection-failure.d.ts +33 -0
  176. package/types/utils/src/legacy-keys.d.ts +20 -0
  177. package/types/utils/src/recorded-message.d.ts +18 -0
  178. package/types/utils/src/schema-definitions.d.ts +13 -0
  179. package/types/utils/src/user-facing-error.d.ts +83 -0
  180. package/js/chunk-6IIO4NPI.js +0 -29
  181. package/js/chunk-6YBRWRK3.js +0 -160
  182. package/js/chunk-BMOIAIVR.js +0 -138
  183. package/js/chunk-FZJOYIZO.js +0 -19
  184. package/js/chunk-G7IE6BKC.js +0 -224
  185. package/js/chunk-IHQ4ML7K.js +0 -2193
  186. package/js/chunk-KOXMLKTM.js +0 -1288
  187. package/js/chunk-M6ZRRIBI.js +0 -877
  188. package/js/chunk-PLCMJREA.js +0 -590
  189. package/js/chunk-PZ36XMXW.js +0 -93
  190. package/js/chunk-RBAC33PQ.js +0 -267
  191. package/js/chunk-SATWJKN6.js +0 -34
  192. package/js/chunk-SWPD52J7.js +0 -35
  193. package/js/chunk-TE4KO4HI.js +0 -47
  194. package/js/chunk-W7D7WVSY.js +0 -18
  195. package/js/chunk-X7SFGU4Q.js +0 -280
  196. package/js/chunk-ZJWDMTE3.js +0 -63
  197. package/js/mcp/stdio.js +0 -128
  198. package/types/app-data/src/implementation/cursor.d.ts +0 -10
  199. package/types/app-data/src/implementation/index-key.d.ts +0 -7
  200. package/types/app-data/src/implementation/promise.d.ts +0 -68
  201. package/types/app-data/src/implementation/range.d.ts +0 -8
  202. package/types/app-data/src/implementation/schema.d.ts +0 -33
  203. package/types/app-data/src/implementation/sqlite.d.ts +0 -11
  204. package/types/app-data/src/index.d.ts +0 -4
  205. package/types/apps/src/contracts/dynamic-tools.d.ts +0 -13
  206. package/types/apps/src/contracts/storage.d.ts +0 -68
  207. package/types/apps/src/implementation/account-operations.d.ts +0 -151
  208. package/types/apps/src/implementation/dynamic-tools.d.ts +0 -8
  209. package/types/apps/src/implementation/mcp-stdio.d.ts +0 -4
  210. package/types/apps/src/implementation/storage.d.ts +0 -13
  211. package/types/apps/src/mcp-stdio.d.ts +0 -8
package/README.md CHANGED
@@ -4,34 +4,36 @@ Author apps with ordinary TypeScript and Promises. Framework operations use
4
4
  Effect v4 internally. The root export contains declarations and schemas;
5
5
  protocol helpers have separate entry points.
6
6
 
7
- The Executor package starts at `0.0.1-beta.0`. The first npm beta is being
8
- prepared; `latest` belongs to the earlier package and is not this framework.
9
- Once the beta is published, install it with `npm install --save-exact apps@beta`.
10
- For local testing, install the tarball made by `bun run pack` in this directory.
7
+ Install the exact version your Executor host runs: agents read it with the
8
+ Executor app's `framework.release`, and `executor apps framework` prints it. Run
9
+ `npm install --save-exact apps@<version>` and declare the same version in the
10
+ app's `package.json`. Do not install `apps@latest`; that tag is an unrelated,
11
+ earlier package. The package includes `framework-reference.json`, generated from
12
+ these declarations. The Executor app's `app-authoring` skill is the authoring
13
+ guide; [Author an app](https://v2.executor.sh/docs/author-an-app) summarizes
14
+ it. In this repository, `bun run pack` builds a local tarball.
11
15
 
12
16
  ```ts
13
17
  import { defineApp } from "apps";
14
- import { mcpOperations } from "apps/mcp";
18
+ import { mcpRouter } from "apps/mcp";
15
19
 
16
- export default defineApp({ accounts: {} }, async ({ signal }) => ({
17
- ...(await mcpOperations({
20
+ export default defineApp({}, async ({ signal }) => ({
21
+ tools: await mcpRouter({
18
22
  url: "https://mcp.deepwiki.com/mcp",
19
23
  ...(signal === undefined ? {} : { signal }),
20
- })),
24
+ }),
21
25
  }));
22
26
  ```
23
27
 
24
- | Import | Helper | App dependency |
25
- | ---------------- | ------------------- | --------------------------- |
26
- | `apps/mcp` | `mcpOperations` | `@modelcontextprotocol/sdk` |
27
- | `apps/mcp/stdio` | `stdioOperations` | `@modelcontextprotocol/sdk` |
28
- | `apps/graphql` | `graphqlOperations` | `graphql` |
29
- | `apps/openapi` | `openapiOperations` | None |
28
+ | Import | Helper | App dependency |
29
+ | -------------- | ------------------------ | --------------------------- |
30
+ | `apps/mcp` | `mcpRouter`, `mcpHealth` | `@modelcontextprotocol/sdk` |
31
+ | `apps/graphql` | `graphqlRouter` | `graphql` |
32
+ | `apps/openapi` | `liveOpenapiRouter` | None |
30
33
 
31
34
  MCP and GraphQL are optional peers. Subpath imports isolate their module graphs;
32
- optional peers keep unused libraries out of the dependency installation. The
33
- MCP HTTP entry point does not import the stdio process adapter. Stdio requires
34
- a host with process support.
35
+ optional peers keep unused libraries out of the dependency installation. Apps
36
+ reach MCP servers over HTTP; they cannot start local processes.
35
37
 
36
38
  `defineApp` declares behavior, not a name. Package identity lives in
37
39
  `package.json.name`; the host separately names each installed copy.
@@ -39,24 +41,25 @@ a host with process support.
39
41
  Declare the needed peer in the deployed app's `package.json`, for example:
40
42
 
41
43
  ```json
42
- { "name": "deepwiki", "dependencies": { "@modelcontextprotocol/sdk": "1.30.0" } }
44
+ { "name": "deepwiki", "dependencies": { "@modelcontextprotocol/sdk": "1.32.1" } }
43
45
  ```
44
46
 
45
47
  Product runtimes compile authored source and declared dependencies inside workerd,
46
- then retain the executable Worker modules. Declare `apps` in `package.json` to
47
- select its npm version for both server and browser code. Use an exact version to
48
- keep rebuilds repeatable. Apps with no `apps` dependency use the host's framework.
48
+ then retain the executable Worker modules. Every app declares the exact `apps`
49
+ version in `package.json`; it selects the framework for both server and browser
50
+ code and keeps rebuilds repeatable. A build without it fails and names the
51
+ version the host ships.
49
52
  In this repository, playground workspaces use `"apps": "workspace:*"` for development;
50
- replace that workspace reference with a released version before deployment.
53
+ replace that workspace reference with a released version before deploying.
51
54
 
52
- `liveOpenapiOperations` reads an OpenAPI document through `ctx.cache`. Generated
55
+ `liveOpenapiRouter` reads an OpenAPI document through `ctx.cache`. Generated
53
56
  imports retain a source URL, allowed origin, and static credential bindings in
54
57
  `openapi.json`. The framework compiles a revision on a cache miss. It writes each
55
58
  operation and shared schema before publishing the current revision. A warm call
56
59
  reads that revision and the requested operation's schema dependencies. It does
57
- not download, parse, or read the full catalog. `openapiOperations` remains the
60
+ not download, parse, or read the full catalog. `openapiRouter` remains the
58
61
  lower-level helper for already normalized metadata.
59
- `parameterDefaults` binds path, query or header values to the selected account.
62
+ `parameterDefaults` binds path, query or header values to the account.
60
63
  Those parameters become optional and publish their value as the schema `default`;
61
64
  an explicit value still wins.
62
65
 
@@ -68,45 +71,67 @@ Accounts bind at execution time. Live documents cannot change credential
68
71
  placement or send credentials to another origin. Editing generated source and
69
72
  redeploying is required to change those static choices.
70
73
 
71
- Authenticated templates use `provider.many()` and `accountOperations` from `apps`:
74
+ Requirements are declared by scope. `user: { accounts }` holds each caller's
75
+ own accounts, read as `ctx.user.accounts`; `app: { accounts }` holds the app's
76
+ own accounts, which people who can edit the app link for everyone, read as
77
+ `ctx.app.accounts`. A requirement name is used once across both. Contexts of the
78
+ `"app"` scope, such as `MutationContext<typeof requirements, "app">`, have no
79
+ `user`: app schedules (`appCron`, `appInterval`), webhooks whose `account` is
80
+ `{ app: "..." }` and the workflows they start run without a caller. App
81
+ schedules also accept a mutation whose handler declares no parameters, unless
82
+ the call passes explicit type arguments: their third, the context, defaults to
83
+ the caller's. A
84
+ handler that declares its context without a type gets the caller's, with
85
+ `ctx.user`, as a tool's does; app schedules reject it. User
86
+ schedules (`userCron`, `userInterval`) run once for each member who enables them,
87
+ as them. `{ accounts }` requirements and `ctx.accounts` are removed.
88
+
89
+ Authenticated templates use a `provider.many()` user requirement and
90
+ `accountRouter` from `apps`. A factory also runs without a caller for app-scope
91
+ work, so `ctx.user` may be undefined there:
72
92
 
73
93
  ```ts
74
- export default defineApp({ accounts: { service: provider.many() } }, async ({ accounts, signal }) =>
75
- accountOperations(
76
- accounts.service,
77
- (account) =>
78
- mcpOperations({
79
- url: "https://example.com/mcp",
80
- headers: { Authorization: "Bearer " + account.fields.token },
81
- signal,
82
- }),
83
- { signal },
84
- ),
94
+ export default defineApp(
95
+ { user: { accounts: { service: provider.many() } } },
96
+ async ({ user, signal }) => ({
97
+ tools: await accountRouter(
98
+ user?.accounts.service ?? [],
99
+ (account) =>
100
+ mcpRouter({
101
+ url: "https://example.com/mcp",
102
+ account,
103
+ headers: { Authorization: "Bearer " + account.fields.token },
104
+ signal,
105
+ }),
106
+ { signal },
107
+ ),
108
+ }),
85
109
  );
86
110
  ```
87
111
 
88
- MCP and GraphQL helpers accept `cache: ctx.cache.forAccount(account)` (or
89
- `ctx.cache` for a public source). They return `{ dynamicTools }`, cache remote
112
+ MCP and GraphQL helpers take the account their headers come from, and accept
113
+ `cache: ctx.cache`; an account's catalog is kept in that account's scope and
114
+ credentials never enter its key. They return a dynamic router, cache remote
90
115
  metadata, and compile only the selected tool. The defaults are five minutes fresh
91
116
  plus five minutes stale. Use `freshFor` / `staleFor` to change the windows, or
92
117
  `revalidate: true` to await a refresh. Tool results are never cached.
93
118
 
94
119
  Each combined tool takes `{ accountId, input }`. `input` keeps the upstream shape;
95
- `accountId` must identify a selected account that exposes that tool. Discovery
120
+ `accountId` must identify one of the caller's accounts that exposes that tool. Discovery
96
121
  and validation remain specific to each account. An empty selection returns no
97
- tools. This helper also works with OpenAPI, GraphQL and stdio operations.
122
+ tools. This helper also works with OpenAPI and GraphQL operations.
98
123
 
99
124
  Contracts live in `src/contracts/`; native operations live in `src/implementation/`.
100
125
  Promise conversion happens at the public entry points. `apps/mcp/effect` exposes
101
126
  the native HTTP discovery operation for host-side import probing.
102
127
 
103
128
  Helpers are ordinary app libraries. The SDK still builds and invokes one app
104
- model with the configured account selections; there is no protocol dispatcher.
105
- Existing retained builds keep their bundled code until a new deployment.
129
+ model with the accounts each operation runs with; there is no protocol dispatcher.
130
+ Existing retained builds keep their bundled code until the next deploy.
106
131
 
107
132
  The packaged runtime uses host protocol 1. A package missing that runtime or using
108
133
  an unsupported protocol fails at build time; it is never replaced silently with
109
- the host's framework. An unsuccessful update preserves the active deployment.
134
+ the host's framework. An unsuccessful update preserves the active version.
110
135
  Beta compatibility is checked with an earlier package fixture, not a promise to
111
136
  support all historical versions indefinitely.
112
137
 
@@ -116,7 +141,8 @@ returns `approved`, `denied`, or `user-approval`. It receives `toolName`, decode
116
141
  `toolInput`, and `signal`. Reuse a policy function across tools or attach it when
117
142
  composing generated tools. There is no app-level policy.
118
143
  The framework enforces the decision before the selected tool body.
119
- Human approval delivery is separate; Executor SDK call/resume persists the pending invocation. See [tool approvals](../../notes/app-policies.md).
144
+ Human approval delivery is separate; Executor SDK call/resume persists the pending invocation.
145
+ See [Tools and approvals](https://v2.executor.sh/docs/concepts/tools-and-approvals).
120
146
 
121
147
  ## Browser UI
122
148
 
@@ -166,28 +192,26 @@ Use the Promise client methods for one-time reads and explicit writes.
166
192
 
167
193
  The product host supplies authentication and binds the browser to one configured
168
194
  app. No app ID, account token or Executor API key belongs in UI code. New
169
- activations reload open app pages. See [the full example](../../playground/demo-apps/live-inbox/ui/main.tsx)
170
- and [hosting notes](../../notes/app-ui.md).
195
+ activations reload open app pages. The `live-inbox` example in `framework-reference.json` is a complete app with a UI.
171
196
 
172
197
  ## Webhooks
173
198
 
174
- Expose `webhooks: { issueOpened }` beside queries and mutations. Each definition
199
+ Expose `webhooks: { issueOpened }` beside `tools`. Each definition
175
200
  has an `account` requirement, `config` and `state` schemas, and async `register`,
176
201
  `handle`, and `unregister` callbacks. Register and unregister must be idempotent;
177
202
  handle must verify the provider signature before acting.
178
203
 
179
204
  The SDK creates durable subscriptions with `executor.webhooks.create`. A
180
- subscription pins its deployment and saved account IDs while resolving fresh
205
+ subscription pins its app version and saved account IDs while resolving fresh
181
206
  credentials on each invocation. `.many()` sources use one subscription per
182
207
  selected source account. Local, self-host and cloud use the same author API.
183
- See [the lifecycle and management API](../../notes/webhooks.md) and
184
- [the GitHub/Gmail example](../../playground/demo-apps/issue-mail/webhooks.ts).
208
+ The app-authoring skill's `webhooks.md` covers the lifecycle and examples.
185
209
 
186
210
  Providers without a webhook API can use
187
211
  `setup: { instructions: "...", signingSecret: "executor" }`
188
212
  instead of `register` and `unregister`. The private setup page collects the
189
213
  `state` schema and the signing secret. Agents get a setup link and safe status
190
- through the normal management API. See [manual setup](../../notes/webhooks.md#manual-registration).
214
+ through the normal management API.
191
215
 
192
216
  ## Workflows
193
217
 
@@ -201,9 +225,7 @@ Start and inspect runs through `executor.apps.workflowRuns`. Inside an app,
201
225
  queries can inspect `ctx.workflows`; mutations and webhooks can also start and
202
226
  terminate runs. Workflow execution has no live `elicit` capability.
203
227
 
204
- See [workflow semantics](../../notes/app-workflows.md) for replay, idempotency,
205
- self-host recovery and v1 limits, and the
206
- [repository report example](../../playground/demo-apps/workflow-report/) for a full app.
228
+ The app-authoring skill's `workflows.md` covers replay, idempotency and limits.
207
229
 
208
230
  Local and self-host products run authored apps in Alchemy/workerd, using the
209
231
  same Worker build format and app-data facets as Cloud. Host filesystem and
@@ -218,7 +240,7 @@ private data; it also includes the current credential fingerprint. Use the
218
240
  shared cache for public metadata that is identical across accounts.
219
241
 
220
242
  ```ts
221
- const projects = await ctx.cache.forAccount(ctx.accounts.service).get({
243
+ const projects = await ctx.cache.forAccount(ctx.user.accounts.service).get({
222
244
  key: ["projects", region],
223
245
  schema: array(object({ id: string(), name: string() })),
224
246
  freshFor: "1 minute",
@@ -243,39 +265,57 @@ errors are explicit. Background refreshes have a 30-second deadline.
243
265
  bounded JSON batches with a retention duration. These support immutable pieces
244
266
  that must be stored before a manifest becomes visible.
245
267
 
246
- `dynamicTools({ list, resolve })` separates descriptions from executable
247
- operations. `list()` returns tool metadata with qualified names such as
248
- `queries.getProject`. `resolve(name)` returns a query/mutation declaration or
249
- `undefined`. The host validates input and applies approval policy after resolving
250
- an operation. `accountOperations` preserves this separation. Static operations
251
- can run without resolving the source; listings reject duplicate names.
252
-
253
- Assign the resolver to the app's `dynamicTools` field. The helper returns only
254
- `list` and `resolve`, never static query or mutation maps. Both static maps are
255
- optional, so an app can contain only dynamic tools.
268
+ ## Routers
269
+
270
+ An app's `tools` is a router. Keys form tool paths, and routers nest like tRPC's:
271
+ `router({ health, issues: router({ list, close }, { description }) })` exposes
272
+ `health`, `issues.list` and `issues.close`. Each query or mutation keeps its own
273
+ kind; names carry no `queries.` or `mutations.` prefix. Router options are
274
+ `title`, `description`, `instructions`, `icons` and `tags`. Instructions become a
275
+ skill named `tools` for the root router and `tools-<path>` below it, such as
276
+ `tools-issues`. Paths other than lowercase letters and digits get a slug and a
277
+ hash of the path, so names never collide. An authored skill with the same name
278
+ replaces the generated one. `router(source, options)` overrides a source's
279
+ metadata. Keys `__proto__`, `constructor` and `prototype` are reserved, and an
280
+ mutation can be mounted at only one path.
281
+
282
+ Protocol helpers return routers, so an app mounts several sources under keys.
283
+ `mcpRouter` takes its title, description, icons and instructions from the
284
+ server, and `liveOpenapiRouter` from the document's `info` and tags. `openapiRouter`
285
+ and `graphqlRouter` carry no source metadata. A nested router that fails to load is reported on its own catalog entry;
286
+ the app's other tools still load. The root failing fails discovery.
287
+
288
+ `dynamicRouter({ list, resolve })` separates descriptions from executable
289
+ operations. `list()` returns tool metadata with names relative to the router,
290
+ such as `getProject`; names may contain dots. `resolve(name)` returns a
291
+ query/mutation declaration or `undefined`. The host validates input and applies
292
+ approval policy after resolving an operation. `accountRouter` preserves this
293
+ separation. Static operations run without resolving a source; listings reject
294
+ duplicate names.
256
295
 
257
296
  ```ts
258
297
  export default defineApp(
259
- { accounts: {} },
298
+ {},
260
299
  {
261
- dynamicTools: dynamicTools({
300
+ tools: dynamicRouter({
262
301
  list: async () => [
263
302
  {
264
- name: "queries.ping",
303
+ name: "ping",
265
304
  description: "Return pong",
266
305
  inputSchema: { type: "object", properties: {} },
267
306
  readOnly: true,
268
307
  },
269
308
  ],
270
309
  resolve: async (name) =>
271
- name === "queries.ping" ? query({ input: object({}) }, async () => "pong") : undefined,
310
+ name === "ping" ? query({ input: object({}) }, async () => "pong") : undefined,
272
311
  }),
273
312
  },
274
313
  );
275
314
  ```
276
315
 
277
- Names include `queries.` or `mutations.`. `list` describes available tools;
278
- `resolve` returns the matching query or mutation declaration.
316
+ Mark queries with `readOnly: true`; other listed tools are mutations. `list`
317
+ describes available tools; `resolve` returns the matching declaration. An
318
+ optional `meta()` returns the router's title, description and instructions.
279
319
 
280
320
  `ctx.cache.revalidate(options)` takes the same options as `get`, but always
281
321
  awaits a refresh. Concurrent refreshes share a load. The previous value stays