@gjermundgaraba/effect-actions 0.20.0 → 0.21.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 (321) hide show
  1. package/README.md +19 -41
  2. package/dist/Action.d.mts +140 -46
  3. package/dist/Action.mjs +87 -42
  4. package/dist/ActionCli.d.mts +69 -33
  5. package/dist/ActionCli.mjs +51 -32
  6. package/dist/ActionHttp.d.mts +69 -35
  7. package/dist/ActionHttp.mjs +75 -23
  8. package/dist/ActionMcp.d.mts +56 -22
  9. package/dist/ActionMcp.mjs +94 -69
  10. package/dist/ActionRpc.d.mts +222 -55
  11. package/dist/ActionRpc.mjs +299 -46
  12. package/dist/ActionToolkit.d.mts +22 -5
  13. package/dist/ActionToolkit.mjs +36 -12
  14. package/dist/Authentication.d.mts +42 -10
  15. package/dist/Authentication.mjs +37 -30
  16. package/dist/Event.d.mts +370 -0
  17. package/dist/Event.mjs +103 -0
  18. package/dist/Testing.mjs +1 -1
  19. package/dist/Webhook.d.mts +146 -0
  20. package/dist/Webhook.mjs +72 -0
  21. package/dist/authentication/provider.d.mts +35 -10
  22. package/dist/authentication/provider.mjs +1 -1
  23. package/dist/authentication/refusal.mjs +2 -2
  24. package/dist/cli/commands.d.mts +9 -5
  25. package/dist/cli/commands.mjs +84 -33
  26. package/dist/contract/ast.mjs +4 -1
  27. package/dist/contract/authorizer.d.mts +8 -0
  28. package/dist/contract/authorizer.mjs +20 -0
  29. package/dist/contract/call.d.mts +9 -6
  30. package/dist/contract/call.mjs +48 -6
  31. package/dist/contract/callback.d.mts +7 -0
  32. package/dist/contract/callback.mjs +27 -0
  33. package/dist/contract/caller.d.mts +13 -2
  34. package/dist/contract/caller.mjs +22 -3
  35. package/dist/contract/canonical.mjs +10 -0
  36. package/dist/contract/codec.d.mts +9 -0
  37. package/dist/contract/codec.mjs +9 -0
  38. package/dist/contract/codes.mjs +81 -0
  39. package/dist/contract/declared.mjs +25 -9
  40. package/dist/contract/digest.mjs +6 -0
  41. package/dist/contract/errors.d.mts +9 -3
  42. package/dist/contract/errors.mjs +1 -1
  43. package/dist/contract/feed.d.mts +127 -0
  44. package/dist/contract/feed.mjs +249 -0
  45. package/dist/contract/hub.d.mts +94 -0
  46. package/dist/contract/hub.mjs +133 -0
  47. package/dist/contract/idempotency.d.mts +47 -0
  48. package/dist/contract/idempotency.mjs +99 -0
  49. package/dist/contract/implementation.d.mts +73 -47
  50. package/dist/contract/implementation.mjs +92 -58
  51. package/dist/contract/input-check.d.mts +15 -0
  52. package/dist/contract/input-check.mjs +16 -0
  53. package/dist/contract/lease.mjs +28 -0
  54. package/dist/contract/listed.d.mts +4 -0
  55. package/dist/contract/listed.mjs +22 -0
  56. package/dist/contract/log.d.mts +41 -0
  57. package/dist/contract/log.mjs +144 -0
  58. package/dist/contract/names.mjs +14 -4
  59. package/dist/contract/occurrence.d.mts +29 -0
  60. package/dist/contract/occurrence.mjs +45 -0
  61. package/dist/contract/pages.d.mts +13 -0
  62. package/dist/contract/pages.mjs +39 -0
  63. package/dist/contract/progress.d.mts +26 -0
  64. package/dist/contract/progress.mjs +72 -0
  65. package/dist/contract/push.d.mts +20 -0
  66. package/dist/contract/push.mjs +96 -0
  67. package/dist/contract/receiving.d.mts +29 -0
  68. package/dist/contract/receiving.mjs +42 -0
  69. package/dist/contract/recent.mjs +12 -0
  70. package/dist/contract/reported.mjs +16 -0
  71. package/dist/contract/serving.mjs +63 -0
  72. package/dist/contract/status.mjs +14 -5
  73. package/dist/contract/stream.d.mts +34 -0
  74. package/dist/contract/stream.mjs +31 -0
  75. package/dist/contract/subscribe.d.mts +45 -0
  76. package/dist/contract/subscribe.mjs +50 -0
  77. package/dist/contract/transient.mjs +28 -0
  78. package/dist/contract/watch.d.mts +18 -0
  79. package/dist/contract/watch.mjs +105 -0
  80. package/dist/contract/webhooks.d.mts +42 -0
  81. package/dist/contract/webhooks.mjs +53 -0
  82. package/dist/http/client.d.mts +37 -12
  83. package/dist/http/client.mjs +51 -12
  84. package/dist/http/events.d.mts +56 -0
  85. package/dist/http/events.mjs +102 -0
  86. package/dist/http/placed.d.mts +36 -0
  87. package/dist/http/placed.mjs +71 -0
  88. package/dist/http/schema-errors.mjs +1 -1
  89. package/dist/http/streamed.d.mts +21 -0
  90. package/dist/http/streamed.mjs +94 -0
  91. package/dist/http/watch.mjs +50 -0
  92. package/dist/mcp/bridge.mjs +283 -0
  93. package/dist/mcp/client.d.mts +30 -97
  94. package/dist/mcp/client.mjs +59 -132
  95. package/dist/mcp/events.mjs +142 -0
  96. package/dist/mcp/progress.mjs +34 -0
  97. package/dist/mcp/protocol.mjs +39 -13
  98. package/dist/mcp/reply.d.mts +79 -0
  99. package/dist/mcp/reply.mjs +99 -0
  100. package/dist/mcp/request.d.mts +40 -0
  101. package/dist/mcp/request.mjs +51 -0
  102. package/dist/mcp/watch.mjs +115 -0
  103. package/dist/rpc/watch.mjs +39 -0
  104. package/dist/stdio/console.mjs +13 -5
  105. package/dist/testing/memory.d.mts +1 -1
  106. package/dist/testing/memory.mjs +3 -3
  107. package/dist/webhook/address.mjs +47 -0
  108. package/dist/webhook/attempt.mjs +65 -0
  109. package/dist/webhook/receiver.mjs +67 -0
  110. package/dist/webhook/signing.mjs +28 -0
  111. package/dist/webhook/stored.mjs +57 -0
  112. package/dist/webhook/subscriptions.mjs +342 -0
  113. package/docs/Action-failures.md +2 -2
  114. package/docs/Action-streams.md +115 -0
  115. package/docs/Action.md +58 -124
  116. package/docs/ActionCli-failures.md +1 -2
  117. package/docs/ActionCli.md +83 -88
  118. package/docs/ActionHttp-failures.md +3 -3
  119. package/docs/ActionHttp.md +90 -70
  120. package/docs/ActionMcp-failures.md +2 -1
  121. package/docs/ActionMcp.md +120 -92
  122. package/docs/ActionRpc-events.md +126 -0
  123. package/docs/ActionRpc-failures.md +1 -2
  124. package/docs/ActionRpc.md +108 -79
  125. package/docs/ActionToolkit-failures.md +1 -2
  126. package/docs/ActionToolkit.md +33 -90
  127. package/docs/Authentication-advanced.md +52 -60
  128. package/docs/Authentication-failures.md +5 -4
  129. package/docs/Authentication.md +23 -58
  130. package/docs/Event-failures.md +15 -0
  131. package/docs/Event.md +281 -0
  132. package/docs/README.md +51 -82
  133. package/docs/Testing-failures.md +1 -5
  134. package/docs/Testing.md +126 -86
  135. package/docs/Webhook-failures.md +8 -0
  136. package/docs/Webhook.md +319 -0
  137. package/docs/setup-failures.md +2 -3
  138. package/docs/setup.md +32 -52
  139. package/examples/README.md +12 -37
  140. package/examples/assistant/README.md +21 -26
  141. package/examples/assistant/src/agent.ts +66 -24
  142. package/examples/assistant/src/cli.ts +7 -4
  143. package/examples/assistant/src/commands.ts +9 -4
  144. package/examples/assistant/src/identity/Identity.ts +5 -4
  145. package/examples/assistant/src/identity/authorize.ts +13 -5
  146. package/examples/assistant/src/identity/handlers.ts +3 -2
  147. package/examples/assistant/src/identity/permissions.ts +9 -3
  148. package/examples/assistant/src/platform/tasks-file.ts +15 -11
  149. package/examples/assistant/src/scripted.ts +7 -4
  150. package/examples/assistant/src/tasks/Tasks.ts +20 -6
  151. package/examples/assistant/src/tasks/handlers.ts +9 -5
  152. package/examples/assistant/src/tasks/store.ts +38 -11
  153. package/examples/assistant/src/toolkit.ts +11 -7
  154. package/examples/assistant/test/commands.test.ts +53 -27
  155. package/examples/assistant/test/identity/identity.test.ts +27 -11
  156. package/examples/assistant/test/platform/tasks-file.test.ts +39 -23
  157. package/examples/assistant/test/tasks/tasks.test.ts +62 -34
  158. package/examples/assistant/test/toolkit.test.ts +104 -75
  159. package/examples/build-events/README.md +83 -0
  160. package/examples/build-events/src/Api.ts +27 -0
  161. package/examples/build-events/src/Rpc.ts +26 -0
  162. package/examples/build-events/src/builds/Builds.ts +108 -0
  163. package/examples/build-events/src/builds/events.ts +54 -0
  164. package/examples/build-events/src/builds/handlers.ts +58 -0
  165. package/examples/build-events/src/builds/log.ts +30 -0
  166. package/examples/build-events/src/builds/status.ts +28 -0
  167. package/examples/build-events/src/builds/store.ts +130 -0
  168. package/examples/build-events/src/cli.ts +18 -0
  169. package/examples/build-events/src/commands.ts +32 -0
  170. package/examples/build-events/src/deploys/Deploys.ts +44 -0
  171. package/examples/build-events/src/deploys/approvers.ts +55 -0
  172. package/examples/build-events/src/deploys/events.ts +32 -0
  173. package/examples/build-events/src/deploys/handlers.ts +38 -0
  174. package/examples/build-events/src/identity/Identity.ts +29 -0
  175. package/examples/build-events/src/identity/members.ts +7 -0
  176. package/examples/build-events/src/identity/verifier.ts +22 -0
  177. package/examples/build-events/src/notifier/Notices.ts +26 -0
  178. package/examples/build-events/src/notifier/routes.ts +71 -0
  179. package/examples/build-events/src/notifier.ts +48 -0
  180. package/examples/build-events/src/routes.ts +71 -0
  181. package/examples/build-events/src/server.ts +62 -0
  182. package/examples/build-events/test/builds/events.test.ts +68 -0
  183. package/examples/build-events/test/builds/log.test.ts +71 -0
  184. package/examples/build-events/test/builds/progress.test.ts +57 -0
  185. package/examples/build-events/test/builds/status.test.ts +42 -0
  186. package/examples/build-events/test/commands.test.ts +103 -0
  187. package/examples/build-events/test/deploys/events.test.ts +52 -0
  188. package/examples/build-events/test/http.test.ts +95 -0
  189. package/examples/build-events/test/notifier.test.ts +80 -0
  190. package/examples/build-events/test/routes.test.ts +96 -0
  191. package/examples/build-events/test/rpc.test.ts +84 -0
  192. package/examples/build-events/test/support/as.ts +8 -0
  193. package/examples/build-events/test/support/memory.ts +43 -0
  194. package/examples/build-events/test/webhooks.test.ts +143 -0
  195. package/examples/kitchen-sink/README.md +178 -166
  196. package/examples/kitchen-sink/src/Actions.ts +11 -3
  197. package/examples/kitchen-sink/src/Api.ts +12 -6
  198. package/examples/kitchen-sink/src/Rpc.ts +7 -5
  199. package/examples/kitchen-sink/src/admin/Admin.ts +21 -10
  200. package/examples/kitchen-sink/src/admin/authenticate.ts +8 -4
  201. package/examples/kitchen-sink/src/admin/authorize.ts +13 -5
  202. package/examples/kitchen-sink/src/admin/grants.ts +5 -3
  203. package/examples/kitchen-sink/src/admin/handlers.ts +9 -5
  204. package/examples/kitchen-sink/src/agent.ts +14 -6
  205. package/examples/kitchen-sink/src/assistant/Assistant.ts +21 -15
  206. package/examples/kitchen-sink/src/assistant/conversations.ts +14 -9
  207. package/examples/kitchen-sink/src/assistant/demo-model.ts +2 -2
  208. package/examples/kitchen-sink/src/assistant/handlers.ts +42 -22
  209. package/examples/kitchen-sink/src/attachments/Attachments.ts +6 -6
  210. package/examples/kitchen-sink/src/attachments/download.ts +7 -6
  211. package/examples/kitchen-sink/src/attachments/handlers.ts +9 -4
  212. package/examples/kitchen-sink/src/attachments/store.ts +25 -18
  213. package/examples/kitchen-sink/src/browser.ts +10 -4
  214. package/examples/kitchen-sink/src/cli.ts +28 -12
  215. package/examples/kitchen-sink/src/config.ts +1 -1
  216. package/examples/kitchen-sink/src/identity/Identity.ts +24 -10
  217. package/examples/kitchen-sink/src/identity/authenticate.ts +19 -11
  218. package/examples/kitchen-sink/src/identity/authorize.ts +14 -4
  219. package/examples/kitchen-sink/src/identity/directory.ts +16 -7
  220. package/examples/kitchen-sink/src/identity/handlers.ts +1 -0
  221. package/examples/kitchen-sink/src/identity/members.ts +7 -2
  222. package/examples/kitchen-sink/src/identity/quota.ts +23 -20
  223. package/examples/kitchen-sink/src/issues/Issues.ts +91 -15
  224. package/examples/kitchen-sink/src/issues/assistant.ts +4 -2
  225. package/examples/kitchen-sink/src/issues/events.ts +46 -0
  226. package/examples/kitchen-sink/src/issues/export.ts +35 -0
  227. package/examples/kitchen-sink/src/issues/guide.ts +4 -3
  228. package/examples/kitchen-sink/src/issues/handlers.ts +20 -7
  229. package/examples/kitchen-sink/src/issues/store.ts +156 -67
  230. package/examples/kitchen-sink/src/issues/write-limit.ts +44 -18
  231. package/examples/kitchen-sink/src/memory.ts +11 -2
  232. package/examples/kitchen-sink/src/ops.ts +10 -5
  233. package/examples/kitchen-sink/src/request-policy.ts +21 -9
  234. package/examples/kitchen-sink/src/routes.ts +67 -27
  235. package/examples/kitchen-sink/src/sdk.ts +22 -12
  236. package/examples/kitchen-sink/src/seed.ts +15 -9
  237. package/examples/kitchen-sink/src/server.ts +24 -10
  238. package/examples/kitchen-sink/src/stdio.ts +9 -3
  239. package/examples/kitchen-sink/src/workspaces/Workspaces.ts +10 -7
  240. package/examples/kitchen-sink/src/workspaces/handlers.ts +3 -2
  241. package/examples/kitchen-sink/src/workspaces/registry.ts +16 -10
  242. package/examples/kitchen-sink/src/workspaces/tenant.ts +12 -5
  243. package/examples/kitchen-sink/test/admin/admin.test.ts +38 -23
  244. package/examples/kitchen-sink/test/assistant/assistant.test.ts +471 -299
  245. package/examples/kitchen-sink/test/attachments/attachments.test.ts +135 -94
  246. package/examples/kitchen-sink/test/identity/identity.test.ts +110 -82
  247. package/examples/kitchen-sink/test/identity/session.test.ts +65 -43
  248. package/examples/kitchen-sink/test/issues/assistant.test.ts +50 -31
  249. package/examples/kitchen-sink/test/issues/events.test.ts +273 -0
  250. package/examples/kitchen-sink/test/issues/export.test.ts +120 -0
  251. package/examples/kitchen-sink/test/issues/issues.test.ts +105 -75
  252. package/examples/kitchen-sink/test/request-policy.test.ts +108 -47
  253. package/examples/kitchen-sink/test/routes.test.ts +102 -57
  254. package/examples/kitchen-sink/test/support/as.ts +9 -0
  255. package/examples/kitchen-sink/test/support/scripted.ts +6 -5
  256. package/examples/kitchen-sink/test/support/services.ts +17 -0
  257. package/examples/live-rpc/README.md +33 -35
  258. package/examples/live-rpc/src/Rpc.ts +9 -5
  259. package/examples/live-rpc/src/browser.ts +39 -11
  260. package/examples/live-rpc/src/chat/Chat.ts +30 -16
  261. package/examples/live-rpc/src/chat/authorize.ts +2 -1
  262. package/examples/live-rpc/src/chat/events.ts +74 -0
  263. package/examples/live-rpc/src/chat/handlers.ts +13 -5
  264. package/examples/live-rpc/src/chat/room.ts +9 -5
  265. package/examples/live-rpc/src/chat/store.ts +51 -14
  266. package/examples/live-rpc/src/client.ts +22 -5
  267. package/examples/live-rpc/src/identity/Identity.ts +3 -3
  268. package/examples/live-rpc/src/identity/verifier.ts +8 -4
  269. package/examples/live-rpc/src/page.ts +58 -12
  270. package/examples/live-rpc/src/routes.ts +14 -10
  271. package/examples/live-rpc/src/server.ts +15 -5
  272. package/examples/live-rpc/test/browser.test.ts +127 -50
  273. package/examples/live-rpc/test/chat/chat.test.ts +215 -23
  274. package/examples/live-rpc/test/routes.test.ts +130 -46
  275. package/examples/live-rpc/test/server.test.ts +94 -33
  276. package/examples/mcp-tools/README.md +24 -38
  277. package/examples/mcp-tools/src/platform/fake-farm.ts +63 -24
  278. package/examples/mcp-tools/src/platform/print-farm.ts +59 -29
  279. package/examples/mcp-tools/src/printers/Printers.ts +18 -7
  280. package/examples/mcp-tools/src/printers/farm.ts +15 -5
  281. package/examples/mcp-tools/src/printers/handlers.ts +12 -6
  282. package/examples/mcp-tools/src/routes.ts +8 -6
  283. package/examples/mcp-tools/src/server.ts +12 -5
  284. package/examples/mcp-tools/src/stdio.ts +3 -2
  285. package/examples/mcp-tools/test/printers/printers.test.ts +132 -89
  286. package/examples/mcp-tools/test/routes.test.ts +140 -81
  287. package/examples/notes-service/README.md +30 -45
  288. package/examples/notes-service/src/Api.ts +1 -0
  289. package/examples/notes-service/src/browser.ts +15 -14
  290. package/examples/notes-service/src/cli.ts +8 -3
  291. package/examples/notes-service/src/commands.ts +46 -20
  292. package/examples/notes-service/src/identity/Identity.ts +2 -2
  293. package/examples/notes-service/src/identity/authorize.ts +6 -2
  294. package/examples/notes-service/src/identity/handlers.ts +3 -2
  295. package/examples/notes-service/src/identity/users.ts +2 -1
  296. package/examples/notes-service/src/identity/verifier.ts +12 -6
  297. package/examples/notes-service/src/notes/Notes.ts +46 -22
  298. package/examples/notes-service/src/notes/handlers.ts +18 -9
  299. package/examples/notes-service/src/notes/store.ts +70 -43
  300. package/examples/notes-service/src/routes.ts +7 -5
  301. package/examples/notes-service/src/server.ts +12 -5
  302. package/examples/notes-service/src/status/Status.ts +1 -1
  303. package/examples/notes-service/src/status/handlers.ts +5 -3
  304. package/examples/notes-service/src/stdio.ts +7 -3
  305. package/examples/notes-service/src/worker.ts +6 -3
  306. package/examples/notes-service/test/commands.test.ts +164 -91
  307. package/examples/notes-service/test/notes/as.ts +3 -1
  308. package/examples/notes-service/test/notes/idempotency.test.ts +97 -67
  309. package/examples/notes-service/test/notes/in-process.test.ts +26 -15
  310. package/examples/notes-service/test/notes/notes.test.ts +49 -31
  311. package/examples/notes-service/test/routes.test.ts +106 -71
  312. package/examples/notes-service/test/worker.test.ts +21 -13
  313. package/examples/quickstart/README.md +2 -6
  314. package/examples/quickstart/src/Api.ts +1 -0
  315. package/examples/quickstart/src/client.ts +6 -3
  316. package/examples/quickstart/src/greeting/Greeting.ts +1 -1
  317. package/examples/quickstart/src/greeting/handlers.ts +5 -2
  318. package/examples/quickstart/src/routes.ts +3 -2
  319. package/examples/quickstart/src/server.ts +6 -2
  320. package/examples/quickstart/test/routes.test.ts +3 -2
  321. package/package.json +10 -4
@@ -1,46 +1,28 @@
1
1
  import { Anyone, assertAuthentication } from "./contract/caller.mjs";
2
- import { assertOnce, heldOnce } from "./contract/names.mjs";
3
2
  import { projectedErrors } from "./contract/declared.mjs";
3
+ import { assertOnce, heldOnce } from "./contract/names.mjs";
4
+ import { toolSuccessOf } from "./contract/stream.mjs";
5
+ import { acquire, answeringWhole } from "./contract/implementation.mjs";
6
+ import { inputParseOptions } from "./contract/call.mjs";
4
7
  import { hintsOf } from "./contract/hints.mjs";
5
- import { acquire, provideHandlers, select, toList } from "./contract/implementation.mjs";
6
8
  import { promote, providerOf } from "./authentication/provider.mjs";
7
- import { inputParseOptions } from "./contract/call.mjs";
8
- import { defaultPath, fieldKey, httpProtocol, isMisplaced, liftOf, liftedFrom, protocols } from "./mcp/protocol.mjs";
9
+ import { provideServed, selectFrom } from "./contract/serving.mjs";
9
10
  import { recordStepUp } from "./authentication/refusal.mjs";
10
11
  import { withStderrConsole } from "./stdio/console.mjs";
11
- import { McpCallError, client, request } from "./mcp/client.mjs";
12
- import { Cause, Context, Effect, ErrorReporter, Exit, Fiber, JsonPointer, Layer, Option, Predicate, Schema, Stdio, Stream } from "effect";
13
- import { AiError, McpSchema, McpServer } from "effect/ai";
12
+ import { defaultPath, fieldKey, httpProtocol, isMisplaced, isObjectSchema, liftOf, liftedFrom, protocols, routingFormsOf, toolJsonSchema } from "./mcp/protocol.mjs";
13
+ import { eventSchemasOf, refuseUnservable, serveWebhooks, withEvents } from "./mcp/bridge.mjs";
14
+ import { progressNotifier } from "./mcp/progress.mjs";
15
+ import { McpCallError } from "./mcp/reply.mjs";
16
+ import { request } from "./mcp/request.mjs";
17
+ import { client } from "./mcp/client.mjs";
18
+ import { Cause, Context, Effect, ErrorReporter, Exit, Fiber, Layer, Option, Predicate, Schema, Stdio, Stream } from "effect";
14
19
  import { HttpRouter, HttpServerRequest } from "effect/http";
15
- import { Base64 } from "effect/encoding";
20
+ import { AiError, McpSchema, McpServer } from "effect/ai";
16
21
  // src/mcp/ActionMcp.ts
17
- const isToolArgumentsSchema = Schema.is(McpSchema.ToolJson);
18
- const isJson = Schema.is(Schema.Json);
19
- const definitionsReferenced = (value) => {
20
- if (value === null || Predicate.isString(value) || Predicate.isNumber(value) || Predicate.isBoolean(value)) return [];
21
- if (Array.isArray(value)) return value.flatMap(definitionsReferenced);
22
- return Object.entries(value).flatMap(([field, nested]) => {
23
- if (field !== "$ref") return definitionsReferenced(nested);
24
- const [scope, key] = Predicate.isString(nested) ? JsonPointer.parseUriFragment(nested) ?? [] : [];
25
- return scope === "$defs" && key !== void 0 ? [key] : [];
26
- });
27
- };
28
- const toolJsonSchema = (schema, strict) => {
29
- const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: strict ? "error" : "ignore" });
30
- const [scope, key] = Predicate.isString(document.schema["$ref"]) ? JsonPointer.parseUriFragment(document.schema["$ref"]) ?? [] : [];
31
- const inlined = scope === "$defs" && key !== void 0 ? key : void 0;
32
- const root = inlined === void 0 ? document.schema : document.definitions[inlined];
33
- if (root === void 0) return void 0;
34
- const definitions = inlined !== void 0 && ![root, ...Object.values(document.definitions)].flatMap((schema) => isJson(schema) ? definitionsReferenced(schema) : []).includes(inlined) ? Object.fromEntries(Object.entries(document.definitions).filter(([name]) => name !== inlined)) : document.definitions;
35
- return Object.keys(definitions).length === 0 ? root : {
36
- ...root,
37
- $defs: definitions
38
- };
39
- };
40
- const assertToolShapes = (lifted) => {
41
- const inputs = lifted.map(([action]) => action).filter((action) => !isToolArgumentsSchema(toolJsonSchema(Schema.toCodecJson(action.input), true))).map(({ name }) => name);
22
+ const assertToolsServable = (lifted) => {
23
+ const inputs = lifted.map(([action]) => action).flatMap(({ input, name }) => isObjectSchema(toolJsonSchema(Schema.toCodecJson(input), true)) ? [] : [name]);
42
24
  if (inputs.length > 0) throw new Error(`MCP tool input must be one object with keys, such as a struct: ${inputs.join(", ")} (wrap a union, an array or a scalar in a field, omit input for no arguments, or leave the action out of actions)`);
43
- const misplaced = lifted.filter(([action, lift]) => isMisplaced(action, lift)).map(([{ name }]) => name);
25
+ const misplaced = lifted.flatMap(([action, lift]) => isMisplaced(action, lift) ? [action.name] : []);
44
26
  if (misplaced.length > 0) throw new Error(`MCP media must be the success or an array of it, or a top-level field of a struct success, one, optional or a required array: ${misplaced.join(", ")} (make the image such a field, or give an optional array as a required one, empty when absent; an image in input or an error is not served over MCP, so leave that action out of actions)`);
45
27
  };
46
28
  const nativeInternalErrorText = "Tool execution failed due to an internal server error.";
@@ -72,26 +54,30 @@ const toolOf = (action, outputSchema) => Effect.map(Schema.decodeUnknownEffect(M
72
54
  },
73
55
  _meta: action.mcp._meta === void 0 ? void 0 : { ...action.mcp._meta }
74
56
  }));
57
+ const internalError = (cause) => Effect.logError(cause).pipe(Effect.andThen(ErrorReporter.report(cause)), Effect.as(textErrorResult(nativeInternalErrorText)));
58
+ const internalErrorOnDefect = (cause) => Cause.hasDies(cause) ? internalError(cause) : Effect.failCause(cause);
59
+ const encoder = (schema) => {
60
+ const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema));
61
+ return (value) => Effect.orDie(encode(value));
62
+ };
75
63
  const registerTools = Effect.fnUntraced(function* (apps, authentication) {
76
64
  const registry = yield* McpServer.McpServer;
77
- const bound = yield* acquire(apps);
65
+ const bound = yield* acquire(apps, authentication);
78
66
  const built = yield* Effect.context();
79
- const internalError = (cause) => Effect.logError(cause).pipe(Effect.andThen(ErrorReporter.report(cause)), Effect.as(textErrorResult(nativeInternalErrorText)));
80
- const internalErrorOnDefect = (cause) => Cause.hasDies(cause) ? internalError(cause) : Effect.failCause(cause);
81
- for (const [action, run] of bound) {
82
- const lift = liftOf(action.success);
67
+ for (const [action, handler] of bound) {
68
+ const toolSuccess = toolSuccessOf(action.success);
69
+ const run = answeringWhole(action, handler);
70
+ const lift = liftOf(toolSuccess);
83
71
  const media = lift.fields.length === 0 ? void 0 : lift;
84
- const structured = media === void 0 ? Schema.toCodecJson(action.success) : media.rest === void 0 ? void 0 : Schema.toCodecJson(media.rest);
72
+ const structuredSuccess = media === void 0 ? toolSuccess : media.rest;
73
+ const structured = structuredSuccess === void 0 ? void 0 : Schema.toCodecJson(structuredSuccess);
85
74
  const outputSchema = structured === void 0 ? void 0 : yield* Schema.decodeUnknownEffect(McpSchema.ToolOutputJson)(toolJsonSchema(structured, false)).pipe(Effect.orDie);
86
75
  const tool = yield* toolOf(action, outputSchema).pipe(Effect.orDie);
87
76
  const decode = Schema.decodeUnknownEffect(Schema.toCodecJson(action.input), inputParseOptions);
88
- const encoder = (schema) => {
89
- const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema));
90
- return (value) => Effect.orDie(encode(value));
91
- };
92
- const encodeSuccess = encoder(action.success);
77
+ const encodeSuccess = encoder(toolSuccess);
93
78
  const encodeFailure = encoder(Schema.Union(projectedErrors(action)));
94
- const call = authentication === void 0 || action.caller === Anyone ? run : (input) => recordStepUp(promote(authentication, run(input)));
79
+ const reported = (input) => action.progress === void 0 ? run(input) : Effect.flatMap(progressNotifier(registry.notifications, action.progress), (sink) => run(input, sink));
80
+ const call = authentication === void 0 || action.caller === Anyone ? reported : (input) => recordStepUp(promote(authentication, reported(input)));
95
81
  const liftedFieldNames = new Set(media?.fields.map(({ name }) => name));
96
82
  const resultOf = (encoded, success) => {
97
83
  if (media === void 0) return new McpSchema.CallToolResult({
@@ -114,10 +100,7 @@ const registerTools = Effect.fnUntraced(function* (apps, authentication) {
114
100
  yield* registry.addTool({
115
101
  tool,
116
102
  annotations: Context.empty(),
117
- handle: (payload) => Effect.annotateCurrentSpan({
118
- tool: action.name,
119
- parameters: payload ?? {}
120
- }).pipe(Effect.andThen(() => decode(payload ?? {})), Effect.mapError(({ message }) => new McpSchema.InvalidParams({ message: new AiError.ToolParameterValidationError({
103
+ handle: (payload) => Effect.annotateCurrentSpan({ tool: action.name }).pipe(Effect.andThen(() => decode(payload ?? {})), Effect.mapError(({ message }) => new McpSchema.InvalidParams({ message: new AiError.ToolParameterValidationError({
121
104
  toolName: action.name,
122
105
  description: message
123
106
  }).message })), Effect.flatMap((input) => call(input).pipe(Effect.matchEffect({
@@ -130,34 +113,63 @@ const registerTools = Effect.fnUntraced(function* (apps, authentication) {
130
113
  });
131
114
  }
132
115
  });
133
- const server = (apps, transport, features = Layer.empty, authentication) => {
116
+ /**
117
+ * Refuses event types an endpoint cannot serve as MCP events: one named twice, one named as MCP's
118
+ * own, or one whose input or payload is no object.
119
+ */
120
+ const assertEventsServable = (events) => {
121
+ assertOnce("MCP event", events);
122
+ const reserved = events.find(({ name }) => name.startsWith("mcp."));
123
+ if (reserved !== void 0) throw new Error(`MCP event name starts with "mcp.", which MCP keeps for its own events: ${reserved.name} (rename it, or serve it on another surface)`);
124
+ for (const event of events) eventSchemasOf(event);
125
+ };
126
+ /** The revisions an endpoint speaks, the 2026-07-28 one serving `serving`'s events if any. */
127
+ const servingEvents = ([stateless, ...rest], serving) => serving.events.length === 0 ? [stateless, ...rest] : [withEvents(stateless, serving), ...rest];
128
+ const server = (apps, serving, transport, features = Layer.empty) => {
129
+ const { events, authentication } = serving;
134
130
  assertOnce("MCP tool", apps.flatMap((app) => app.actions), heldOnce);
135
- const lifted = apps.flatMap((app) => app.actions.map((action) => [action, liftOf(action.success)]));
136
- assertToolShapes(lifted);
131
+ const lifted = apps.flatMap((app) => app.actions.map((action) => [action, liftOf(toolSuccessOf(action.success))]));
132
+ assertToolsServable(lifted);
137
133
  const names = new Set(lifted.map(([{ name }]) => name));
138
134
  const register = Effect.gen(function* () {
139
135
  const namesClaimedByFeatures = (yield* McpServer.McpServer).tools.flatMap(({ tool }) => names.has(tool.name) ? [tool.name] : []);
140
136
  if (namesClaimedByFeatures.length > 0) return yield* Effect.die(/* @__PURE__ */ new Error(`Duplicate MCP tool: ${namesClaimedByFeatures.join(", ")}, claimed by an action and a native feature (rename the native tool, or leave the action out of actions)`));
137
+ yield* refuseUnservable(serving);
138
+ yield* serveWebhooks(serving);
141
139
  yield* registerTools(apps, authentication);
142
140
  });
143
- return Layer.effectDiscard(register).pipe(Layer.provide(features), Layer.provide(transport), Layer.fresh, provideHandlers(apps));
141
+ return Layer.effectDiscard(register).pipe(Layer.provide(features), Layer.provide(transport), Layer.fresh, provideServed({
142
+ apps,
143
+ events
144
+ }));
144
145
  };
145
146
  const anonymousMethods = /* @__PURE__ */ new Set([
146
147
  "server/discover",
147
148
  "tools/list",
149
+ "events/list",
148
150
  "notifications/cancelled"
149
151
  ]);
150
- const requiresAuthentication = (actions) => {
151
- const open = new Set(actions.filter(({ caller }) => caller === Anyone).flatMap(({ name }) => [name, `=?base64?${Base64.encode(name)}?=`]));
152
+ const namedMethods = /* @__PURE__ */ new Map([
153
+ ["tools/call", "tool"],
154
+ ["events/poll", "event"],
155
+ ["events/stream", "event"]
156
+ ]);
157
+ const openOf = (contracts) => new Set(contracts.filter(({ caller }) => caller === Anyone).flatMap(({ name }) => routingFormsOf(name)));
158
+ const requiresAuthentication = (actions, events) => {
159
+ const open = {
160
+ tool: openOf(actions),
161
+ event: openOf(events)
162
+ };
152
163
  return (headers) => {
153
- if (open.size === 0) return true;
164
+ if (open.tool.size === 0 && open.event.size === 0) return true;
154
165
  if (headers["mcp-protocol-version"] !== httpProtocol.protocolVersion) return true;
155
166
  const method = headers["mcp-method"];
156
167
  if (method === void 0) return true;
157
168
  if (anonymousMethods.has(method)) return false;
158
- if (method !== "tools/call") return true;
169
+ const named = namedMethods.get(method);
170
+ if (named === void 0) return true;
159
171
  const name = headers["mcp-name"];
160
- return name === void 0 || !open.has(name);
172
+ return name === void 0 || !open[named].has(name);
161
173
  };
162
174
  };
163
175
  const namesItsMethod = (request) => Effect.match(request.json, {
@@ -165,23 +177,30 @@ const namesItsMethod = (request) => Effect.match(request.json, {
165
177
  onSuccess: (body) => !Predicate.hasProperty(body, "method") || body.method === request.headers["mcp-method"]
166
178
  });
167
179
  const readsItsBody = (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method === "POST" ? Effect.andThen(request.text, route) : route);
168
- function layerHttp(apps, { actions, features, path = defaultPath, authentication, requestScoped, allowSubscriptions = features !== void 0, ...options }) {
169
- const selected = select(toList(apps), actions);
180
+ function layerHttp(apps, { actions, features, path = defaultPath, authentication, requestScoped, allowSubscriptions, ...options }) {
181
+ const { apps: selected, events } = selectFrom(apps, actions);
170
182
  const served = selected.flatMap((app) => app.actions);
183
+ const listed = events.flatMap((app) => app.events);
171
184
  assertAuthentication(served, authentication);
172
- const transport = server(selected, requestScoped === true ? McpServer.layerHttpRequestScoped({
185
+ assertAuthentication(listed, authentication, "event");
186
+ assertEventsServable(listed);
187
+ const serving = {
188
+ events,
189
+ authentication
190
+ };
191
+ const transport = server(selected, serving, requestScoped === true ? McpServer.layerHttpRequestScoped({
173
192
  ...options,
174
193
  path,
175
- protocols: [httpProtocol]
194
+ protocols: servingEvents([httpProtocol], serving)
176
195
  }) : McpServer.layerHttp({
177
196
  ...options,
178
197
  path,
179
- protocols,
198
+ protocols: servingEvents(protocols, serving),
180
199
  allowSessionTermination: true,
181
- allowSubscriptions
182
- }), features, authentication);
200
+ allowSubscriptions: allowSubscriptions ?? (features !== void 0 || events.length > 0)
201
+ }), features);
183
202
  if (authentication === void 0) return transport.pipe(Layer.provide(HttpRouter.middleware(readsItsBody).layer));
184
- const required = requiresAuthentication(served);
203
+ const required = requiresAuthentication(served, listed);
185
204
  const middleware = HttpRouter.middleware(Effect.map(providerOf(authentication), (runtime) => (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method !== "POST" || required(request.headers) ? runtime.http(readsItsBody(route), false) : Effect.flatMap(namesItsMethod(request), (named) => runtime.http(readsItsBody(route), named)))));
186
205
  return transport.pipe(Layer.provide(middleware.layer));
187
206
  }
@@ -191,9 +210,15 @@ const jsonLinesOnly = Layer.effect(Stdio.Stdio, Effect.map(Stdio.Stdio, (stdio)
191
210
  stdin: stdio.stdin.pipe(Stream.decodeText, Stream.splitLines, Stream.filter(isJsonLine), Stream.map((line) => `${line}\n`), Stream.encodeText)
192
211
  })));
193
212
  function runStdio(apps, { actions, features, ...options }) {
194
- const transport = server(select(toList(apps), actions), McpServer.layerStdio({
213
+ const { apps: selected, events } = selectFrom(apps, actions);
214
+ assertEventsServable(events.flatMap((app) => app.events));
215
+ const serving = {
216
+ events,
217
+ authentication: void 0
218
+ };
219
+ const transport = server(selected, serving, McpServer.layerStdio({
195
220
  ...options,
196
- protocols
221
+ protocols: servingEvents(protocols, serving)
197
222
  }).pipe(Layer.provide(jsonLinesOnly)), features);
198
223
  return Layer.launch(transport).pipe(withStderrConsole, Effect.forkChild, Effect.flatMap(Fiber.await), Effect.flatMap((exit) => Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause) ? Effect.failCause(exit.cause) : Effect.void));
199
224
  }