effect 4.1.0 → 4.1.2

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 (445) hide show
  1. package/README.md +30 -0
  2. package/THIRD_PARTY_NOTICES.md +62 -0
  3. package/ai-docs/package.json +2 -2
  4. package/dist/BigDecimal.d.ts +139 -7
  5. package/dist/BigDecimal.d.ts.map +1 -1
  6. package/dist/BigDecimal.js +83 -14
  7. package/dist/BigDecimal.js.map +1 -1
  8. package/dist/ByteSize.d.ts.map +1 -1
  9. package/dist/ByteSize.js +27 -14
  10. package/dist/ByteSize.js.map +1 -1
  11. package/dist/Equal.d.ts +2 -2
  12. package/dist/Equal.d.ts.map +1 -1
  13. package/dist/Equal.js +3 -3
  14. package/dist/Equal.js.map +1 -1
  15. package/dist/Hash.d.ts +3 -2
  16. package/dist/Hash.d.ts.map +1 -1
  17. package/dist/Hash.js +5 -4
  18. package/dist/Hash.js.map +1 -1
  19. package/dist/Iterable.d.ts.map +1 -1
  20. package/dist/Iterable.js +38 -32
  21. package/dist/Iterable.js.map +1 -1
  22. package/dist/JsonSchema.d.ts.map +1 -1
  23. package/dist/JsonSchema.js +27 -6
  24. package/dist/JsonSchema.js.map +1 -1
  25. package/dist/MutableRef.d.ts.map +1 -1
  26. package/dist/MutableRef.js +0 -7
  27. package/dist/MutableRef.js.map +1 -1
  28. package/dist/Path.d.ts.map +1 -1
  29. package/dist/Path.js +5 -1
  30. package/dist/Path.js.map +1 -1
  31. package/dist/Pool.d.ts.map +1 -1
  32. package/dist/Pool.js +2 -1
  33. package/dist/Pool.js.map +1 -1
  34. package/dist/Ref.d.ts.map +1 -1
  35. package/dist/Ref.js +0 -8
  36. package/dist/Ref.js.map +1 -1
  37. package/dist/Schedule.d.ts.map +1 -1
  38. package/dist/Schedule.js +8 -3
  39. package/dist/Schedule.js.map +1 -1
  40. package/dist/Schema.d.ts +2 -1
  41. package/dist/Schema.d.ts.map +1 -1
  42. package/dist/Schema.js +2 -1
  43. package/dist/Schema.js.map +1 -1
  44. package/dist/SchemaRepresentation.d.ts +4 -2
  45. package/dist/SchemaRepresentation.d.ts.map +1 -1
  46. package/dist/SchemaRepresentation.js +4 -2
  47. package/dist/SchemaRepresentation.js.map +1 -1
  48. package/dist/SchemaTransformation.d.ts +2 -2
  49. package/dist/SchemaTransformation.js +2 -2
  50. package/dist/Stream.d.ts.map +1 -1
  51. package/dist/Stream.js +6 -5
  52. package/dist/Stream.js.map +1 -1
  53. package/dist/ai/McpClient.d.ts +171 -19
  54. package/dist/ai/McpClient.d.ts.map +1 -1
  55. package/dist/ai/McpClient.js +277 -66
  56. package/dist/ai/McpClient.js.map +1 -1
  57. package/dist/ai/McpSchema.d.ts +108 -0
  58. package/dist/ai/McpSchema.d.ts.map +1 -1
  59. package/dist/ai/McpSchema.js +99 -0
  60. package/dist/ai/McpSchema.js.map +1 -1
  61. package/dist/ai/McpServer.d.ts +120 -6
  62. package/dist/ai/McpServer.d.ts.map +1 -1
  63. package/dist/ai/McpServer.js +258 -49
  64. package/dist/ai/McpServer.js.map +1 -1
  65. package/dist/ai/Prompt.d.ts.map +1 -1
  66. package/dist/ai/Prompt.js +20 -11
  67. package/dist/ai/Prompt.js.map +1 -1
  68. package/dist/ai/Tool.d.ts.map +1 -1
  69. package/dist/ai/Tool.js +5 -7
  70. package/dist/ai/Tool.js.map +1 -1
  71. package/dist/ai/internal/mcpCore.js +72 -3
  72. package/dist/ai/internal/mcpCore.js.map +1 -1
  73. package/dist/ai/internal/mcpProtocol/v2024_11_05.js +3 -1
  74. package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
  75. package/dist/ai/internal/mcpProtocol/v2025_03_26.js +3 -1
  76. package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
  77. package/dist/ai/internal/mcpProtocol/v2025_06_18.js +3 -1
  78. package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
  79. package/dist/ai/internal/mcpProtocol/v2025_11_25.js +3 -1
  80. package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
  81. package/dist/ai/internal/mcpProtocol/v2026_07_28.js +44 -8
  82. package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
  83. package/dist/ai/internal/mcpProtocol.js +12 -0
  84. package/dist/ai/internal/mcpProtocol.js.map +1 -1
  85. package/dist/ai/internal/mcpRuntime.js +3 -3
  86. package/dist/ai/internal/mcpRuntime.js.map +1 -1
  87. package/dist/ai/internal/mcpSkills.d.ts +2 -0
  88. package/dist/ai/internal/mcpSkills.d.ts.map +1 -0
  89. package/dist/ai/internal/mcpSkills.js +428 -0
  90. package/dist/ai/internal/mcpSkills.js.map +1 -0
  91. package/dist/ai/internal/structured-output.js +11 -2
  92. package/dist/ai/internal/structured-output.js.map +1 -1
  93. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  94. package/dist/cluster/ClusterWorkflowEngine.js +30 -11
  95. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  96. package/dist/cluster/Entity.d.ts +26 -0
  97. package/dist/cluster/Entity.d.ts.map +1 -1
  98. package/dist/cluster/Entity.js.map +1 -1
  99. package/dist/cluster/MessageStorage.d.ts +6 -6
  100. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  101. package/dist/cluster/MessageStorage.js +1 -3
  102. package/dist/cluster/MessageStorage.js.map +1 -1
  103. package/dist/cluster/Reply.d.ts +1 -1
  104. package/dist/cluster/Reply.d.ts.map +1 -1
  105. package/dist/cluster/Reply.js.map +1 -1
  106. package/dist/cluster/Runners.d.ts.map +1 -1
  107. package/dist/cluster/Runners.js +13 -2
  108. package/dist/cluster/Runners.js.map +1 -1
  109. package/dist/cluster/Sharding.d.ts +13 -0
  110. package/dist/cluster/Sharding.d.ts.map +1 -1
  111. package/dist/cluster/Sharding.js +4 -1
  112. package/dist/cluster/Sharding.js.map +1 -1
  113. package/dist/cluster/internal/clusterAbandon.d.ts.map +1 -1
  114. package/dist/cluster/internal/clusterAbandon.js +6 -4
  115. package/dist/cluster/internal/clusterAbandon.js.map +1 -1
  116. package/dist/cluster/internal/entityManager.js +63 -11
  117. package/dist/cluster/internal/entityManager.js.map +1 -1
  118. package/dist/cluster/internal/transactionNotifications.d.ts +5 -0
  119. package/dist/cluster/internal/transactionNotifications.d.ts.map +1 -0
  120. package/dist/cluster/internal/transactionNotifications.js +5 -0
  121. package/dist/cluster/internal/transactionNotifications.js.map +1 -0
  122. package/dist/crypto/Aead.d.ts +2 -1
  123. package/dist/crypto/Aead.d.ts.map +1 -1
  124. package/dist/crypto/Aead.js +2 -2
  125. package/dist/crypto/Aead.js.map +1 -1
  126. package/dist/crypto/Cipher.d.ts +2 -1
  127. package/dist/crypto/Cipher.d.ts.map +1 -1
  128. package/dist/crypto/Cipher.js +2 -2
  129. package/dist/crypto/Cipher.js.map +1 -1
  130. package/dist/crypto/KeyAgreement.d.ts +3 -2
  131. package/dist/crypto/KeyAgreement.d.ts.map +1 -1
  132. package/dist/crypto/KeyAgreement.js +2 -2
  133. package/dist/crypto/KeyAgreement.js.map +1 -1
  134. package/dist/crypto/KeyFormat.d.ts +33 -1
  135. package/dist/crypto/KeyFormat.d.ts.map +1 -1
  136. package/dist/crypto/KeyFormat.js.map +1 -1
  137. package/dist/crypto/KeyWrap.d.ts +4 -3
  138. package/dist/crypto/KeyWrap.d.ts.map +1 -1
  139. package/dist/crypto/KeyWrap.js +2 -2
  140. package/dist/crypto/KeyWrap.js.map +1 -1
  141. package/dist/crypto/Mac.d.ts +2 -1
  142. package/dist/crypto/Mac.d.ts.map +1 -1
  143. package/dist/crypto/Mac.js +2 -2
  144. package/dist/crypto/Mac.js.map +1 -1
  145. package/dist/crypto/Signature.d.ts +3 -2
  146. package/dist/crypto/Signature.d.ts.map +1 -1
  147. package/dist/crypto/Signature.js +2 -2
  148. package/dist/crypto/Signature.js.map +1 -1
  149. package/dist/crypto/WebCrypto.d.ts +19 -0
  150. package/dist/crypto/WebCrypto.d.ts.map +1 -1
  151. package/dist/crypto/WebCrypto.js.map +1 -1
  152. package/dist/crypto/internal/asymmetric.js.map +1 -1
  153. package/dist/crypto/internal/key.js +3 -2
  154. package/dist/crypto/internal/key.js.map +1 -1
  155. package/dist/encoding/Base64Url.d.ts.map +1 -1
  156. package/dist/encoding/Base64Url.js +26 -3
  157. package/dist/encoding/Base64Url.js.map +1 -1
  158. package/dist/encoding/Json5.d.ts +44 -0
  159. package/dist/encoding/Json5.d.ts.map +1 -0
  160. package/dist/encoding/Json5.js +56 -0
  161. package/dist/encoding/Json5.js.map +1 -0
  162. package/dist/encoding/Jsonc.d.ts +47 -0
  163. package/dist/encoding/Jsonc.d.ts.map +1 -0
  164. package/dist/encoding/Jsonc.js +120 -0
  165. package/dist/encoding/Jsonc.js.map +1 -0
  166. package/dist/encoding/Ndjson.d.ts +5 -4
  167. package/dist/encoding/Ndjson.d.ts.map +1 -1
  168. package/dist/encoding/Ndjson.js +6 -5
  169. package/dist/encoding/Ndjson.js.map +1 -1
  170. package/dist/encoding/SchemaBinary.d.ts +94 -0
  171. package/dist/encoding/SchemaBinary.d.ts.map +1 -1
  172. package/dist/encoding/SchemaBinary.js +219 -6
  173. package/dist/encoding/SchemaBinary.js.map +1 -1
  174. package/dist/encoding/Sse.d.ts +3 -1
  175. package/dist/encoding/Sse.d.ts.map +1 -1
  176. package/dist/encoding/Sse.js +5 -3
  177. package/dist/encoding/Sse.js.map +1 -1
  178. package/dist/encoding/index.d.ts +10 -0
  179. package/dist/encoding/index.d.ts.map +1 -1
  180. package/dist/encoding/index.js +10 -0
  181. package/dist/encoding/index.js.map +1 -1
  182. package/dist/eventlog/EventLog.d.ts +7 -0
  183. package/dist/eventlog/EventLog.d.ts.map +1 -1
  184. package/dist/eventlog/EventLog.js +7 -0
  185. package/dist/eventlog/EventLog.js.map +1 -1
  186. package/dist/eventlog/EventLogServer.d.ts +7 -1
  187. package/dist/eventlog/EventLogServer.d.ts.map +1 -1
  188. package/dist/eventlog/EventLogServer.js +55 -24
  189. package/dist/eventlog/EventLogServer.js.map +1 -1
  190. package/dist/eventlog/EventLogServerEncrypted.d.ts +10 -0
  191. package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
  192. package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
  193. package/dist/eventlog/EventLogServerUnencrypted.d.ts +17 -0
  194. package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
  195. package/dist/eventlog/EventLogServerUnencrypted.js +14 -2
  196. package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
  197. package/dist/eventlog/EventLogSessionAuth.d.ts +21 -0
  198. package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
  199. package/dist/eventlog/EventLogSessionAuth.js +22 -0
  200. package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
  201. package/dist/graphql/GraphQLClient.d.ts +3 -1
  202. package/dist/graphql/GraphQLClient.d.ts.map +1 -1
  203. package/dist/graphql/GraphQLClient.js.map +1 -1
  204. package/dist/graphql/GraphQLClientError.d.ts +14 -9
  205. package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
  206. package/dist/graphql/GraphQLClientError.js +14 -21
  207. package/dist/graphql/GraphQLClientError.js.map +1 -1
  208. package/dist/graphql/GraphQLProtocol.d.ts +12 -3
  209. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
  210. package/dist/graphql/GraphQLProtocol.js +4 -1
  211. package/dist/graphql/GraphQLProtocol.js.map +1 -1
  212. package/dist/http/HttpClient.d.ts +204 -16
  213. package/dist/http/HttpClient.d.ts.map +1 -1
  214. package/dist/http/HttpClient.js +93 -13
  215. package/dist/http/HttpClient.js.map +1 -1
  216. package/dist/http/HttpServerRequest.d.ts.map +1 -1
  217. package/dist/http/HttpServerRequest.js +38 -22
  218. package/dist/http/HttpServerRequest.js.map +1 -1
  219. package/dist/http/internal/mimeTypes.d.ts +4 -1
  220. package/dist/http/internal/mimeTypes.d.ts.map +1 -1
  221. package/dist/http/internal/mimeTypes.js +4 -1
  222. package/dist/http/internal/mimeTypes.js.map +1 -1
  223. package/dist/http-api/HttpApiSchema.js +1 -1
  224. package/dist/http-api/HttpApiSchema.js.map +1 -1
  225. package/dist/internal/dateTime.js +66 -27
  226. package/dist/internal/dateTime.js.map +1 -1
  227. package/dist/internal/effect.js +10 -0
  228. package/dist/internal/effect.js.map +1 -1
  229. package/dist/internal/glob.js +234 -56
  230. package/dist/internal/glob.js.map +1 -1
  231. package/dist/internal/graphql.js +21 -7
  232. package/dist/internal/graphql.js.map +1 -1
  233. package/dist/internal/graphqlHeaders.d.ts +7 -0
  234. package/dist/internal/graphqlHeaders.d.ts.map +1 -1
  235. package/dist/internal/graphqlHeaders.js +11 -0
  236. package/dist/internal/graphqlHeaders.js.map +1 -1
  237. package/dist/internal/jsonParser.d.ts +5 -0
  238. package/dist/internal/jsonParser.d.ts.map +1 -0
  239. package/dist/internal/jsonParser.js +280 -0
  240. package/dist/internal/jsonParser.js.map +1 -0
  241. package/dist/internal/persistence.js +8 -1
  242. package/dist/internal/persistence.js.map +1 -1
  243. package/dist/internal/request.js +29 -42
  244. package/dist/internal/request.js.map +1 -1
  245. package/dist/internal/schema/fromJsonSchemaDocument.js +7 -8
  246. package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
  247. package/dist/internal/sql.js +16 -0
  248. package/dist/internal/sql.js.map +1 -1
  249. package/dist/internal/version.js +1 -1
  250. package/dist/jose/JoseError.d.ts +285 -0
  251. package/dist/jose/JoseError.d.ts.map +1 -0
  252. package/dist/jose/JoseError.js +269 -0
  253. package/dist/jose/JoseError.js.map +1 -0
  254. package/dist/jose/Jwe.d.ts +128 -0
  255. package/dist/jose/Jwe.d.ts.map +1 -0
  256. package/dist/jose/Jwe.js +134 -0
  257. package/dist/jose/Jwe.js.map +1 -0
  258. package/dist/jose/Jwk.d.ts +597 -0
  259. package/dist/jose/Jwk.d.ts.map +1 -0
  260. package/dist/jose/Jwk.js +503 -0
  261. package/dist/jose/Jwk.js.map +1 -0
  262. package/dist/jose/Jwks.d.ts +236 -0
  263. package/dist/jose/Jwks.d.ts.map +1 -0
  264. package/dist/jose/Jwks.js +306 -0
  265. package/dist/jose/Jwks.js.map +1 -0
  266. package/dist/jose/Jws.d.ts +177 -0
  267. package/dist/jose/Jws.d.ts.map +1 -0
  268. package/dist/jose/Jws.js +183 -0
  269. package/dist/jose/Jws.js.map +1 -0
  270. package/dist/jose/Jwt.d.ts +270 -0
  271. package/dist/jose/Jwt.d.ts.map +1 -0
  272. package/dist/jose/Jwt.js +293 -0
  273. package/dist/jose/Jwt.js.map +1 -0
  274. package/dist/jose/index.d.ts +51 -0
  275. package/dist/jose/index.d.ts.map +1 -0
  276. package/dist/jose/index.js +52 -0
  277. package/dist/jose/index.js.map +1 -0
  278. package/dist/jose/internal/compact.d.ts +2 -0
  279. package/dist/jose/internal/compact.d.ts.map +1 -0
  280. package/dist/jose/internal/compact.js +179 -0
  281. package/dist/jose/internal/compact.js.map +1 -0
  282. package/dist/net/Host.d.ts.map +1 -1
  283. package/dist/net/Host.js +5 -10
  284. package/dist/net/Host.js.map +1 -1
  285. package/dist/observability/OtlpExporter.d.ts +4 -0
  286. package/dist/observability/OtlpExporter.d.ts.map +1 -1
  287. package/dist/observability/OtlpExporter.js +40 -12
  288. package/dist/observability/OtlpExporter.js.map +1 -1
  289. package/dist/observability/OtlpSerialization.d.ts +1 -1
  290. package/dist/observability/OtlpSerialization.d.ts.map +1 -1
  291. package/dist/observability/OtlpSerialization.js +10 -4
  292. package/dist/observability/OtlpSerialization.js.map +1 -1
  293. package/dist/observability/internal/otlpProtobuf.js +3 -3
  294. package/dist/observability/internal/otlpProtobuf.js.map +1 -1
  295. package/dist/observability/internal/protobuf.js +6 -0
  296. package/dist/observability/internal/protobuf.js.map +1 -1
  297. package/dist/persistence/CircuitBreaker.d.ts +98 -38
  298. package/dist/persistence/CircuitBreaker.d.ts.map +1 -1
  299. package/dist/persistence/CircuitBreaker.js +67 -29
  300. package/dist/persistence/CircuitBreaker.js.map +1 -1
  301. package/dist/persistence/RateLimiter.d.ts +15 -0
  302. package/dist/persistence/RateLimiter.d.ts.map +1 -1
  303. package/dist/persistence/RateLimiter.js +76 -16
  304. package/dist/persistence/RateLimiter.js.map +1 -1
  305. package/dist/persistence/index.d.ts +1 -1
  306. package/dist/persistence/index.js +1 -1
  307. package/dist/reactivity/AtomRegistry.js +17 -7
  308. package/dist/reactivity/AtomRegistry.js.map +1 -1
  309. package/dist/rpc/Rpc.d.ts +1 -1
  310. package/dist/rpc/Rpc.d.ts.map +1 -1
  311. package/dist/rpc/Rpc.js.map +1 -1
  312. package/dist/rpc/RpcClient.d.ts +14 -2
  313. package/dist/rpc/RpcClient.d.ts.map +1 -1
  314. package/dist/rpc/RpcClient.js +38 -21
  315. package/dist/rpc/RpcClient.js.map +1 -1
  316. package/dist/rpc/RpcMessage.d.ts +3 -2
  317. package/dist/rpc/RpcMessage.d.ts.map +1 -1
  318. package/dist/rpc/RpcMessage.js.map +1 -1
  319. package/dist/rpc/RpcServer.d.ts.map +1 -1
  320. package/dist/rpc/RpcServer.js +10 -1
  321. package/dist/rpc/RpcServer.js.map +1 -1
  322. package/dist/sql/Migrator.d.ts +9 -1
  323. package/dist/sql/Migrator.d.ts.map +1 -1
  324. package/dist/sql/Migrator.js +18 -6
  325. package/dist/sql/Migrator.js.map +1 -1
  326. package/dist/sql/SqlClient.d.ts +46 -3
  327. package/dist/sql/SqlClient.d.ts.map +1 -1
  328. package/dist/sql/SqlClient.js +40 -15
  329. package/dist/sql/SqlClient.js.map +1 -1
  330. package/dist/sql/Statement.d.ts +46 -3
  331. package/dist/sql/Statement.d.ts.map +1 -1
  332. package/dist/sql/Statement.js +32 -26
  333. package/dist/sql/Statement.js.map +1 -1
  334. package/dist/workflow/Workflow.d.ts +4 -0
  335. package/dist/workflow/Workflow.d.ts.map +1 -1
  336. package/dist/workflow/Workflow.js.map +1 -1
  337. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  338. package/dist/workflow/WorkflowEngine.js +5 -0
  339. package/dist/workflow/WorkflowEngine.js.map +1 -1
  340. package/package.json +7 -3
  341. package/src/BigDecimal.ts +170 -16
  342. package/src/ByteSize.ts +29 -14
  343. package/src/Equal.ts +3 -3
  344. package/src/Hash.ts +5 -4
  345. package/src/Iterable.ts +28 -19
  346. package/src/JsonSchema.ts +45 -7
  347. package/src/MutableRef.ts +1 -8
  348. package/src/Path.ts +6 -1
  349. package/src/Pool.ts +2 -1
  350. package/src/Ref.ts +0 -8
  351. package/src/Schedule.ts +8 -6
  352. package/src/Schema.ts +3 -2
  353. package/src/SchemaRepresentation.ts +4 -2
  354. package/src/SchemaTransformation.ts +2 -2
  355. package/src/Stream.ts +6 -5
  356. package/src/ai/McpClient.ts +488 -91
  357. package/src/ai/McpSchema.ts +119 -0
  358. package/src/ai/McpServer.ts +302 -56
  359. package/src/ai/Prompt.ts +16 -11
  360. package/src/ai/Tool.ts +5 -10
  361. package/src/ai/internal/mcpCore.ts +165 -12
  362. package/src/ai/internal/mcpProtocol/v2024_11_05.ts +3 -1
  363. package/src/ai/internal/mcpProtocol/v2025_03_26.ts +3 -1
  364. package/src/ai/internal/mcpProtocol/v2025_06_18.ts +3 -1
  365. package/src/ai/internal/mcpProtocol/v2025_11_25.ts +3 -1
  366. package/src/ai/internal/mcpProtocol/v2026_07_28.ts +42 -9
  367. package/src/ai/internal/mcpProtocol.ts +15 -0
  368. package/src/ai/internal/mcpRuntime.ts +6 -3
  369. package/src/ai/internal/mcpSkills.ts +480 -0
  370. package/src/ai/internal/structured-output.ts +10 -4
  371. package/src/cluster/ClusterWorkflowEngine.ts +48 -33
  372. package/src/cluster/Entity.ts +52 -0
  373. package/src/cluster/MessageStorage.ts +3 -6
  374. package/src/cluster/Reply.ts +1 -1
  375. package/src/cluster/Runners.ts +16 -2
  376. package/src/cluster/Sharding.ts +17 -1
  377. package/src/cluster/internal/clusterAbandon.ts +7 -7
  378. package/src/cluster/internal/entityManager.ts +89 -15
  379. package/src/cluster/internal/transactionNotifications.ts +7 -0
  380. package/src/crypto/Aead.ts +3 -3
  381. package/src/crypto/Cipher.ts +3 -3
  382. package/src/crypto/KeyAgreement.ts +4 -4
  383. package/src/crypto/KeyFormat.ts +30 -1
  384. package/src/crypto/KeyWrap.ts +6 -6
  385. package/src/crypto/Mac.ts +3 -3
  386. package/src/crypto/Signature.ts +4 -4
  387. package/src/crypto/WebCrypto.ts +20 -0
  388. package/src/crypto/internal/asymmetric.ts +2 -1
  389. package/src/crypto/internal/key.ts +12 -5
  390. package/src/encoding/Base64Url.ts +27 -3
  391. package/src/encoding/Json5.ts +59 -0
  392. package/src/encoding/Jsonc.ts +126 -0
  393. package/src/encoding/Ndjson.ts +6 -5
  394. package/src/encoding/SchemaBinary.ts +228 -7
  395. package/src/encoding/Sse.ts +5 -3
  396. package/src/encoding/index.ts +12 -0
  397. package/src/eventlog/EventLog.ts +7 -0
  398. package/src/eventlog/EventLogServer.ts +67 -24
  399. package/src/eventlog/EventLogServerEncrypted.ts +5 -0
  400. package/src/eventlog/EventLogServerUnencrypted.ts +19 -2
  401. package/src/eventlog/EventLogSessionAuth.ts +26 -0
  402. package/src/graphql/GraphQLClient.ts +3 -1
  403. package/src/graphql/GraphQLClientError.ts +15 -22
  404. package/src/graphql/GraphQLProtocol.ts +12 -3
  405. package/src/http/HttpClient.ts +244 -33
  406. package/src/http/HttpServerRequest.ts +61 -23
  407. package/src/http/internal/mimeTypes.ts +4 -1
  408. package/src/http-api/HttpApiSchema.ts +1 -1
  409. package/src/internal/dateTime.ts +80 -27
  410. package/src/internal/effect.ts +6 -0
  411. package/src/internal/glob.ts +279 -63
  412. package/src/internal/graphql.ts +27 -9
  413. package/src/internal/graphqlHeaders.ts +13 -0
  414. package/src/internal/jsonParser.ts +307 -0
  415. package/src/internal/persistence.ts +9 -1
  416. package/src/internal/request.ts +51 -58
  417. package/src/internal/schema/fromJsonSchemaDocument.ts +11 -10
  418. package/src/internal/sql.ts +25 -0
  419. package/src/internal/version.ts +1 -1
  420. package/src/jose/JoseError.ts +329 -0
  421. package/src/jose/Jwe.ts +196 -0
  422. package/src/jose/Jwk.ts +777 -0
  423. package/src/jose/Jwks.ts +418 -0
  424. package/src/jose/Jws.ts +312 -0
  425. package/src/jose/Jwt.ts +493 -0
  426. package/src/jose/index.ts +58 -0
  427. package/src/jose/internal/compact.ts +195 -0
  428. package/src/net/Host.ts +5 -10
  429. package/src/observability/OtlpExporter.ts +42 -18
  430. package/src/observability/OtlpSerialization.ts +13 -5
  431. package/src/observability/internal/otlpProtobuf.ts +6 -6
  432. package/src/observability/internal/protobuf.ts +10 -0
  433. package/src/persistence/CircuitBreaker.ts +113 -48
  434. package/src/persistence/RateLimiter.ts +97 -19
  435. package/src/persistence/index.ts +1 -1
  436. package/src/reactivity/AtomRegistry.ts +19 -8
  437. package/src/rpc/Rpc.ts +3 -1
  438. package/src/rpc/RpcClient.ts +44 -24
  439. package/src/rpc/RpcMessage.ts +3 -2
  440. package/src/rpc/RpcServer.ts +12 -1
  441. package/src/sql/Migrator.ts +35 -18
  442. package/src/sql/SqlClient.ts +91 -22
  443. package/src/sql/Statement.ts +60 -35
  444. package/src/workflow/Workflow.ts +4 -0
  445. package/src/workflow/WorkflowEngine.ts +5 -0
@@ -0,0 +1,480 @@
1
+ /**
2
+ * The Skills extension (SEP-2640): its wire vocabulary, the catalog behind a
3
+ * static skill, and the handlers shared by the sessionful adapters.
4
+ *
5
+ * @internal
6
+ */
7
+ import * as Cause from "../../Cause.ts"
8
+ import * as Digest from "../../crypto/Digest.ts"
9
+ import * as Effect from "../../Effect.ts"
10
+ import * as Yaml from "../../encoding/Yaml.ts"
11
+ import * as Mime from "../../http/Mime.ts"
12
+ import * as Option from "../../Option.ts"
13
+ import * as Predicate from "../../Predicate.ts"
14
+ import * as Rpc from "../../rpc/Rpc.ts"
15
+ import * as RpcGroup from "../../rpc/RpcGroup.ts"
16
+ import * as Schema from "../../Schema.ts"
17
+ import * as PublicMcpSchema from "../McpSchema.ts"
18
+ import type * as McpCore from "./mcpCore.ts"
19
+ import * as McpProtocol from "./mcpProtocol.ts"
20
+ import * as Legacy from "./mcpSchema/v2024_11_05.ts"
21
+ import * as Stateless from "./mcpSchema/v2026_07_28.ts"
22
+
23
+ /**
24
+ * @internal
25
+ */
26
+ export const EXTENSION_ID = "io.modelcontextprotocol/skills"
27
+
28
+ const DIRECTORY_MIME_TYPE = "inode/directory"
29
+
30
+ // The extension's per-skill limits, which every conforming host accepts.
31
+ const MAX_FILES_PER_SKILL = 512
32
+ const MAX_BYTES_PER_SKILL = 16 * 1024 * 1024
33
+
34
+ /**
35
+ * Adds the extension declaration while any skill is registered. Declaring it
36
+ * commits the server to `skills/list`, `skills/get` and, through
37
+ * `directoryRead`, `resources/directory/read`.
38
+ *
39
+ * @internal
40
+ */
41
+ export const declareExtension = <A>(
42
+ extensions: Readonly<Record<string, A>> | undefined,
43
+ servesSkills: boolean
44
+ ): Readonly<Record<string, A | { readonly directoryRead: true }>> | undefined =>
45
+ servesSkills ? { ...extensions, [EXTENSION_ID]: { directoryRead: true } } : extensions
46
+
47
+ // =============================================================================
48
+ // Wire schemas
49
+ // =============================================================================
50
+
51
+ const Skill = Schema.Struct({
52
+ uri: Schema.String,
53
+ frontmatter: Legacy.UnknownObject,
54
+ resources: Schema.Union([
55
+ Schema.Array(Schema.Struct(PublicMcpSchema.SkillResource.fields)),
56
+ Schema.Literal("dynamic")
57
+ ])
58
+ })
59
+
60
+ // Listed entries are checked one at a time, so that a client can leave out an
61
+ // invalid entry instead of rejecting the whole page.
62
+ const ListedSkills = Schema.Array(Schema.Unknown)
63
+
64
+ /**
65
+ * @internal
66
+ */
67
+ export class LegacyListSkills extends Rpc.make("skills/list", {
68
+ success: Schema.Struct({ ...Legacy.PaginatedResult.fields, skills: ListedSkills }),
69
+ error: Legacy.McpError,
70
+ payload: Schema.UndefinedOr(Legacy.PaginatedRequest)
71
+ }) {}
72
+
73
+ /**
74
+ * @internal
75
+ */
76
+ export class LegacyGetSkill extends Rpc.make("skills/get", {
77
+ success: Schema.Struct({ ...Legacy.ResultMeta.fields, skill: Skill }),
78
+ error: Legacy.McpError,
79
+ payload: { ...Legacy.RequestMeta.fields, uri: Schema.String }
80
+ }) {}
81
+
82
+ /**
83
+ * @internal
84
+ */
85
+ export class LegacyReadResourceDirectory extends Rpc.make("resources/directory/read", {
86
+ success: Schema.Struct({ ...Legacy.PaginatedResult.fields, resources: Schema.Array(Legacy.Resource) }),
87
+ error: Legacy.McpError,
88
+ payload: { ...Legacy.PaginatedRequest.fields, uri: Schema.String }
89
+ }) {}
90
+
91
+ /**
92
+ * The extension's methods on revisions before 2026-07-28, which have no
93
+ * result caching attributes.
94
+ *
95
+ * @internal
96
+ */
97
+ export class LegacyRpcs extends RpcGroup.make(LegacyListSkills, LegacyGetSkill, LegacyReadResourceDirectory) {}
98
+
99
+ /**
100
+ * @internal
101
+ */
102
+ export const ListSkillsResult = Schema.StructWithRest(
103
+ Schema.Struct({ ...Stateless.PaginatedResult, ...Stateless.CacheableResult, skills: ListedSkills }),
104
+ [Stateless.UnknownObject]
105
+ )
106
+
107
+ /**
108
+ * @internal
109
+ */
110
+ export class ListSkills extends Rpc.make("skills/list", {
111
+ success: ListSkillsResult,
112
+ error: Stateless.McpError,
113
+ payload: Stateless.PaginatedRequestParams
114
+ }) {}
115
+
116
+ /**
117
+ * @internal
118
+ */
119
+ export const GetSkillResult = Schema.StructWithRest(
120
+ Schema.Struct({ ...Stateless.CacheableResult, skill: Skill }),
121
+ [Stateless.UnknownObject]
122
+ )
123
+
124
+ /**
125
+ * @internal
126
+ */
127
+ export class GetSkill extends Rpc.make("skills/get", {
128
+ success: GetSkillResult,
129
+ error: Stateless.McpError,
130
+ payload: { ...Stateless.RequestParams.fields, uri: Schema.String }
131
+ }) {}
132
+
133
+ /**
134
+ * @internal
135
+ */
136
+ export const ReadResourceDirectoryResult = Schema.StructWithRest(
137
+ Schema.Struct({
138
+ ...Stateless.PaginatedResult,
139
+ ...Stateless.CacheableResult,
140
+ resources: Schema.Array(Stateless.Resource)
141
+ }),
142
+ [Stateless.UnknownObject]
143
+ )
144
+
145
+ /**
146
+ * @internal
147
+ */
148
+ export class ReadResourceDirectory extends Rpc.make("resources/directory/read", {
149
+ success: ReadResourceDirectoryResult,
150
+ error: Stateless.McpError,
151
+ payload: { ...Stateless.PaginatedRequestParams, uri: Schema.String }
152
+ }) {}
153
+
154
+ /**
155
+ * The extension's methods on revision 2026-07-28.
156
+ *
157
+ * @internal
158
+ */
159
+ export class StatelessRpcs extends RpcGroup.make(ListSkills, GetSkill, ReadResourceDirectory) {}
160
+
161
+ // =============================================================================
162
+ // Handlers
163
+ // =============================================================================
164
+
165
+ const methodNotFound = (method: string) =>
166
+ new McpProtocol.ProtocolError({
167
+ code: PublicMcpSchema.METHOD_NOT_FOUND_ERROR_CODE,
168
+ message: `Method not found: ${method}`
169
+ })
170
+
171
+ // Every skill fits on one page, so the server never issues a cursor.
172
+ const unknownCursor = new McpProtocol.ProtocolError({
173
+ code: PublicMcpSchema.INVALID_PARAMS_ERROR_CODE,
174
+ message: "Unknown cursor"
175
+ })
176
+
177
+ /**
178
+ * Fails with `Method not found` while no skill is registered, as a server
179
+ * that does not declare the extension.
180
+ *
181
+ * @internal
182
+ */
183
+ export const requireSkills = (core: McpCore.McpCore, method: string) =>
184
+ Effect.flatMap(
185
+ core.registrationPresence,
186
+ (presence) => presence.skills ? Effect.void : Effect.fail(methodNotFound(method))
187
+ )
188
+
189
+ /**
190
+ * @internal
191
+ */
192
+ export const rejectCursor = (cursor: string | undefined) =>
193
+ cursor === undefined ? Effect.void : Effect.fail(unknownCursor)
194
+
195
+ /**
196
+ * Handlers for {@link LegacyRpcs}, for the sessionful adapters.
197
+ *
198
+ * @internal
199
+ */
200
+ export const legacyHandlers = (core: McpCore.McpCore) => ({
201
+ "skills/list": Effect.fnUntraced(function*(request: typeof LegacyListSkills.payloadSchema.Type) {
202
+ yield* requireSkills(core, "skills/list")
203
+ yield* rejectCursor(request?.cursor)
204
+ const skills = yield* McpProtocol.listForClient(core.skills.list)
205
+ return { skills }
206
+ }),
207
+ "skills/get": Effect.fnUntraced(function*(request: typeof LegacyGetSkill.payloadSchema.Type) {
208
+ yield* requireSkills(core, "skills/get")
209
+ const client = yield* PublicMcpSchema.McpServerClient
210
+ const skill = yield* core.skills.get(request.uri, McpProtocol.invocationFromClient(client)).pipe(
211
+ Effect.mapError(McpProtocol.ProtocolError.fromFeature)
212
+ )
213
+ return { skill }
214
+ }),
215
+ "resources/directory/read": Effect.fnUntraced(function*(
216
+ request: typeof LegacyReadResourceDirectory.payloadSchema.Type
217
+ ) {
218
+ yield* requireSkills(core, "resources/directory/read")
219
+ yield* rejectCursor(request.cursor)
220
+ const client = yield* PublicMcpSchema.McpServerClient
221
+ const resources = yield* core.skills.readDirectory(request.uri, McpProtocol.invocationFromClient(client)).pipe(
222
+ Effect.mapError(McpProtocol.ProtocolError.fromFeature)
223
+ )
224
+ return { resources }
225
+ })
226
+ })
227
+
228
+ // =============================================================================
229
+ // Static skills
230
+ // =============================================================================
231
+
232
+ /**
233
+ * A file of a static skill as handed in, `SKILL.md` included, with its path
234
+ * relative to the skill root.
235
+ *
236
+ * @internal
237
+ */
238
+ export interface SourceFile {
239
+ readonly path: string
240
+ readonly content: Uint8Array
241
+ readonly mimeType?: string | undefined
242
+ }
243
+
244
+ /**
245
+ * A file of a static skill as served through `resources/read`.
246
+ *
247
+ * @internal
248
+ */
249
+ export interface ServedFile {
250
+ // Listed by `resources/list` and as a child on `resources/directory/read`.
251
+ readonly resource: McpCore.DirectoryChild
252
+ readonly content: Uint8Array
253
+ // Set when the file is textual and valid UTF-8; otherwise it is served as a blob.
254
+ readonly text: string | undefined
255
+ }
256
+
257
+ /**
258
+ * @internal
259
+ */
260
+ export interface StaticSkill {
261
+ readonly entry: McpCore.Skill
262
+ readonly files: ReadonlyArray<ServedFile>
263
+ // Directory URI to its direct children.
264
+ readonly directories: ReadonlyMap<string, ReadonlyArray<McpCore.DirectoryChild>>
265
+ }
266
+
267
+ const TEXTUAL_APPLICATION_TYPES: ReadonlySet<string> = new Set([
268
+ "application/json",
269
+ "application/yaml",
270
+ "image/svg+xml"
271
+ ])
272
+
273
+ /**
274
+ * @internal
275
+ */
276
+ export const mimeTypeFor = (path: string): string => {
277
+ // The standard table maps `.ts` to MPEG transport streams, but a skill's
278
+ // `.ts` files are TypeScript scripts.
279
+ if (/\.ts$/i.test(path)) return "text/x-typescript"
280
+ return Option.getOrElse(Mime.getType(path), () => "application/octet-stream")
281
+ }
282
+
283
+ // `ignoreBOM` keeps a leading BOM in the decoded text, so re-encoding the text
284
+ // reproduces exactly the bytes the manifest digest covers.
285
+ const utf8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true })
286
+
287
+ const decodeText = (mimeType: string, content: Uint8Array): string | undefined => {
288
+ if (!mimeType.startsWith("text/") && !TEXTUAL_APPLICATION_TYPES.has(mimeType)) {
289
+ return undefined
290
+ }
291
+ try {
292
+ return utf8.decode(content)
293
+ } catch {
294
+ return undefined
295
+ }
296
+ }
297
+
298
+ const isSafeRelativePath = (path: string): boolean =>
299
+ path !== "" &&
300
+ !path.includes("\\") &&
301
+ path.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..")
302
+
303
+ // The Agent Skills `name` rule: lowercase letters, digits and single hyphens,
304
+ // neither leading nor trailing, at most 64 characters.
305
+ const isSkillName = (name: string): boolean => name.length <= 64 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)
306
+
307
+ const FRONTMATTER = /^\uFEFF?---\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/
308
+
309
+ /**
310
+ * The YAML frontmatter of a `SKILL.md`, or `undefined` when the file does not
311
+ * begin with a frontmatter block holding a YAML mapping.
312
+ *
313
+ * @internal
314
+ */
315
+ export const parseFrontmatter = (markdown: string): Record<string, unknown> | undefined => {
316
+ const block = FRONTMATTER.exec(markdown)?.[1]
317
+ if (block === undefined) return undefined
318
+ try {
319
+ const parsed = Yaml.parse(block)
320
+ // The frontmatter is listed as JSON, so keep only what JSON carries:
321
+ // `.inf` and `.nan` become `null`.
322
+ return Predicate.isObject(parsed) ? JSON.parse(JSON.stringify(parsed)) : undefined
323
+ } catch {
324
+ return undefined
325
+ }
326
+ }
327
+
328
+ // The directory holding a skill's `SKILL.md`, given the `SKILL.md` URI.
329
+ const skillRoot = (uri: string): string => uri.slice(0, -"/SKILL.md".length)
330
+
331
+ /**
332
+ * Whether `uri` addresses a file inside the skill whose `SKILL.md` is at
333
+ * `skillUri`.
334
+ *
335
+ * @internal
336
+ */
337
+ export const isSkillFile = (skillUri: string, uri: string): boolean => {
338
+ const root = skillRoot(skillUri)
339
+ return uri.startsWith(`${root}/`) && isSafeRelativePath(uri.slice(root.length + 1))
340
+ }
341
+
342
+ /**
343
+ * Why a skill entry received from a server breaks the extension's rules, or
344
+ * `undefined` when it is valid. Hosts must not load an invalid entry. The
345
+ * digest and size formats are checked by {@link PublicMcpSchema.SkillResource}.
346
+ *
347
+ * @internal
348
+ */
349
+ export const entryProblem = (entry: McpCore.Skill): string | undefined => {
350
+ const schemeEnd = entry.uri.indexOf("://")
351
+ if (schemeEnd <= 0 || !entry.uri.endsWith("/SKILL.md")) return "the URI does not address a SKILL.md"
352
+ const root = skillRoot(entry.uri)
353
+ const skillPath = root.slice(schemeEnd + 3)
354
+ if (!isSafeRelativePath(skillPath)) return "the skill path has an empty, '.' or '..' segment"
355
+ const name = skillPath.split("/").at(-1)!
356
+ if (entry.frontmatter.name !== name || !isSkillName(name)) {
357
+ return `the frontmatter name must equal "${name}" and follow the Agent Skills naming rules`
358
+ }
359
+ const description = entry.frontmatter.description
360
+ if (typeof description !== "string" || description === "" || description.length > 1024) {
361
+ return "the frontmatter description must be a string of 1 to 1024 characters"
362
+ }
363
+ if (entry.resources === "dynamic") return undefined
364
+ const uris = new Set<string>()
365
+ for (const resource of entry.resources) {
366
+ if (!isSkillFile(entry.uri, resource.uri)) return `${resource.uri} is not a file of the skill`
367
+ if (uris.has(resource.uri)) return `${resource.uri} is listed twice`
368
+ uris.add(resource.uri)
369
+ }
370
+ return uris.has(entry.uri) ? undefined : "the manifest does not list SKILL.md"
371
+ }
372
+
373
+ /**
374
+ * Whether `child` is a direct child of the directory at `directory`.
375
+ *
376
+ * @internal
377
+ */
378
+ export const isDirectChild = (directory: string, child: string): boolean => {
379
+ if (!child.startsWith(`${directory}/`)) return false
380
+ const name = child.slice(directory.length + 1)
381
+ return name !== "" && name !== "." && name !== ".." && !name.includes("/")
382
+ }
383
+
384
+ const decodeFrontmatter = Schema.decodeUnknownEffect(PublicMcpSchema.SkillFrontmatter)
385
+
386
+ /**
387
+ * Validates a static skill against the extension's server requirements and
388
+ * precomputes what the protocol serves: the manifest, with digests over the
389
+ * exact bytes served, each file's resource metadata, and the directory tree
390
+ * from the namespace root down.
391
+ *
392
+ * @internal
393
+ */
394
+ export const makeStaticSkill = (options: {
395
+ readonly uri: string
396
+ readonly files: ReadonlyArray<SourceFile>
397
+ }): Effect.Effect<StaticSkill, Cause.IllegalArgumentError, Digest.Digest> =>
398
+ Effect.gen(function*() {
399
+ const { uri } = options
400
+ const fail = (reason: string) => Effect.fail(new Cause.IllegalArgumentError(`Skill ${uri}: ${reason}`))
401
+
402
+ const schemeEnd = uri.indexOf("://")
403
+ if (schemeEnd <= 0 || !uri.endsWith("/SKILL.md")) {
404
+ return yield* fail("the URI must have the form <scheme>://<skill-path>/SKILL.md")
405
+ }
406
+ const scheme = uri.slice(0, schemeEnd + 3)
407
+ const skillPath = uri.slice(scheme.length, -"/SKILL.md".length)
408
+ if (!isSafeRelativePath(skillPath)) {
409
+ return yield* fail("the skill path must have no empty, '.' or '..' segment")
410
+ }
411
+ const name = skillPath.split("/").at(-1)!
412
+ if (options.files.length > MAX_FILES_PER_SKILL) {
413
+ return yield* fail(`it has ${options.files.length} files; the limit is ${MAX_FILES_PER_SKILL}`)
414
+ }
415
+ const totalBytes = options.files.reduce((sum, file) => sum + file.content.byteLength, 0)
416
+ if (totalBytes > MAX_BYTES_PER_SKILL) {
417
+ return yield* fail(`it has ${totalBytes} bytes; the limit is ${MAX_BYTES_PER_SKILL}`)
418
+ }
419
+ const paths = new Set<string>()
420
+ for (const file of options.files) {
421
+ if (!isSafeRelativePath(file.path)) return yield* fail(`the file path "${file.path}" escapes the skill`)
422
+ if (paths.has(file.path)) return yield* fail(`the file "${file.path}" is given twice`)
423
+ paths.add(file.path)
424
+ }
425
+ const skillMd = options.files.find((file) => file.path === "SKILL.md")
426
+ if (skillMd === undefined) return yield* fail("SKILL.md is missing")
427
+
428
+ // The listed frontmatter is parsed from the served SKILL.md, so the two
429
+ // cannot differ.
430
+ const frontmatter = parseFrontmatter(decodeText("text/markdown", skillMd.content) ?? "")
431
+ if (frontmatter === undefined) return yield* fail("SKILL.md must begin with YAML frontmatter holding a mapping")
432
+ if (frontmatter.name !== name) {
433
+ return yield* fail(`the frontmatter name ${JSON.stringify(frontmatter.name)} must equal "${name}"`)
434
+ }
435
+ // A skill served over MCP must conform to the Agent Skills specification.
436
+ const { description } = yield* decodeFrontmatter(frontmatter).pipe(
437
+ Effect.catch((error) => fail(`the frontmatter is not valid Agent Skills frontmatter: ${error.message}`))
438
+ )
439
+
440
+ const digest = yield* Digest.Digest
441
+ const sorted = [...options.files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)
442
+ const resources: Array<McpCore.SkillResource> = []
443
+ const files: Array<ServedFile> = []
444
+ const children = new Map<string, Map<string, McpCore.DirectoryChild>>()
445
+ for (const file of sorted) {
446
+ const fileUri = `${scheme}${skillPath}/${file.path}`
447
+ const fileDigest = `sha256:${yield* digest.digestHex(Digest.sha256, file.content)}`
448
+ const mimeType = file.mimeType ?? mimeTypeFor(file.path)
449
+ const size = file.content.byteLength
450
+ const resource: McpCore.DirectoryChild = file.path === "SKILL.md"
451
+ ? { uri: fileUri, name, description, mimeType, size }
452
+ : { uri: fileUri, name: file.path.split("/").at(-1)!, mimeType, size }
453
+ files.push({ resource, content: file.content, text: decodeText(mimeType, file.content) })
454
+ resources.push({ uri: fileUri, digest: fileDigest, size })
455
+
456
+ // Every directory from the namespace root down is readable, including
457
+ // the prefix directories above the skill root.
458
+ const segments = `${skillPath}/${file.path}`.split("/")
459
+ for (let depth = 1; depth < segments.length; depth++) {
460
+ const directory = `${scheme}${segments.slice(0, depth).join("/")}`
461
+ const child: McpCore.DirectoryChild = depth === segments.length - 1 ? resource : {
462
+ uri: `${scheme}${segments.slice(0, depth + 1).join("/")}`,
463
+ name: segments[depth]!,
464
+ mimeType: DIRECTORY_MIME_TYPE
465
+ }
466
+ let siblings = children.get(directory)
467
+ if (siblings === undefined) {
468
+ siblings = new Map()
469
+ children.set(directory, siblings)
470
+ }
471
+ siblings.set(child.uri, child)
472
+ }
473
+ }
474
+
475
+ const directories = new Map<string, ReadonlyArray<McpCore.DirectoryChild>>()
476
+ for (const [directory, siblings] of children) {
477
+ directories.set(directory, Array.from(siblings.values()))
478
+ }
479
+ return { entry: { uri, frontmatter, resources }, files, directories }
480
+ })
@@ -38,11 +38,17 @@ export function resolveReference($ref: string, definitions: JsonSchema.Definitio
38
38
  export function resolveTopLevelReference(
39
39
  document: JsonSchema.Document<"draft-2020-12">
40
40
  ): JsonSchema.Document<"draft-2020-12"> {
41
- if (typeof document.schema.$ref !== "string") return document
42
- return {
43
- ...document,
44
- schema: resolveReference(document.schema.$ref, document.definitions)
41
+ let schema = document.schema
42
+ if (typeof schema.$ref !== "string") return document
43
+ const visited = new Set<string>()
44
+ while (typeof schema.$ref === "string") {
45
+ if (visited.has(schema.$ref)) {
46
+ throw new Error(`Circular reference ${JSON.stringify(schema.$ref)}`)
47
+ }
48
+ visited.add(schema.$ref)
49
+ schema = resolveReference(schema.$ref, document.definitions)
45
50
  }
51
+ return { ...document, schema }
46
52
  }
47
53
 
48
54
  /**
@@ -267,7 +267,11 @@ export const make = Effect.gen(function*() {
267
267
  id: activityPrimaryKey(options.activity.name, options.attempt)
268
268
  })
269
269
  if (Option.isNone(requestId)) return
270
- yield* sharding.reset(requestId.value)
270
+ // Reset only the Suspended reply this runner saw. If another runner has
271
+ // stored a newer reply, storage skips the reset and the caller reads it.
272
+ const reply = yield* replyForRequestId(requestId.value)
273
+ if (Option.isNone(reply) || !isSuspendedReply(reply.value)) return
274
+ yield* sharding.reset(requestId.value, { expectedReplyId: Snowflake.Snowflake(reply.value.id) })
271
275
  },
272
276
  Effect.retry({
273
277
  times: 3,
@@ -344,7 +348,7 @@ export const make = Effect.gen(function*() {
344
348
  }
345
349
  const reply = yield* replyForRequestId(requestId.value)
346
350
  if (Option.isNone(reply)) return
347
- yield* sharding.reset(requestId.value)
351
+ yield* sharding.reset(requestId.value, { expectedReplyId: Snowflake.Snowflake(reply.value.id) })
348
352
  }, Effect.scoped)
349
353
 
350
354
  // Subscribe to the run's next reply before reading storage, so a reply
@@ -535,14 +539,15 @@ export const make = Effect.gen(function*() {
535
539
  if (instance.abandoned) {
536
540
  instance.suspended = false
537
541
  }
542
+ // Abandoned runs never wake the parent; another owner replays them.
543
+ const resumeParent = parent && !parent.detached && !instance.abandoned
544
+ ? ensureSuccess(sendResumeParent(parent, executionId))
545
+ : Effect.void
538
546
  if (
539
547
  !instance.suspended &&
540
548
  !instance.abandoned &&
541
549
  !(suspendOnFailure && exit._tag === "Failure")
542
550
  ) {
543
- const resumeParent = parent && !parent.detached
544
- ? ensureSuccess(sendResumeParent(parent, executionId))
545
- : Effect.void
546
551
  if (exit._tag === "Success" || !Cause.hasInterruptsOnly(exit.cause)) {
547
552
  return resumeParent
548
553
  }
@@ -568,9 +573,13 @@ export const make = Effect.gen(function*() {
568
573
  }
569
574
  instance.suspended = false
570
575
  instance.interrupted = true
571
- return Effect.andThen(
572
- Effect.ignore(clearClock({ workflow, executionId })),
573
- Effect.withFiber<void>((fiber) => Effect.interruptible(Fiber.interrupt(fiber)))
576
+ // The interrupt completes the run, so wake the parent
577
+ // to observe it.
578
+ return Effect.ignore(clearClock({ workflow, executionId })).pipe(
579
+ Effect.andThen(resumeParent),
580
+ Effect.andThen(
581
+ Effect.withFiber<void>((fiber) => Effect.interruptible(Fiber.interrupt(fiber)))
582
+ )
574
583
  )
575
584
  }),
576
585
  Effect.orDie
@@ -760,7 +769,7 @@ export const make = Effect.gen(function*() {
760
769
  // A pending interrupt replays only to rebuild compensations, so it must
761
770
  // not run new activities. Finalizers run once `interrupted` is set.
762
771
  if (!instance.interrupted && (yield* interruptPending(instance))) {
763
- const reply = yield* Effect.orDie(requestReply({
772
+ const reply = yield* retryPersistence(requestReply({
764
773
  workflow: instance.workflow,
765
774
  entityType: `Workflow/${instance.workflow._tag}`,
766
775
  executionId: instance.executionId,
@@ -777,7 +786,7 @@ export const make = Effect.gen(function*() {
777
786
  if (!activities.has(activityId)) {
778
787
  activities.set(activityId, { activity, context: services })
779
788
  }
780
- const result = yield* Effect.orDie(
789
+ const result = yield* retryPersistence(
781
790
  client.activity({
782
791
  name: activity.name,
783
792
  attempt,
@@ -860,7 +869,7 @@ export const make = Effect.gen(function*() {
860
869
  }
861
870
  const workflow = workflows.get(workflowName)
862
871
  if (workflow) {
863
- return yield* Effect.orDie(sendDiscard({
872
+ return yield* retryPersistence(sendDiscard({
864
873
  rpc: DeferredRpc,
865
874
  address: entityAddressFor({
866
875
  workflow,
@@ -874,7 +883,7 @@ export const make = Effect.gen(function*() {
874
883
  }))
875
884
  }
876
885
  const client = yield* RcMap.get(clientsPartial, workflowName)
877
- return yield* Effect.orDie(
886
+ return yield* retryPersistence(
878
887
  client(executionId).deferred({
879
888
  name: deferredName,
880
889
  exit
@@ -885,27 +894,24 @@ export const make = Effect.gen(function*() {
885
894
  ),
886
895
 
887
896
  scheduleClock(workflow, options) {
888
- return DateTime.now.pipe(
889
- Effect.flatMap((now) =>
890
- sendDiscard({
891
- rpc: ClockRpc,
892
- address: entityAddressFor({
893
- workflow,
894
- entityType: ClockEntity.type,
895
- executionId: options.executionId
896
- }),
897
- payload: {
898
- name: options.clock.name,
899
- workflowName: workflow._tag,
900
- wakeUp: DateTime.mapEpochMillis(
901
- DateTime.addDuration(now, options.clock.duration),
902
- Math.ceil
903
- )
904
- }
905
- })
906
- ),
907
- Effect.orDie
908
- )
897
+ // Compute the deadline once, so a retried save keeps the original wake-up.
898
+ return Effect.flatMap(DateTime.now, (now) =>
899
+ retryPersistence(sendDiscard({
900
+ rpc: ClockRpc,
901
+ address: entityAddressFor({
902
+ workflow,
903
+ entityType: ClockEntity.type,
904
+ executionId: options.executionId
905
+ }),
906
+ payload: {
907
+ name: options.clock.name,
908
+ workflowName: workflow._tag,
909
+ wakeUp: DateTime.mapEpochMillis(
910
+ DateTime.addDuration(now, options.clock.duration),
911
+ Math.ceil
912
+ )
913
+ }
914
+ })))
909
915
  }
910
916
  })
911
917
 
@@ -917,6 +923,15 @@ const retryPolicy = Schedule.min([
917
923
  Schedule.spaced("1 minute")
918
924
  ])
919
925
 
926
+ // A transient storage failure must not become the workflow result. Activity,
927
+ // clock and deferred requests are saved under a primary key, so a retry after
928
+ // a lost acknowledgement is deduplicated instead of stored twice.
929
+ const retryPersistence = <A, E extends { readonly _tag: string }, R>(effect: Effect.Effect<A, E, R>) =>
930
+ effect.pipe(
931
+ Effect.retry({ schedule: retryPolicy, while: (e) => e._tag === "PersistenceError" }),
932
+ Effect.orDie
933
+ )
934
+
920
935
  // A cluster abandonment means this owner can no longer complete the effect, so
921
936
  // retrying it would only wait on a retired run. Re-raise it as an annotated
922
937
  // interrupt, so the activation can unwind and its shard can be released.