effect 4.0.3 → 4.0.5

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 (449) hide show
  1. package/AGENTS.md +24 -0
  2. package/CLAUDE.md +24 -0
  3. package/ai-docs/package.json +2 -2
  4. package/ai-docs/src/52_graphql/10_basics.ts +117 -0
  5. package/ai-docs/src/52_graphql/20_testing.ts +45 -0
  6. package/ai-docs/src/52_graphql/30_batching.ts +118 -0
  7. package/ai-docs/src/52_graphql/40_aliased-batching.ts +124 -0
  8. package/ai-docs/src/52_graphql/50_errors-and-retries.ts +74 -0
  9. package/ai-docs/src/52_graphql/index.md +6 -0
  10. package/dist/Array.d.ts +90 -6
  11. package/dist/Array.d.ts.map +1 -1
  12. package/dist/Array.js +4 -2
  13. package/dist/Array.js.map +1 -1
  14. package/dist/Channel.d.ts +6 -1
  15. package/dist/Channel.d.ts.map +1 -1
  16. package/dist/Channel.js +17 -3
  17. package/dist/Channel.js.map +1 -1
  18. package/dist/ConfigProvider.d.ts.map +1 -1
  19. package/dist/ConfigProvider.js +33 -32
  20. package/dist/ConfigProvider.js.map +1 -1
  21. package/dist/Context.d.ts.map +1 -1
  22. package/dist/Context.js +9 -0
  23. package/dist/Context.js.map +1 -1
  24. package/dist/Duration.d.ts.map +1 -1
  25. package/dist/Duration.js +2 -5
  26. package/dist/Duration.js.map +1 -1
  27. package/dist/Effect.d.ts +61 -19
  28. package/dist/Effect.d.ts.map +1 -1
  29. package/dist/Effect.js +58 -39
  30. package/dist/Effect.js.map +1 -1
  31. package/dist/FileSystem.d.ts +23 -9
  32. package/dist/FileSystem.d.ts.map +1 -1
  33. package/dist/FileSystem.js.map +1 -1
  34. package/dist/Match.d.ts +20 -6
  35. package/dist/Match.d.ts.map +1 -1
  36. package/dist/Match.js +2 -2
  37. package/dist/Match.js.map +1 -1
  38. package/dist/Path.d.ts +37 -5
  39. package/dist/Path.d.ts.map +1 -1
  40. package/dist/Path.js +36 -5
  41. package/dist/Path.js.map +1 -1
  42. package/dist/RequestResolver.d.ts.map +1 -1
  43. package/dist/RequestResolver.js +4 -10
  44. package/dist/RequestResolver.js.map +1 -1
  45. package/dist/Scheduler.d.ts +9 -0
  46. package/dist/Scheduler.d.ts.map +1 -1
  47. package/dist/Scheduler.js +9 -0
  48. package/dist/Scheduler.js.map +1 -1
  49. package/dist/Schema.d.ts +15 -2
  50. package/dist/Schema.d.ts.map +1 -1
  51. package/dist/Schema.js +16 -2
  52. package/dist/Schema.js.map +1 -1
  53. package/dist/SchemaGetter.d.ts +4 -0
  54. package/dist/SchemaGetter.d.ts.map +1 -1
  55. package/dist/SchemaGetter.js +52 -33
  56. package/dist/SchemaGetter.js.map +1 -1
  57. package/dist/Sink.d.ts.map +1 -1
  58. package/dist/Sink.js +38 -17
  59. package/dist/Sink.js.map +1 -1
  60. package/dist/Stream.d.ts +11 -0
  61. package/dist/Stream.d.ts.map +1 -1
  62. package/dist/Stream.js +16 -1
  63. package/dist/Stream.js.map +1 -1
  64. package/dist/String.d.ts +12 -0
  65. package/dist/String.d.ts.map +1 -1
  66. package/dist/String.js +17 -4
  67. package/dist/String.js.map +1 -1
  68. package/dist/TxRef.d.ts.map +1 -1
  69. package/dist/TxRef.js +3 -2
  70. package/dist/TxRef.js.map +1 -1
  71. package/dist/Utils.js +8 -3
  72. package/dist/Utils.js.map +1 -1
  73. package/dist/ai/AiError.d.ts +10 -10
  74. package/dist/ai/AiError.d.ts.map +1 -1
  75. package/dist/ai/AiError.js +1 -1
  76. package/dist/ai/AiError.js.map +1 -1
  77. package/dist/ai/AnthropicStructuredOutput.js +0 -2
  78. package/dist/ai/AnthropicStructuredOutput.js.map +1 -1
  79. package/dist/ai/Chat.d.ts +2 -2
  80. package/dist/ai/Chat.d.ts.map +1 -1
  81. package/dist/ai/Decision.d.ts +70 -19
  82. package/dist/ai/Decision.d.ts.map +1 -1
  83. package/dist/ai/Decision.js +37 -3
  84. package/dist/ai/Decision.js.map +1 -1
  85. package/dist/ai/DecisionModel.js +1 -1
  86. package/dist/ai/DecisionModel.js.map +1 -1
  87. package/dist/ai/LanguageModel.d.ts +38 -7
  88. package/dist/ai/LanguageModel.d.ts.map +1 -1
  89. package/dist/ai/LanguageModel.js +70 -40
  90. package/dist/ai/LanguageModel.js.map +1 -1
  91. package/dist/ai/McpServer.d.ts +61 -52
  92. package/dist/ai/McpServer.d.ts.map +1 -1
  93. package/dist/ai/McpServer.js +134 -50
  94. package/dist/ai/McpServer.js.map +1 -1
  95. package/dist/ai/Prompt.d.ts.map +1 -1
  96. package/dist/ai/Prompt.js +28 -5
  97. package/dist/ai/Prompt.js.map +1 -1
  98. package/dist/ai/Response.d.ts +5 -4
  99. package/dist/ai/Response.d.ts.map +1 -1
  100. package/dist/ai/Response.js.map +1 -1
  101. package/dist/cli/Completions.d.ts +5 -0
  102. package/dist/cli/Completions.d.ts.map +1 -1
  103. package/dist/cli/Completions.js.map +1 -1
  104. package/dist/cli/Flag.d.ts +100 -0
  105. package/dist/cli/Flag.d.ts.map +1 -1
  106. package/dist/cli/Flag.js +33 -0
  107. package/dist/cli/Flag.js.map +1 -1
  108. package/dist/cli/Param.d.ts +87 -0
  109. package/dist/cli/Param.d.ts.map +1 -1
  110. package/dist/cli/Param.js +30 -0
  111. package/dist/cli/Param.js.map +1 -1
  112. package/dist/cli/internal/command.d.ts.map +1 -1
  113. package/dist/cli/internal/command.js +2 -1
  114. package/dist/cli/internal/command.js.map +1 -1
  115. package/dist/cli/internal/completions/bash.js +4 -3
  116. package/dist/cli/internal/completions/bash.js.map +1 -1
  117. package/dist/cli/internal/completions/descriptor.js +8 -1
  118. package/dist/cli/internal/completions/descriptor.js.map +1 -1
  119. package/dist/cli/internal/completions/fish.js +4 -4
  120. package/dist/cli/internal/completions/fish.js.map +1 -1
  121. package/dist/cli/internal/completions/powershell.js +3 -2
  122. package/dist/cli/internal/completions/powershell.js.map +1 -1
  123. package/dist/cli/internal/completions/zsh.js +7 -3
  124. package/dist/cli/internal/completions/zsh.js.map +1 -1
  125. package/dist/cli/internal/parser.js +11 -3
  126. package/dist/cli/internal/parser.js.map +1 -1
  127. package/dist/cli/internal/wizard.d.ts.map +1 -1
  128. package/dist/cli/internal/wizard.js +2 -1
  129. package/dist/cli/internal/wizard.js.map +1 -1
  130. package/dist/cluster/ClusterWorkflowEngine.d.ts +1 -0
  131. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  132. package/dist/cluster/ClusterWorkflowEngine.js +113 -21
  133. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  134. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  135. package/dist/cluster/MessageStorage.js +20 -12
  136. package/dist/cluster/MessageStorage.js.map +1 -1
  137. package/dist/cluster/Runners.d.ts.map +1 -1
  138. package/dist/cluster/Runners.js +54 -34
  139. package/dist/cluster/Runners.js.map +1 -1
  140. package/dist/cluster/Sharding.d.ts.map +1 -1
  141. package/dist/cluster/Sharding.js +6 -4
  142. package/dist/cluster/Sharding.js.map +1 -1
  143. package/dist/cluster/internal/entityManager.js +1 -1
  144. package/dist/cluster/internal/entityManager.js.map +1 -1
  145. package/dist/encoding/Sse.d.ts +6 -0
  146. package/dist/encoding/Sse.d.ts.map +1 -1
  147. package/dist/encoding/Sse.js +63 -71
  148. package/dist/encoding/Sse.js.map +1 -1
  149. package/dist/graphql/GraphQL.d.ts +349 -0
  150. package/dist/graphql/GraphQL.d.ts.map +1 -0
  151. package/dist/graphql/GraphQL.js +207 -0
  152. package/dist/graphql/GraphQL.js.map +1 -0
  153. package/dist/graphql/GraphQLClient.d.ts +562 -0
  154. package/dist/graphql/GraphQLClient.d.ts.map +1 -0
  155. package/dist/graphql/GraphQLClient.js +505 -0
  156. package/dist/graphql/GraphQLClient.js.map +1 -0
  157. package/dist/graphql/GraphQLClientError.d.ts +445 -0
  158. package/dist/graphql/GraphQLClientError.d.ts.map +1 -0
  159. package/dist/graphql/GraphQLClientError.js +479 -0
  160. package/dist/graphql/GraphQLClientError.js.map +1 -0
  161. package/dist/graphql/GraphQLGroup.d.ts +118 -0
  162. package/dist/graphql/GraphQLGroup.d.ts.map +1 -0
  163. package/dist/graphql/GraphQLGroup.js +109 -0
  164. package/dist/graphql/GraphQLGroup.js.map +1 -0
  165. package/dist/graphql/GraphQLMiddleware.d.ts +249 -0
  166. package/dist/graphql/GraphQLMiddleware.d.ts.map +1 -0
  167. package/dist/graphql/GraphQLMiddleware.js +130 -0
  168. package/dist/graphql/GraphQLMiddleware.js.map +1 -0
  169. package/dist/graphql/GraphQLProtocol.d.ts +969 -0
  170. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -0
  171. package/dist/graphql/GraphQLProtocol.js +809 -0
  172. package/dist/graphql/GraphQLProtocol.js.map +1 -0
  173. package/dist/graphql/GraphQLResolver.d.ts +453 -0
  174. package/dist/graphql/GraphQLResolver.d.ts.map +1 -0
  175. package/dist/graphql/GraphQLResolver.js +582 -0
  176. package/dist/graphql/GraphQLResolver.js.map +1 -0
  177. package/dist/graphql/index.d.ts +40 -0
  178. package/dist/graphql/index.d.ts.map +1 -0
  179. package/dist/graphql/index.js +41 -0
  180. package/dist/graphql/index.js.map +1 -0
  181. package/dist/http/FetchHttpClient.d.ts +6 -3
  182. package/dist/http/FetchHttpClient.d.ts.map +1 -1
  183. package/dist/http/FetchHttpClient.js +6 -3
  184. package/dist/http/FetchHttpClient.js.map +1 -1
  185. package/dist/http/FindMyWay/internal/router.js +2 -1
  186. package/dist/http/FindMyWay/internal/router.js.map +1 -1
  187. package/dist/http/Headers.d.ts +3 -3
  188. package/dist/http/Headers.d.ts.map +1 -1
  189. package/dist/http/Headers.js +6 -5
  190. package/dist/http/Headers.js.map +1 -1
  191. package/dist/http/HttpClient.d.ts +27 -0
  192. package/dist/http/HttpClient.d.ts.map +1 -1
  193. package/dist/http/HttpClient.js +38 -11
  194. package/dist/http/HttpClient.js.map +1 -1
  195. package/dist/http/HttpClientError.d.ts.map +1 -1
  196. package/dist/http/HttpClientError.js +8 -6
  197. package/dist/http/HttpClientError.js.map +1 -1
  198. package/dist/http/HttpClientRequest.d.ts +147 -4
  199. package/dist/http/HttpClientRequest.d.ts.map +1 -1
  200. package/dist/http/HttpClientRequest.js +47 -1
  201. package/dist/http/HttpClientRequest.js.map +1 -1
  202. package/dist/http/HttpEffect.d.ts.map +1 -1
  203. package/dist/http/HttpEffect.js +14 -7
  204. package/dist/http/HttpEffect.js.map +1 -1
  205. package/dist/http/HttpMiddleware.d.ts +60 -0
  206. package/dist/http/HttpMiddleware.d.ts.map +1 -1
  207. package/dist/http/HttpMiddleware.js +93 -32
  208. package/dist/http/HttpMiddleware.js.map +1 -1
  209. package/dist/http/HttpRouter.d.ts +35 -0
  210. package/dist/http/HttpRouter.d.ts.map +1 -1
  211. package/dist/http/HttpRouter.js +87 -13
  212. package/dist/http/HttpRouter.js.map +1 -1
  213. package/dist/http/HttpServerError.d.ts.map +1 -1
  214. package/dist/http/HttpServerError.js +6 -4
  215. package/dist/http/HttpServerError.js.map +1 -1
  216. package/dist/http/HttpServerRequest.js +2 -2
  217. package/dist/http/HttpServerRequest.js.map +1 -1
  218. package/dist/http/HttpServerResponse.d.ts +8 -6
  219. package/dist/http/HttpServerResponse.d.ts.map +1 -1
  220. package/dist/http/HttpServerResponse.js +27 -16
  221. package/dist/http/HttpServerResponse.js.map +1 -1
  222. package/dist/http/HttpStaticServer.d.ts.map +1 -1
  223. package/dist/http/HttpStaticServer.js +4 -10
  224. package/dist/http/HttpStaticServer.js.map +1 -1
  225. package/dist/http/HttpTraceContext.js +1 -1
  226. package/dist/http/HttpTraceContext.js.map +1 -1
  227. package/dist/http/Multipart.d.ts.map +1 -1
  228. package/dist/http/Multipart.js +15 -1
  229. package/dist/http/Multipart.js.map +1 -1
  230. package/dist/http/Url.d.ts.map +1 -1
  231. package/dist/http/Url.js +2 -1
  232. package/dist/http/Url.js.map +1 -1
  233. package/dist/http/UrlParams.d.ts +112 -8
  234. package/dist/http/UrlParams.d.ts.map +1 -1
  235. package/dist/http/UrlParams.js +141 -14
  236. package/dist/http/UrlParams.js.map +1 -1
  237. package/dist/http/internal/compression.d.ts +1 -1
  238. package/dist/http/internal/compression.d.ts.map +1 -1
  239. package/dist/http/internal/compression.js +2 -10
  240. package/dist/http/internal/compression.js.map +1 -1
  241. package/dist/http/internal/compressionBody.d.ts +2 -0
  242. package/dist/http/internal/compressionBody.d.ts.map +1 -0
  243. package/dist/http/internal/compressionBody.js +36 -0
  244. package/dist/http/internal/compressionBody.js.map +1 -0
  245. package/dist/http/internal/decompression.d.ts +2 -0
  246. package/dist/http/internal/decompression.d.ts.map +1 -0
  247. package/dist/http/internal/decompression.js +162 -0
  248. package/dist/http/internal/decompression.js.map +1 -0
  249. package/dist/http/internal/tracing.js +14 -4
  250. package/dist/http/internal/tracing.js.map +1 -1
  251. package/dist/http/internal/urlParams.d.ts +2 -0
  252. package/dist/http/internal/urlParams.d.ts.map +1 -0
  253. package/dist/http/internal/urlParams.js +4 -0
  254. package/dist/http/internal/urlParams.js.map +1 -0
  255. package/dist/http-api/HttpApiClient.d.ts.map +1 -1
  256. package/dist/http-api/HttpApiClient.js +2 -1
  257. package/dist/http-api/HttpApiClient.js.map +1 -1
  258. package/dist/http-api/HttpApiScalar.d.ts +5 -0
  259. package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
  260. package/dist/http-api/HttpApiScalar.js.map +1 -1
  261. package/dist/internal/core.js +17 -1
  262. package/dist/internal/core.js.map +1 -1
  263. package/dist/internal/dateTime.js +40 -35
  264. package/dist/internal/dateTime.js.map +1 -1
  265. package/dist/internal/effect.js +13 -6
  266. package/dist/internal/effect.js.map +1 -1
  267. package/dist/internal/graphql.d.ts +2 -0
  268. package/dist/internal/graphql.d.ts.map +1 -0
  269. package/dist/internal/graphql.js +205 -0
  270. package/dist/internal/graphql.js.map +1 -0
  271. package/dist/internal/graphqlHeaders.d.ts +4 -0
  272. package/dist/internal/graphqlHeaders.d.ts.map +1 -0
  273. package/dist/internal/graphqlHeaders.js +11 -0
  274. package/dist/internal/graphqlHeaders.js.map +1 -0
  275. package/dist/internal/request.js +20 -1
  276. package/dist/internal/request.js.map +1 -1
  277. package/dist/internal/schema/toCodeDocument.js +4 -1
  278. package/dist/internal/schema/toCodeDocument.js.map +1 -1
  279. package/dist/internal/schema/toJsonSchemaDocument.js +29 -5
  280. package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
  281. package/dist/internal/version.js +1 -1
  282. package/dist/net/Host.d.ts +49 -0
  283. package/dist/net/Host.d.ts.map +1 -1
  284. package/dist/net/Host.js +55 -0
  285. package/dist/net/Host.js.map +1 -1
  286. package/dist/net/NetAddress.d.ts +8 -0
  287. package/dist/net/NetAddress.d.ts.map +1 -1
  288. package/dist/net/NetAddress.js +8 -0
  289. package/dist/net/NetAddress.js.map +1 -1
  290. package/dist/observability/Otlp.d.ts +15 -0
  291. package/dist/observability/Otlp.d.ts.map +1 -1
  292. package/dist/observability/Otlp.js +3 -0
  293. package/dist/observability/Otlp.js.map +1 -1
  294. package/dist/observability/OtlpExporter.d.ts +8 -0
  295. package/dist/observability/OtlpExporter.d.ts.map +1 -1
  296. package/dist/observability/OtlpExporter.js +10 -1
  297. package/dist/observability/OtlpExporter.js.map +1 -1
  298. package/dist/observability/OtlpLogger.d.ts +17 -0
  299. package/dist/observability/OtlpLogger.d.ts.map +1 -1
  300. package/dist/observability/OtlpLogger.js +14 -1
  301. package/dist/observability/OtlpLogger.js.map +1 -1
  302. package/dist/observability/OtlpMetrics.d.ts +17 -0
  303. package/dist/observability/OtlpMetrics.d.ts.map +1 -1
  304. package/dist/observability/OtlpMetrics.js +13 -0
  305. package/dist/observability/OtlpMetrics.js.map +1 -1
  306. package/dist/observability/OtlpTracer.d.ts +17 -0
  307. package/dist/observability/OtlpTracer.d.ts.map +1 -1
  308. package/dist/observability/OtlpTracer.js +15 -2
  309. package/dist/observability/OtlpTracer.js.map +1 -1
  310. package/dist/reactivity/AsyncResult.d.ts +6 -0
  311. package/dist/reactivity/AsyncResult.d.ts.map +1 -1
  312. package/dist/reactivity/AsyncResult.js +27 -0
  313. package/dist/reactivity/AsyncResult.js.map +1 -1
  314. package/dist/reactivity/AtomRegistry.js +3 -1
  315. package/dist/reactivity/AtomRegistry.js.map +1 -1
  316. package/dist/rpc/RpcClient.d.ts.map +1 -1
  317. package/dist/rpc/RpcClient.js +6 -1
  318. package/dist/rpc/RpcClient.js.map +1 -1
  319. package/dist/rpc/RpcServer.d.ts.map +1 -1
  320. package/dist/rpc/RpcServer.js +36 -9
  321. package/dist/rpc/RpcServer.js.map +1 -1
  322. package/dist/socket/Socket.d.ts +6 -0
  323. package/dist/socket/Socket.d.ts.map +1 -1
  324. package/dist/socket/Socket.js.map +1 -1
  325. package/dist/sql/SqlClient.d.ts +8 -7
  326. package/dist/sql/SqlClient.d.ts.map +1 -1
  327. package/dist/sql/SqlClient.js +8 -7
  328. package/dist/sql/SqlClient.js.map +1 -1
  329. package/dist/testing/TestClock.d.ts +16 -3
  330. package/dist/testing/TestClock.d.ts.map +1 -1
  331. package/dist/testing/TestClock.js +112 -22
  332. package/dist/testing/TestClock.js.map +1 -1
  333. package/dist/workflow/Activity.js +1 -0
  334. package/dist/workflow/Activity.js.map +1 -1
  335. package/dist/workflow/DurableDeferred.d.ts.map +1 -1
  336. package/dist/workflow/DurableDeferred.js +32 -3
  337. package/dist/workflow/DurableDeferred.js.map +1 -1
  338. package/dist/workflow/Workflow.d.ts +22 -0
  339. package/dist/workflow/Workflow.d.ts.map +1 -1
  340. package/dist/workflow/Workflow.js +15 -3
  341. package/dist/workflow/Workflow.js.map +1 -1
  342. package/dist/workflow/WorkflowEngine.d.ts +44 -3
  343. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  344. package/dist/workflow/WorkflowEngine.js +45 -22
  345. package/dist/workflow/WorkflowEngine.js.map +1 -1
  346. package/package.json +6 -3
  347. package/src/Array.ts +95 -6
  348. package/src/Channel.ts +24 -3
  349. package/src/ConfigProvider.ts +40 -44
  350. package/src/Context.ts +9 -0
  351. package/src/Duration.ts +4 -5
  352. package/src/Effect.ts +140 -53
  353. package/src/FileSystem.ts +23 -9
  354. package/src/Match.ts +65 -12
  355. package/src/Path.ts +52 -7
  356. package/src/RequestResolver.ts +4 -10
  357. package/src/Scheduler.ts +9 -0
  358. package/src/Schema.ts +25 -4
  359. package/src/SchemaGetter.ts +47 -35
  360. package/src/Sink.ts +45 -18
  361. package/src/Stream.ts +33 -4
  362. package/src/String.ts +17 -4
  363. package/src/TxRef.ts +4 -2
  364. package/src/Utils.ts +8 -5
  365. package/src/ai/AiError.ts +3 -1
  366. package/src/ai/AnthropicStructuredOutput.ts +2 -2
  367. package/src/ai/Chat.ts +2 -2
  368. package/src/ai/Decision.ts +70 -21
  369. package/src/ai/DecisionModel.ts +1 -1
  370. package/src/ai/LanguageModel.ts +141 -63
  371. package/src/ai/McpServer.ts +259 -145
  372. package/src/ai/Prompt.ts +24 -10
  373. package/src/ai/Response.ts +6 -3
  374. package/src/cli/Completions.ts +5 -0
  375. package/src/cli/Flag.ts +101 -0
  376. package/src/cli/Param.ts +96 -0
  377. package/src/cli/internal/command.ts +2 -1
  378. package/src/cli/internal/completions/bash.ts +4 -3
  379. package/src/cli/internal/completions/descriptor.ts +10 -1
  380. package/src/cli/internal/completions/fish.ts +4 -4
  381. package/src/cli/internal/completions/powershell.ts +5 -2
  382. package/src/cli/internal/completions/zsh.ts +7 -3
  383. package/src/cli/internal/parser.ts +12 -3
  384. package/src/cli/internal/wizard.ts +2 -1
  385. package/src/cluster/ClusterWorkflowEngine.ts +143 -36
  386. package/src/cluster/MessageStorage.ts +14 -3
  387. package/src/cluster/Runners.ts +88 -66
  388. package/src/cluster/Sharding.ts +12 -9
  389. package/src/cluster/internal/entityManager.ts +1 -1
  390. package/src/encoding/Sse.ts +70 -80
  391. package/src/graphql/GraphQL.ts +494 -0
  392. package/src/graphql/GraphQLClient.ts +924 -0
  393. package/src/graphql/GraphQLClientError.ts +542 -0
  394. package/src/graphql/GraphQLGroup.ts +167 -0
  395. package/src/graphql/GraphQLMiddleware.ts +253 -0
  396. package/src/graphql/GraphQLProtocol.ts +1540 -0
  397. package/src/graphql/GraphQLResolver.ts +1038 -0
  398. package/src/graphql/index.ts +48 -0
  399. package/src/http/FetchHttpClient.ts +6 -3
  400. package/src/http/FindMyWay/internal/router.ts +2 -1
  401. package/src/http/Headers.ts +6 -9
  402. package/src/http/HttpClient.ts +72 -11
  403. package/src/http/HttpClientError.ts +10 -6
  404. package/src/http/HttpClientRequest.ts +173 -7
  405. package/src/http/HttpEffect.ts +11 -5
  406. package/src/http/HttpMiddleware.ts +113 -34
  407. package/src/http/HttpRouter.ts +95 -13
  408. package/src/http/HttpServerError.ts +8 -4
  409. package/src/http/HttpServerRequest.ts +2 -2
  410. package/src/http/HttpServerResponse.ts +28 -16
  411. package/src/http/HttpStaticServer.ts +4 -10
  412. package/src/http/HttpTraceContext.ts +1 -1
  413. package/src/http/Multipart.ts +17 -1
  414. package/src/http/Url.ts +2 -1
  415. package/src/http/UrlParams.ts +225 -26
  416. package/src/http/internal/compression.ts +3 -17
  417. package/src/http/internal/compressionBody.ts +56 -0
  418. package/src/http/internal/decompression.ts +226 -0
  419. package/src/http/internal/tracing.ts +21 -4
  420. package/src/http/internal/urlParams.ts +5 -0
  421. package/src/http-api/HttpApiClient.ts +2 -1
  422. package/src/http-api/HttpApiScalar.ts +5 -0
  423. package/src/internal/core.ts +21 -1
  424. package/src/internal/dateTime.ts +13 -10
  425. package/src/internal/effect.ts +13 -7
  426. package/src/internal/graphql.ts +286 -0
  427. package/src/internal/graphqlHeaders.ts +11 -0
  428. package/src/internal/request.ts +31 -3
  429. package/src/internal/schema/toCodeDocument.ts +7 -1
  430. package/src/internal/schema/toJsonSchemaDocument.ts +34 -2
  431. package/src/internal/version.ts +1 -1
  432. package/src/net/Host.ts +72 -0
  433. package/src/net/NetAddress.ts +9 -0
  434. package/src/observability/Otlp.ts +18 -0
  435. package/src/observability/OtlpExporter.ts +14 -3
  436. package/src/observability/OtlpLogger.ts +31 -2
  437. package/src/observability/OtlpMetrics.ts +30 -1
  438. package/src/observability/OtlpTracer.ts +32 -3
  439. package/src/reactivity/AsyncResult.ts +31 -0
  440. package/src/reactivity/AtomRegistry.ts +3 -1
  441. package/src/rpc/RpcClient.ts +6 -1
  442. package/src/rpc/RpcServer.ts +55 -15
  443. package/src/socket/Socket.ts +6 -0
  444. package/src/sql/SqlClient.ts +9 -7
  445. package/src/testing/TestClock.ts +144 -29
  446. package/src/workflow/Activity.ts +1 -0
  447. package/src/workflow/DurableDeferred.ts +43 -5
  448. package/src/workflow/Workflow.ts +31 -5
  449. package/src/workflow/WorkflowEngine.ts +107 -25
package/src/Stream.ts CHANGED
@@ -20767,6 +20767,9 @@ export const mkUint8Array = <E, R>(self: Stream<Uint8Array, E, R>): Effect.Effec
20767
20767
  *
20768
20768
  * See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream.
20769
20769
  *
20770
+ * When `signal` aborts, the stream is interrupted even if the reader has
20771
+ * stopped pulling, and the `ReadableStream` closes.
20772
+ *
20770
20773
  * **Example** (Converting to a ReadableStream with services)
20771
20774
  *
20772
20775
  * ```ts import.meta.vitest
@@ -20795,6 +20798,9 @@ export const toReadableStreamWith: {
20795
20798
  *
20796
20799
  * See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream.
20797
20800
  *
20801
+ * When `signal` aborts, the stream is interrupted even if the reader has
20802
+ * stopped pulling, and the `ReadableStream` closes.
20803
+ *
20798
20804
  * **Example** (Converting to a ReadableStream with services)
20799
20805
  *
20800
20806
  * ```ts import.meta.vitest
@@ -20812,7 +20818,10 @@ export const toReadableStreamWith: {
20812
20818
  */
20813
20819
  <A, XR>(
20814
20820
  context: Context.Context<XR>,
20815
- options?: { readonly strategy?: QueuingStrategy<A> | undefined }
20821
+ options?: {
20822
+ readonly strategy?: QueuingStrategy<A> | undefined
20823
+ readonly signal?: AbortSignal | undefined
20824
+ }
20816
20825
  ): <E, R extends XR>(self: Stream<A, E, R>) => ReadableStream<A>
20817
20826
  /**
20818
20827
  * Converts the stream to a `ReadableStream` using the provided services.
@@ -20826,6 +20835,9 @@ export const toReadableStreamWith: {
20826
20835
  *
20827
20836
  * See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream.
20828
20837
  *
20838
+ * When `signal` aborts, the stream is interrupted even if the reader has
20839
+ * stopped pulling, and the `ReadableStream` closes.
20840
+ *
20829
20841
  * **Example** (Converting to a ReadableStream with services)
20830
20842
  *
20831
20843
  * ```ts import.meta.vitest
@@ -20844,18 +20856,28 @@ export const toReadableStreamWith: {
20844
20856
  <A, E, XR, R extends XR>(
20845
20857
  self: Stream<A, E, R>,
20846
20858
  context: Context.Context<XR>,
20847
- options?: { readonly strategy?: QueuingStrategy<A> | undefined }
20859
+ options?: {
20860
+ readonly strategy?: QueuingStrategy<A> | undefined
20861
+ readonly signal?: AbortSignal | undefined
20862
+ }
20848
20863
  ): ReadableStream<A>
20849
20864
  } = dual(
20850
20865
  (args) => isStream(args[0]),
20851
20866
  <A, E, XR, R extends XR>(
20852
20867
  self: Stream<A, E, R>,
20853
20868
  context: Context.Context<XR>,
20854
- options?: { readonly strategy?: QueuingStrategy<A> | undefined }
20869
+ options?: {
20870
+ readonly strategy?: QueuingStrategy<A> | undefined
20871
+ readonly signal?: AbortSignal | undefined
20872
+ }
20855
20873
  ): ReadableStream<A> => {
20856
20874
  let currentResolve: (() => void) | undefined = undefined
20857
20875
  let fiber: Fiber.Fiber<void, E> | undefined = undefined
20876
+ let cancelled = false
20858
20877
  const latch = Latch.makeUnsafe(false)
20878
+ const signal = options?.signal
20879
+ // Interrupting the fiber directly also stops a consumer waiting for a pull.
20880
+ const onAbort = () => fiber!.interruptUnsafe()
20859
20881
 
20860
20882
  return new ReadableStream<A>({
20861
20883
  start(controller) {
@@ -20872,12 +20894,18 @@ export const toReadableStreamWith: {
20872
20894
  context
20873
20895
  ))
20874
20896
  fiber.addObserver((exit) => {
20875
- if (exit._tag === "Failure") {
20897
+ signal?.removeEventListener("abort", onAbort)
20898
+ if (cancelled) return
20899
+ if (exit._tag === "Failure" && signal?.aborted !== true) {
20876
20900
  controller.error(Cause.squash(exit.cause))
20877
20901
  } else {
20878
20902
  controller.close()
20879
20903
  }
20880
20904
  })
20905
+ if (signal !== undefined && fiber.pollUnsafe() === undefined) {
20906
+ if (signal.aborted) onAbort()
20907
+ else signal.addEventListener("abort", onAbort, { once: true })
20908
+ }
20881
20909
  },
20882
20910
  pull() {
20883
20911
  return new Promise<void>((resolve) => {
@@ -20887,6 +20915,7 @@ export const toReadableStreamWith: {
20887
20915
  },
20888
20916
  cancel() {
20889
20917
  if (!fiber) return
20918
+ cancelled = true
20890
20919
  return Effect.runPromise(Effect.asVoid(Fiber.interrupt(fiber)))
20891
20920
  }
20892
20921
  }, options?.strategy)
package/src/String.ts CHANGED
@@ -1441,6 +1441,12 @@ export const stripMargin = (self: string): string => stripMarginWith(self, "|")
1441
1441
  /**
1442
1442
  * Converts a snake_case string to camelCase.
1443
1443
  *
1444
+ * **Details**
1445
+ *
1446
+ * Keeps the first character, then replaces each later underscore and the
1447
+ * character after it with that character uppercased. A trailing underscore is
1448
+ * dropped. Input made only of an even number of underscores returns `""`.
1449
+ *
1444
1450
  * **Example** (Converting snake_case to camelCase)
1445
1451
  *
1446
1452
  * ```ts import.meta.vitest
@@ -1455,10 +1461,10 @@ export const stripMargin = (self: string): string => stripMarginWith(self, "|")
1455
1461
  * @since 2.0.0
1456
1462
  */
1457
1463
  export const snakeToCamel = (self: string): string => {
1458
- if (self.length === 0) return self
1464
+ if (self.length === 0 || (self.length % 2 === 0 && self[0] === "_" && /^_+$/.test(self))) return ""
1459
1465
  let str = self[0]
1460
1466
  for (let i = 1; i < self.length; i++) {
1461
- str += self[i] === "_" ? self[++i].toUpperCase() : self[i]
1467
+ str += self[i] === "_" ? self.charAt(++i).toUpperCase() : self[i]
1462
1468
  }
1463
1469
  return str
1464
1470
  }
@@ -1466,6 +1472,12 @@ export const snakeToCamel = (self: string): string => {
1466
1472
  /**
1467
1473
  * Converts a snake_case string to PascalCase.
1468
1474
  *
1475
+ * **Details**
1476
+ *
1477
+ * Uppercases the first character, then replaces each later underscore and the
1478
+ * character after it with that character uppercased. A trailing underscore is
1479
+ * dropped. Input made only of an even number of underscores returns `""`.
1480
+ *
1469
1481
  * **Example** (Converting snake_case to PascalCase)
1470
1482
  *
1471
1483
  * ```ts import.meta.vitest
@@ -1480,10 +1492,10 @@ export const snakeToCamel = (self: string): string => {
1480
1492
  * @since 2.0.0
1481
1493
  */
1482
1494
  export const snakeToPascal = (self: string): string => {
1483
- if (self.length === 0) return self
1495
+ if (self.length === 0 || (self.length % 2 === 0 && self[0] === "_" && /^_+$/.test(self))) return ""
1484
1496
  let str = self[0].toUpperCase()
1485
1497
  for (let i = 1; i < self.length; i++) {
1486
- str += self[i] === "_" ? self[++i].toUpperCase() : self[i]
1498
+ str += self[i] === "_" ? self.charAt(++i).toUpperCase() : self[i]
1487
1499
  }
1488
1500
  return str
1489
1501
  }
@@ -1739,6 +1751,7 @@ const normalizeCase = (
1739
1751
  while (result.charAt(end - 1) === "\0") {
1740
1752
  end--
1741
1753
  }
1754
+ if (start >= end) return ""
1742
1755
 
1743
1756
  // Transform each token independently.
1744
1757
  return result.slice(start, end).split("\0").map(transform).join(delimiter)
package/src/TxRef.ts CHANGED
@@ -13,6 +13,7 @@
13
13
  * @since 4.0.0
14
14
  */
15
15
  import * as Effect from "./Effect.ts"
16
+ import type { TransactionMetaInner } from "./Effect.ts"
16
17
  import { dual } from "./Function.ts"
17
18
  import { pipeArguments } from "./Pipeable.ts"
18
19
  import type { Pipeable } from "./Pipeable.ts"
@@ -140,10 +141,11 @@ export const makeUnsafe = <A>(initial: A): TxRef<A> => ({
140
141
  })
141
142
 
142
143
  const journalEntry = <A>(state: Effect.Transaction["Service"], self: TxRef<A>) => {
143
- let entry = state.journal.get(self)
144
+ const journal = (state as TransactionMetaInner).journal
145
+ let entry = journal.get(self)
144
146
  if (entry === undefined) {
145
147
  entry = { version: self.version, value: self.value, written: false }
146
- state.journal.set(self, entry)
148
+ journal.set(self, entry)
147
149
  }
148
150
  return entry
149
151
  }
package/src/Utils.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  * @since 2.0.0
13
13
  */
14
14
  import type { Kind, TypeLambda } from "./HKT.ts"
15
- import { getStackTraceLimit } from "./internal/stackTraceLimit.ts"
15
+ import { getStackTraceLimit, setStackTraceLimit } from "./internal/stackTraceLimit.ts"
16
16
  import type * as Types from "./Types.ts"
17
17
 
18
18
  /**
@@ -209,10 +209,13 @@ const pickInternalCall = (): <A>(body: () => A) => A => {
209
209
  }
210
210
  }
211
211
 
212
- const isNotOptimizedAway = getStackTraceLimit() !== 0 &&
213
- standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true
214
-
215
- return isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId]
212
+ const limit = getStackTraceLimit()
213
+ if (limit === 0) return forced[InternalTypeId]
214
+ // Only the callback and internal call frames are needed for detection.
215
+ setStackTraceLimit(2)
216
+ const error = standard[InternalTypeId](() => new Error())
217
+ setStackTraceLimit(limit)
218
+ return error.stack?.includes(InternalTypeId) === true ? standard[InternalTypeId] : forced[InternalTypeId]
216
219
  }
217
220
 
218
221
  /** @internal */
package/src/ai/AiError.ts CHANGED
@@ -47,7 +47,9 @@ import * as Schema from "../Schema.ts"
47
47
  export const HttpRequestDetails = Schema.Struct({
48
48
  method: Schema.Literals(["GET", "POST", "PATCH", "PUT", "DELETE", "HEAD", "OPTIONS", "TRACE", "QUERY"]),
49
49
  url: Schema.String,
50
- urlParams: Schema.Array(Schema.Tuple([Schema.String, Schema.String])),
50
+ urlParams: Schema.Array(
51
+ Schema.Tuple([Schema.String, Schema.Union([Schema.String, Schema.Redacted(Schema.String)])])
52
+ ),
51
53
  hash: Schema.optional(Schema.String),
52
54
  headers: Schema.Record(
53
55
  Schema.String,
@@ -14,8 +14,8 @@ import type * as JsonSchema from "../JsonSchema.ts"
14
14
  import * as Rec from "../Record.ts"
15
15
  import * as Schema from "../Schema.ts"
16
16
  import * as InternalStructuredOutput from "./internal/structured-output.ts"
17
- import * as LanguageModel from "./LanguageModel.ts"
18
- import * as OpenAiStructuredOutput from "./OpenAiStructuredOutput.ts"
17
+ import type * as LanguageModel from "./LanguageModel.ts"
18
+ import type * as OpenAiStructuredOutput from "./OpenAiStructuredOutput.ts"
19
19
 
20
20
  /**
21
21
  * Converts a `Schema.Codec` to Anthropic structured-output JSON Schema and a
package/src/ai/Chat.ts CHANGED
@@ -228,7 +228,7 @@ export interface Chat {
228
228
  <Options extends NoExcessProperties<LanguageModel.GenerateTextOptions<{}>, Options>>(
229
229
  options: Options & { readonly toolkit?: undefined } & LanguageModel.GenerateTextOptions<{}>
230
230
  ): Effect.Effect<
231
- LanguageModel.GenerateTextResponse<{}>,
231
+ LanguageModel.GenerateTextResponse<{}, LanguageModel.ExtractToolParametersModeWithoutToolkit<Options>>,
232
232
  LanguageModel.ExtractError<Options>,
233
233
  LanguageModel.LanguageModel | LanguageModel.ExtractServices<Options>
234
234
  >
@@ -310,7 +310,7 @@ export interface Chat {
310
310
  <Options extends NoExcessProperties<LanguageModel.GenerateTextOptions<{}>, Options>>(
311
311
  options: Options & { readonly toolkit?: undefined } & LanguageModel.GenerateTextOptions<{}>
312
312
  ): Stream.Stream<
313
- Response.StreamPart<{}>,
313
+ Response.StreamPart<{}, LanguageModel.ExtractToolParametersModeWithoutToolkit<Options>>,
314
314
  LanguageModel.ExtractError<Options>,
315
315
  LanguageModel.LanguageModel | LanguageModel.ExtractServices<Options>
316
316
  >
@@ -28,9 +28,23 @@ export type TypeId = "~effect/ai/Decision"
28
28
  */
29
29
  export const TypeId: TypeId = "~effect/ai/Decision"
30
30
 
31
+ /**
32
+ * Decision instructions or descriptions: a string, JSON object, or JSON array.
33
+ *
34
+ * **Details**
35
+ *
36
+ * TypeScript interfaces lack the index signature required by `Schema.JsonObject`;
37
+ * use object literals, type aliases, or Schema types instead.
38
+ *
39
+ * @stability unstable
40
+ * @category models
41
+ * @since 4.0.5
42
+ */
43
+ export type Description = string | Schema.JsonObject | Schema.JsonArray
44
+
31
45
  /**
32
46
  * Decision that assigns the input one label out of a set of criteria.
33
- * `criteria` maps labels to descriptions.
47
+ * `criteria` maps labels to descriptions; use `null` for a label without a description.
34
48
  *
35
49
  * @see {@link classify} for the constructor
36
50
  * @see {@link ClassifyAnswer} for the answer produced by this decision
@@ -41,13 +55,14 @@ export const TypeId: TypeId = "~effect/ai/Decision"
41
55
  */
42
56
  export interface Classify<Label extends string> {
43
57
  readonly _tag: "Classify"
44
- readonly instructions: string
45
- readonly criteria: { readonly [L in Label]: string }
58
+ readonly instructions: Description
59
+ readonly criteria: { readonly [L in Label]: Description | null }
46
60
  }
47
61
 
48
62
  /**
49
63
  * Decision that places the input on an ordered scale of criteria.
50
- * `criteria` lists levels from lowest to highest.
64
+ * `criteria` lists levels from lowest to highest, with labels for answers and
65
+ * descriptions for the provider.
51
66
  *
52
67
  * @see {@link rate} for the constructor
53
68
  * @see {@link RateAnswer} for the answer produced by this decision
@@ -58,8 +73,8 @@ export interface Classify<Label extends string> {
58
73
  */
59
74
  export interface Rate<Level extends string> {
60
75
  readonly _tag: "Rate"
61
- readonly instructions: string
62
- readonly criteria: ReadonlyArray<Level>
76
+ readonly instructions: Description
77
+ readonly criteria: ReadonlyArray<{ readonly label: Level; readonly description: Description }>
63
78
  }
64
79
 
65
80
  /**
@@ -76,10 +91,10 @@ export interface Rate<Level extends string> {
76
91
  */
77
92
  export interface Probability {
78
93
  readonly _tag: "Probability"
79
- readonly instructions: string
94
+ readonly instructions: Description
80
95
  readonly criteria?: {
81
- readonly false: string
82
- readonly true: string
96
+ readonly false: Description
97
+ readonly true: Description
83
98
  } | undefined
84
99
  }
85
100
 
@@ -110,8 +125,9 @@ export interface ClassifyAnswer<Label extends string> {
110
125
  /**
111
126
  * Answer to a {@link Rate} decision.
112
127
  * `rating` is the probability-weighted position on the scale and may fall
113
- * between two levels, within `[0, criteria.length - 1]`. `label` is the level
114
- * with the highest probability, choosing the first criteria entry on ties.
128
+ * between two levels, within `[0, criteria.length - 1]`. `label` is the label
129
+ * of the level with the highest probability, choosing the first criteria entry
130
+ * on ties.
115
131
  * `confidence` is an optional, provider-defined measure in `[0, 1]`.
116
132
  *
117
133
  * @stability unstable
@@ -176,6 +192,7 @@ export interface Definition<Input extends Schema.Constraint, Decisions extends R
176
192
 
177
193
  /**
178
194
  * Creates a classification decision from labelled criteria.
195
+ * Descriptions can be `null` when the label needs no explanation.
179
196
  * Throws if fewer than two labels are supplied.
180
197
  *
181
198
  * **Example** (Choosing a department)
@@ -201,8 +218,8 @@ export interface Definition<Input extends Schema.Constraint, Decisions extends R
201
218
  * @since 4.0.0
202
219
  */
203
220
  export const classify = <Label extends string>(options: {
204
- readonly instructions: string
205
- readonly criteria: { readonly [L in Label]: string }
221
+ readonly instructions: Description
222
+ readonly criteria: { readonly [L in Label]: Description | null }
206
223
  }): Classify<Label> => {
207
224
  if (Object.keys(options.criteria).length < 2) {
208
225
  throw new Error("Decision.classify: criteria must contain at least two labels")
@@ -216,7 +233,9 @@ export const classify = <Label extends string>(options: {
216
233
 
217
234
  /**
218
235
  * Creates a rating decision from an ordered list of criteria.
219
- * Throws if fewer than two levels or duplicate levels are supplied.
236
+ * Strings serve as both label and description; use `{ label, description }`
237
+ * to separate them. Answers use the label.
238
+ * Throws if fewer than two levels or duplicate labels are supplied.
220
239
  *
221
240
  * **Example** (Rating frustration)
222
241
  *
@@ -229,6 +248,33 @@ export const classify = <Label extends string>(options: {
229
248
  * })
230
249
  * ```
231
250
  *
251
+ * **Example** (Describing levels with structure)
252
+ *
253
+ * ```ts
254
+ * import { Decision } from "effect/ai"
255
+ *
256
+ * const severity = Decision.rate({
257
+ * instructions: "How severe is the reported issue?",
258
+ * criteria: [
259
+ * "cosmetic",
260
+ * {
261
+ * label: "degraded",
262
+ * description: {
263
+ * what: "Broken or degraded feature, but workaround exists",
264
+ * examples: ["export fails in one browser but works in another"]
265
+ * }
266
+ * },
267
+ * {
268
+ * label: "blocking",
269
+ * description: {
270
+ * what: "Blocking issue; no workaround exists",
271
+ * examples: ["cannot log in", "data loss"]
272
+ * }
273
+ * }
274
+ * ]
275
+ * })
276
+ * ```
277
+ *
232
278
  * @see {@link classify} for unordered labels
233
279
  *
234
280
  * @stability unstable
@@ -236,19 +282,22 @@ export const classify = <Label extends string>(options: {
236
282
  * @since 4.0.0
237
283
  */
238
284
  export const rate = <const Level extends string>(options: {
239
- readonly instructions: string
240
- readonly criteria: ReadonlyArray<Level>
285
+ readonly instructions: Description
286
+ readonly criteria: ReadonlyArray<Level | { readonly label: Level; readonly description: Description }>
241
287
  }): Rate<Level> => {
242
288
  if (options.criteria.length < 2) {
243
289
  throw new Error("Decision.rate: criteria must contain at least two levels")
244
290
  }
245
- if (new Set(options.criteria).size !== options.criteria.length) {
291
+ const criteria = options.criteria.map((level) =>
292
+ typeof level === "string" ? { label: level, description: level } : level
293
+ )
294
+ if (new Set(criteria.map((level) => level.label)).size !== criteria.length) {
246
295
  throw new Error("Decision.rate: criteria must contain distinct levels")
247
296
  }
248
297
  return {
249
298
  _tag: "Rate",
250
299
  instructions: options.instructions,
251
- criteria: options.criteria
300
+ criteria
252
301
  }
253
302
  }
254
303
 
@@ -287,10 +336,10 @@ export const rate = <const Level extends string>(options: {
287
336
  * @since 4.0.0
288
337
  */
289
338
  export const probability = (options: {
290
- readonly instructions: string
339
+ readonly instructions: Description
291
340
  readonly criteria?: {
292
- readonly false: string
293
- readonly true: string
341
+ readonly false: Description
342
+ readonly true: Description
294
343
  } | undefined
295
344
  }): Probability => ({
296
345
  _tag: "Probability",
@@ -290,7 +290,7 @@ const validateAnswer = (
290
290
  return { label: answer.label, probabilities, ...(confidence === undefined ? undefined : { confidence }) }
291
291
  }
292
292
  case "Rate": {
293
- const levels = decision.criteria
293
+ const levels = decision.criteria.map((level) => level.label)
294
294
  if (!isFiniteNumber(answer.rating) || answer.rating < 0 || answer.rating > levels.length - 1) {
295
295
  return invalidOutput(`Provider returned a rating outside [0, ${levels.length - 1}] for decision "${key}"`)
296
296
  }