@yolk-sdk/emulators 0.1.0-canary.96

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 (333) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2135 -0
  3. package/dist/anthropic.d.mts +269 -0
  4. package/dist/anthropic.d.mts.map +1 -0
  5. package/dist/anthropic.mjs +177 -0
  6. package/dist/anthropic.mjs.map +1 -0
  7. package/dist/chat-completions.d.mts +288 -0
  8. package/dist/chat-completions.d.mts.map +1 -0
  9. package/dist/chat-completions.mjs +451 -0
  10. package/dist/chat-completions.mjs.map +1 -0
  11. package/dist/codex.d.mts +265 -0
  12. package/dist/codex.d.mts.map +1 -0
  13. package/dist/codex.mjs +199 -0
  14. package/dist/codex.mjs.map +1 -0
  15. package/dist/dropbox/api.d.mts +63 -0
  16. package/dist/dropbox/api.d.mts.map +1 -0
  17. package/dist/dropbox/api.mjs +565 -0
  18. package/dist/dropbox/api.mjs.map +1 -0
  19. package/dist/dropbox/state.d.mts +136 -0
  20. package/dist/dropbox/state.d.mts.map +1 -0
  21. package/dist/dropbox/state.mjs +209 -0
  22. package/dist/dropbox/state.mjs.map +1 -0
  23. package/dist/dropbox.d.mts +79 -0
  24. package/dist/dropbox.d.mts.map +1 -0
  25. package/dist/dropbox.mjs +124 -0
  26. package/dist/dropbox.mjs.map +1 -0
  27. package/dist/email-fixtures.d.mts +36 -0
  28. package/dist/email-fixtures.d.mts.map +1 -0
  29. package/dist/email-fixtures.mjs +1080 -0
  30. package/dist/email-fixtures.mjs.map +1 -0
  31. package/dist/email.d.mts +160 -0
  32. package/dist/email.d.mts.map +1 -0
  33. package/dist/email.mjs +608 -0
  34. package/dist/email.mjs.map +1 -0
  35. package/dist/emulator-compose.d.mts +40 -0
  36. package/dist/emulator-compose.d.mts.map +1 -0
  37. package/dist/emulator-compose.mjs +91 -0
  38. package/dist/emulator-compose.mjs.map +1 -0
  39. package/dist/emulator-http.d.mts +53 -0
  40. package/dist/emulator-http.d.mts.map +1 -0
  41. package/dist/emulator-http.mjs +117 -0
  42. package/dist/emulator-http.mjs.map +1 -0
  43. package/dist/emulator-kernel.d.mts +176 -0
  44. package/dist/emulator-kernel.d.mts.map +1 -0
  45. package/dist/emulator-kernel.mjs +413 -0
  46. package/dist/emulator-kernel.mjs.map +1 -0
  47. package/dist/fixture-route.d.mts +129 -0
  48. package/dist/fixture-route.d.mts.map +1 -0
  49. package/dist/fixture-route.mjs +257 -0
  50. package/dist/fixture-route.mjs.map +1 -0
  51. package/dist/fortnox/api.d.mts +92 -0
  52. package/dist/fortnox/api.d.mts.map +1 -0
  53. package/dist/fortnox/api.mjs +750 -0
  54. package/dist/fortnox/api.mjs.map +1 -0
  55. package/dist/fortnox/state.d.mts +533 -0
  56. package/dist/fortnox/state.d.mts.map +1 -0
  57. package/dist/fortnox/state.mjs +612 -0
  58. package/dist/fortnox/state.mjs.map +1 -0
  59. package/dist/fortnox.d.mts +128 -0
  60. package/dist/fortnox.d.mts.map +1 -0
  61. package/dist/fortnox.mjs +403 -0
  62. package/dist/fortnox.mjs.map +1 -0
  63. package/dist/gateway-evaluate-recordings.d.mts +12 -0
  64. package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
  65. package/dist/gateway-evaluate-recordings.mjs +128 -0
  66. package/dist/gateway-evaluate-recordings.mjs.map +1 -0
  67. package/dist/gateway.d.mts +272 -0
  68. package/dist/gateway.d.mts.map +1 -0
  69. package/dist/gateway.mjs +400 -0
  70. package/dist/gateway.mjs.map +1 -0
  71. package/dist/github/api.d.mts +63 -0
  72. package/dist/github/api.d.mts.map +1 -0
  73. package/dist/github/api.mjs +527 -0
  74. package/dist/github/api.mjs.map +1 -0
  75. package/dist/github/state.d.mts +272 -0
  76. package/dist/github/state.d.mts.map +1 -0
  77. package/dist/github/state.mjs +303 -0
  78. package/dist/github/state.mjs.map +1 -0
  79. package/dist/github.d.mts +77 -0
  80. package/dist/github.d.mts.map +1 -0
  81. package/dist/github.mjs +180 -0
  82. package/dist/github.mjs.map +1 -0
  83. package/dist/google/calendar.d.mts +10 -0
  84. package/dist/google/calendar.d.mts.map +1 -0
  85. package/dist/google/calendar.mjs +252 -0
  86. package/dist/google/calendar.mjs.map +1 -0
  87. package/dist/google/drive.d.mts +8 -0
  88. package/dist/google/drive.d.mts.map +1 -0
  89. package/dist/google/drive.mjs +252 -0
  90. package/dist/google/drive.mjs.map +1 -0
  91. package/dist/google/gmail.d.mts +10 -0
  92. package/dist/google/gmail.d.mts.map +1 -0
  93. package/dist/google/gmail.mjs +591 -0
  94. package/dist/google/gmail.mjs.map +1 -0
  95. package/dist/google/shared.d.mts +107 -0
  96. package/dist/google/shared.d.mts.map +1 -0
  97. package/dist/google/shared.mjs +146 -0
  98. package/dist/google/shared.mjs.map +1 -0
  99. package/dist/google/state.d.mts +385 -0
  100. package/dist/google/state.d.mts.map +1 -0
  101. package/dist/google/state.mjs +496 -0
  102. package/dist/google/state.mjs.map +1 -0
  103. package/dist/google.d.mts +75 -0
  104. package/dist/google.d.mts.map +1 -0
  105. package/dist/google.mjs +210 -0
  106. package/dist/google.mjs.map +1 -0
  107. package/dist/linkedin-search/api.d.mts +45 -0
  108. package/dist/linkedin-search/api.d.mts.map +1 -0
  109. package/dist/linkedin-search/api.mjs +181 -0
  110. package/dist/linkedin-search/api.mjs.map +1 -0
  111. package/dist/linkedin-search/state.d.mts +123 -0
  112. package/dist/linkedin-search/state.d.mts.map +1 -0
  113. package/dist/linkedin-search/state.mjs +261 -0
  114. package/dist/linkedin-search/state.mjs.map +1 -0
  115. package/dist/linkedin-search.d.mts +69 -0
  116. package/dist/linkedin-search.d.mts.map +1 -0
  117. package/dist/linkedin-search.mjs +158 -0
  118. package/dist/linkedin-search.mjs.map +1 -0
  119. package/dist/mcp/api.d.mts +44 -0
  120. package/dist/mcp/api.d.mts.map +1 -0
  121. package/dist/mcp/api.mjs +557 -0
  122. package/dist/mcp/api.mjs.map +1 -0
  123. package/dist/mcp/recordings.d.mts +40 -0
  124. package/dist/mcp/recordings.d.mts.map +1 -0
  125. package/dist/mcp/recordings.mjs +2390 -0
  126. package/dist/mcp/recordings.mjs.map +1 -0
  127. package/dist/mcp/state.d.mts +71 -0
  128. package/dist/mcp/state.d.mts.map +1 -0
  129. package/dist/mcp/state.mjs +83 -0
  130. package/dist/mcp/state.mjs.map +1 -0
  131. package/dist/mcp.d.mts +84 -0
  132. package/dist/mcp.d.mts.map +1 -0
  133. package/dist/mcp.mjs +241 -0
  134. package/dist/mcp.mjs.map +1 -0
  135. package/dist/messages.d.mts +183 -0
  136. package/dist/messages.d.mts.map +1 -0
  137. package/dist/messages.mjs +532 -0
  138. package/dist/messages.mjs.map +1 -0
  139. package/dist/microsoft/api.d.mts +47 -0
  140. package/dist/microsoft/api.d.mts.map +1 -0
  141. package/dist/microsoft/api.mjs +178 -0
  142. package/dist/microsoft/api.mjs.map +1 -0
  143. package/dist/microsoft/calendar.d.mts +30 -0
  144. package/dist/microsoft/calendar.d.mts.map +1 -0
  145. package/dist/microsoft/calendar.mjs +271 -0
  146. package/dist/microsoft/calendar.mjs.map +1 -0
  147. package/dist/microsoft/drive.d.mts +36 -0
  148. package/dist/microsoft/drive.d.mts.map +1 -0
  149. package/dist/microsoft/drive.mjs +298 -0
  150. package/dist/microsoft/drive.mjs.map +1 -0
  151. package/dist/microsoft/graph.d.mts +198 -0
  152. package/dist/microsoft/graph.d.mts.map +1 -0
  153. package/dist/microsoft/graph.mjs +264 -0
  154. package/dist/microsoft/graph.mjs.map +1 -0
  155. package/dist/microsoft/mail.d.mts +48 -0
  156. package/dist/microsoft/mail.d.mts.map +1 -0
  157. package/dist/microsoft/mail.mjs +488 -0
  158. package/dist/microsoft/mail.mjs.map +1 -0
  159. package/dist/microsoft/state.d.mts +480 -0
  160. package/dist/microsoft/state.d.mts.map +1 -0
  161. package/dist/microsoft/state.mjs +625 -0
  162. package/dist/microsoft/state.mjs.map +1 -0
  163. package/dist/microsoft.d.mts +168 -0
  164. package/dist/microsoft.d.mts.map +1 -0
  165. package/dist/microsoft.mjs +483 -0
  166. package/dist/microsoft.mjs.map +1 -0
  167. package/dist/node.d.mts +47 -0
  168. package/dist/node.d.mts.map +1 -0
  169. package/dist/node.mjs +178 -0
  170. package/dist/node.mjs.map +1 -0
  171. package/dist/notion/api.d.mts +51 -0
  172. package/dist/notion/api.d.mts.map +1 -0
  173. package/dist/notion/api.mjs +507 -0
  174. package/dist/notion/api.mjs.map +1 -0
  175. package/dist/notion/state.d.mts +329 -0
  176. package/dist/notion/state.d.mts.map +1 -0
  177. package/dist/notion/state.mjs +432 -0
  178. package/dist/notion/state.mjs.map +1 -0
  179. package/dist/notion.d.mts +72 -0
  180. package/dist/notion.d.mts.map +1 -0
  181. package/dist/notion.mjs +127 -0
  182. package/dist/notion.mjs.map +1 -0
  183. package/dist/openai.d.mts +165 -0
  184. package/dist/openai.d.mts.map +1 -0
  185. package/dist/openai.mjs +141 -0
  186. package/dist/openai.mjs.map +1 -0
  187. package/dist/opencode-recordings.d.mts +7 -0
  188. package/dist/opencode-recordings.d.mts.map +1 -0
  189. package/dist/opencode-recordings.mjs +222 -0
  190. package/dist/opencode-recordings.mjs.map +1 -0
  191. package/dist/opencode.d.mts +70 -0
  192. package/dist/opencode.d.mts.map +1 -0
  193. package/dist/opencode.mjs +217 -0
  194. package/dist/opencode.mjs.map +1 -0
  195. package/dist/r2-fixtures.d.mts +36 -0
  196. package/dist/r2-fixtures.d.mts.map +1 -0
  197. package/dist/r2-fixtures.mjs +245 -0
  198. package/dist/r2-fixtures.mjs.map +1 -0
  199. package/dist/r2-guard.d.mts +43 -0
  200. package/dist/r2-guard.d.mts.map +1 -0
  201. package/dist/r2-guard.mjs +215 -0
  202. package/dist/r2-guard.mjs.map +1 -0
  203. package/dist/r2.d.mts +166 -0
  204. package/dist/r2.d.mts.map +1 -0
  205. package/dist/r2.mjs +517 -0
  206. package/dist/r2.mjs.map +1 -0
  207. package/dist/responses.d.mts +231 -0
  208. package/dist/responses.d.mts.map +1 -0
  209. package/dist/responses.mjs +556 -0
  210. package/dist/responses.mjs.map +1 -0
  211. package/dist/route-evidence.d.mts +45 -0
  212. package/dist/route-evidence.d.mts.map +1 -0
  213. package/dist/route-evidence.mjs +56 -0
  214. package/dist/route-evidence.mjs.map +1 -0
  215. package/dist/router.d.mts +93 -0
  216. package/dist/router.d.mts.map +1 -0
  217. package/dist/router.mjs +259 -0
  218. package/dist/router.mjs.map +1 -0
  219. package/dist/stateful-core.d.mts +17 -0
  220. package/dist/stateful-core.d.mts.map +1 -0
  221. package/dist/stateful-core.mjs +41 -0
  222. package/dist/stateful-core.mjs.map +1 -0
  223. package/dist/stateful-emulator.d.mts +565 -0
  224. package/dist/stateful-emulator.d.mts.map +1 -0
  225. package/dist/stateful-emulator.mjs +1228 -0
  226. package/dist/stateful-emulator.mjs.map +1 -0
  227. package/dist/stateful-secrets.d.mts +84 -0
  228. package/dist/stateful-secrets.d.mts.map +1 -0
  229. package/dist/stateful-secrets.mjs +216 -0
  230. package/dist/stateful-secrets.mjs.map +1 -0
  231. package/dist/subscription-usage-recordings.d.mts +9 -0
  232. package/dist/subscription-usage-recordings.d.mts.map +1 -0
  233. package/dist/subscription-usage-recordings.mjs +53 -0
  234. package/dist/subscription-usage-recordings.mjs.map +1 -0
  235. package/dist/subscription-usage.d.mts +53 -0
  236. package/dist/subscription-usage.d.mts.map +1 -0
  237. package/dist/subscription-usage.mjs +21 -0
  238. package/dist/subscription-usage.mjs.map +1 -0
  239. package/dist/telegram/api.d.mts +34 -0
  240. package/dist/telegram/api.d.mts.map +1 -0
  241. package/dist/telegram/api.mjs +257 -0
  242. package/dist/telegram/api.mjs.map +1 -0
  243. package/dist/telegram/state.d.mts +128 -0
  244. package/dist/telegram/state.d.mts.map +1 -0
  245. package/dist/telegram/state.mjs +154 -0
  246. package/dist/telegram/state.mjs.map +1 -0
  247. package/dist/telegram.d.mts +62 -0
  248. package/dist/telegram.d.mts.map +1 -0
  249. package/dist/telegram.mjs +127 -0
  250. package/dist/telegram.mjs.map +1 -0
  251. package/dist/todoist/api.d.mts +55 -0
  252. package/dist/todoist/api.d.mts.map +1 -0
  253. package/dist/todoist/api.mjs +415 -0
  254. package/dist/todoist/api.mjs.map +1 -0
  255. package/dist/todoist/state.d.mts +275 -0
  256. package/dist/todoist/state.d.mts.map +1 -0
  257. package/dist/todoist/state.mjs +345 -0
  258. package/dist/todoist/state.mjs.map +1 -0
  259. package/dist/todoist.d.mts +68 -0
  260. package/dist/todoist.d.mts.map +1 -0
  261. package/dist/todoist.mjs +181 -0
  262. package/dist/todoist.mjs.map +1 -0
  263. package/dist/xai.d.mts +267 -0
  264. package/dist/xai.d.mts.map +1 -0
  265. package/dist/xai.mjs +252 -0
  266. package/dist/xai.mjs.map +1 -0
  267. package/package.json +157 -0
  268. package/src/anthropic.ts +289 -0
  269. package/src/chat-completions.ts +924 -0
  270. package/src/codex.ts +296 -0
  271. package/src/dropbox/api.ts +1084 -0
  272. package/src/dropbox/state.ts +364 -0
  273. package/src/dropbox.ts +203 -0
  274. package/src/email-fixtures.ts +1297 -0
  275. package/src/email.ts +1108 -0
  276. package/src/emulator-compose.ts +147 -0
  277. package/src/emulator-http.ts +184 -0
  278. package/src/emulator-kernel.ts +844 -0
  279. package/src/fixture-route.ts +561 -0
  280. package/src/fortnox/api.ts +1352 -0
  281. package/src/fortnox/state.ts +798 -0
  282. package/src/fortnox.ts +801 -0
  283. package/src/gateway-evaluate-recordings.ts +153 -0
  284. package/src/gateway.ts +530 -0
  285. package/src/github/api.ts +986 -0
  286. package/src/github/state.ts +439 -0
  287. package/src/github.ts +271 -0
  288. package/src/google/calendar.ts +486 -0
  289. package/src/google/drive.ts +471 -0
  290. package/src/google/gmail.ts +1011 -0
  291. package/src/google/shared.ts +321 -0
  292. package/src/google/state.ts +686 -0
  293. package/src/google.ts +298 -0
  294. package/src/linkedin-search/api.ts +363 -0
  295. package/src/linkedin-search/state.ts +373 -0
  296. package/src/linkedin-search.ts +241 -0
  297. package/src/mcp/api.ts +995 -0
  298. package/src/mcp/recordings.ts +2665 -0
  299. package/src/mcp/state.ts +125 -0
  300. package/src/mcp.ts +319 -0
  301. package/src/messages.ts +844 -0
  302. package/src/microsoft/api.ts +426 -0
  303. package/src/microsoft/calendar.ts +491 -0
  304. package/src/microsoft/drive.ts +541 -0
  305. package/src/microsoft/graph.ts +550 -0
  306. package/src/microsoft/mail.ts +833 -0
  307. package/src/microsoft/state.ts +822 -0
  308. package/src/microsoft.ts +982 -0
  309. package/src/node.ts +293 -0
  310. package/src/notion/api.ts +976 -0
  311. package/src/notion/state.ts +512 -0
  312. package/src/notion.ts +210 -0
  313. package/src/openai.ts +198 -0
  314. package/src/opencode-recordings.ts +257 -0
  315. package/src/opencode.ts +271 -0
  316. package/src/r2-fixtures.ts +295 -0
  317. package/src/r2-guard.ts +323 -0
  318. package/src/r2.ts +890 -0
  319. package/src/responses.ts +901 -0
  320. package/src/route-evidence.ts +90 -0
  321. package/src/router.ts +490 -0
  322. package/src/stateful-core.ts +70 -0
  323. package/src/stateful-emulator.ts +2571 -0
  324. package/src/stateful-secrets.ts +299 -0
  325. package/src/subscription-usage-recordings.ts +77 -0
  326. package/src/subscription-usage.ts +68 -0
  327. package/src/telegram/api.ts +437 -0
  328. package/src/telegram/state.ts +229 -0
  329. package/src/telegram.ts +227 -0
  330. package/src/todoist/api.ts +736 -0
  331. package/src/todoist/state.ts +456 -0
  332. package/src/todoist.ts +316 -0
  333. package/src/xai.ts +341 -0
package/dist/mcp.d.mts ADDED
@@ -0,0 +1,84 @@
1
+ import { EmulatorEvidence, EmulatorRouteEvidence, emulatorEvidenceHeader } from "./route-evidence.mjs";
2
+ import { StatefulCoverage, StatefulEmulatorApi, StatefulFaultMatch, StatefulFaultState, StatefulInputKind, StatefulLedgerEntry, StatefulStreamFault } from "./stateful-emulator.mjs";
3
+ import { McpRecordedExchange, McpRecordedFixture, McpRecordedRequest, McpRecordedResponse, mcpEmulatorFixtures } from "./mcp/recordings.mjs";
4
+ import { McpEmulatorModernListing, McpEmulatorSeed, McpEmulatorSession, McpEmulatorState, McpEmulatorStateSchema, mcpEmulatorLegacyPath, mcpEmulatorModernPath, mcpEmulatorOrigin, mcpEmulatorReservedInvalidCredential, mcpEmulatorSessionCap, mcpEmulatorSessionPrefix } from "./mcp/state.mjs";
5
+ import { McpEmulatorDrills, isMcpEmulatedRequestId, mcpEmulatorDrillKnobs } from "./mcp/api.mjs";
6
+
7
+ //#region src/mcp.d.ts
8
+ /**
9
+ * Route evidence manifest: one `RPC <origin><path>#<method>` row per recorded JSON-RPC method of
10
+ * each profile, plus the legacy `GET` row, with the conformance cases whose (synthetic,
11
+ * unverified) fixtures each answers. No row writes anything. Kept in sync with the handlers by
12
+ * construction (both come from one route table).
13
+ */
14
+ declare const mcpEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
15
+ /**
16
+ * Optional fault filter; an omitted field matches every request. `method` is the HTTP method
17
+ * (`POST` or `GET`, never a row's `RPC`); `path` is the raw request path (ending in `*`, a
18
+ * prefix); `route` is a manifest row path (for example
19
+ * `https://mcp.example.test/legacy/mcp#tools/list`), and a value naming no row is rejected when
20
+ * the fault is added.
21
+ */
22
+ declare const McpFaultMatch: import("effect/Schema").Struct<{
23
+ readonly method: import("effect/Schema").optionalKey<import("effect/Schema").String>;
24
+ readonly path: import("effect/Schema").optionalKey<import("effect/Schema").String>;
25
+ readonly route: import("effect/Schema").optionalKey<import("effect/Schema").String>;
26
+ }>;
27
+ type McpFaultMatch = typeof StatefulFaultMatch.Type;
28
+ /**
29
+ * A status fault (400-599), or a `truncate-after-chunks` fault that sends the first `chunks`
30
+ * chunks of the prepared answer and then ends it cleanly (an SSE answer has two chunks, a JSON
31
+ * answer one). Only a request the emulator would answer reaches a fault: a request that is not
32
+ * emulated, by its shape or by the state, never uses one up. A faulted request writes nothing (a
33
+ * truncated `initialize` mints no session; a truncated first page issues no cursor). A truncation
34
+ * that cannot apply answers 500 and is not used up.
35
+ */
36
+ declare const McpFault: import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
37
+ readonly kind: import("effect/Schema").Literal<"status">;
38
+ readonly status: import("effect/Schema").Int;
39
+ readonly headers: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").String>>;
40
+ readonly body: import("effect/Schema").optionalKey<import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>;
41
+ readonly match: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
42
+ readonly method: import("effect/Schema").optionalKey<import("effect/Schema").String>;
43
+ readonly path: import("effect/Schema").optionalKey<import("effect/Schema").String>;
44
+ readonly route: import("effect/Schema").optionalKey<import("effect/Schema").String>;
45
+ }>>;
46
+ readonly count: import("effect/Schema").optionalKey<import("effect/Schema").Int>;
47
+ }>, import("effect/Schema").Struct<{
48
+ readonly kind: import("effect/Schema").Literal<"truncate-after-chunks">;
49
+ readonly chunks: import("effect/Schema").Int;
50
+ readonly match: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
51
+ readonly method: import("effect/Schema").optionalKey<import("effect/Schema").String>;
52
+ readonly path: import("effect/Schema").optionalKey<import("effect/Schema").String>;
53
+ readonly route: import("effect/Schema").optionalKey<import("effect/Schema").String>;
54
+ }>>;
55
+ readonly count: import("effect/Schema").optionalKey<import("effect/Schema").Int>;
56
+ }>]>;
57
+ type McpFault = StatefulStreamFault;
58
+ type McpFaultState = StatefulFaultState<McpFault>;
59
+ type McpLedgerEntry = StatefulLedgerEntry;
60
+ type McpCoverage = StatefulCoverage;
61
+ declare const McpEmulatorInputInvalid_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
62
+ readonly _tag: "McpEmulatorInputInvalid";
63
+ } & Readonly<A>;
64
+ /** Invalid emulator input from the JS API: a seed, a fault, or an option. A programmer error. */
65
+ declare class McpEmulatorInputInvalid extends McpEmulatorInputInvalid_base<{
66
+ readonly input: StatefulInputKind;
67
+ readonly reason: string;
68
+ }> {
69
+ get message(): string;
70
+ }
71
+ type McpEmulatorOptions = {
72
+ /** Typed seed; defaults to the one-page modern listing (sessions are never seeded). */readonly seed?: McpEmulatorSeed; /** Drill knobs (tests only): make the emulator disagree with one conformance claim. */
73
+ readonly drills?: McpEmulatorDrills;
74
+ };
75
+ type McpEmulator = StatefulEmulatorApi<McpEmulatorState, McpEmulatorSeed, McpFault>;
76
+ /**
77
+ * Create a stateful MCP emulator on the `@emulators/core` custom runtime. Each call has its own
78
+ * state, ledger, faults, and session counter. Rejects with `McpEmulatorInputInvalid` for an
79
+ * invalid seed or option. See `src/stateful-emulator.ts` for the request precedence.
80
+ */
81
+ declare const makeMcpEmulator: (options?: McpEmulatorOptions) => Promise<McpEmulator>;
82
+ //#endregion
83
+ export { type EmulatorEvidence, type EmulatorRouteEvidence, McpCoverage, McpEmulator, type McpEmulatorDrills, McpEmulatorInputInvalid, McpEmulatorModernListing, McpEmulatorOptions, McpEmulatorSeed, McpEmulatorSession, type McpEmulatorState, McpEmulatorStateSchema, McpFault, McpFaultMatch, McpFaultState, McpLedgerEntry, type McpRecordedExchange, type McpRecordedFixture, type McpRecordedRequest, type McpRecordedResponse, emulatorEvidenceHeader, isMcpEmulatedRequestId, makeMcpEmulator, mcpEmulatorDrillKnobs, mcpEmulatorFixtures, mcpEmulatorLegacyPath, mcpEmulatorModernPath, mcpEmulatorOrigin, mcpEmulatorReservedInvalidCredential, mcpEmulatorRoutes, mcpEmulatorSessionCap, mcpEmulatorSessionPrefix };
84
+ //# sourceMappingURL=mcp.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.mts","names":[],"sources":["../src/mcp.ts"],"mappings":";;;;;;;;;AA6KmE;AAUnE;;;cAVa,iBAAA,EAAmB,aAAa,CAAC,qBAAA;;;;;;;;cAUjC,aAAA,0BAAa,MAAA;EAAA;;;;KAEd,aAAA,UAAuB,kBAAA,CAAmB,IAAI;;;;AAAA;AAU1D;;;;cAAa,QAAA,0BAAQ,KAAA,mCAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;KAET,QAAA,GAAW,mBAAmB;AAAA,KAE9B,aAAA,GAAgB,kBAAkB,CAAC,QAAA;AAAA,KAEnC,cAAA,GAAiB,mBAAmB;AAAA,KAEpC,WAAA,GAAc,gBAAgB;AAAA,cAAA,4BAAA;;;;cAG7B,uBAAA,SAAgC,4BAAA;EAAA,SAClC,KAAA,EAAO,iBAAA;EAAA,SACP,MAAA;AAAA;EAAA,IAEI,OAAA,CAAA;AAAA;AAAA,KAKH,kBAAA;kGAED,IAAA,GAAO,eAAA;WAEP,MAAA,GAAS,iBAAiB;AAAA;AAAA,KAGzB,WAAA,GAAc,mBAAA,CAAoB,gBAAA,EAAkB,eAAA,EAAiB,QAAA;;;;;;cAgBpE,eAAA,GAAyB,OAAA,GAAS,kBAAA,KAA0B,OAAA,CAAQ,WAAA"}
package/dist/mcp.mjs ADDED
@@ -0,0 +1,241 @@
1
+ import { emulatorEvidenceHeader } from "./route-evidence.mjs";
2
+ import { isRecognisableBearerValue } from "./stateful-secrets.mjs";
3
+ import { StatefulFaultMatch, StatefulStreamFault, checkBooleanDrills, makeChunkedStatefulEmulator, routeManifest } from "./stateful-emulator.mjs";
4
+ import { statefulCoreRuntime } from "./stateful-core.mjs";
5
+ import { mcpEmulatorFixtures } from "./mcp/recordings.mjs";
6
+ import { McpEmulatorModernListing, McpEmulatorSeed, McpEmulatorSession, McpEmulatorStateSchema, buildSeedState, decodeState, makeMcpRuntime, mcpBearerDigest, mcpEmulatorLegacyPath, mcpEmulatorModernPath, mcpEmulatorOrigin, mcpEmulatorReservedInvalidCredential, mcpEmulatorSessionCap, mcpEmulatorSessionPrefix } from "./mcp/state.mjs";
7
+ import { isMcpEmulatedRequestId, mcpApiRoutes, mcpEmulatorDrillKnobs, mcpRecordingProblems } from "./mcp/api.mjs";
8
+ import { Data, Predicate } from "effect";
9
+ //#region src/mcp.ts
10
+ /**
11
+ * Stateful MCP emulator (the two synthetic servers of the MCP conformance fixtures: profile
12
+ * `synthetic-modern` on `https://mcp.example.test/modern/mcp`, stateless `2026-07-28` with JSON
13
+ * answers, and profile `synthetic-legacy` on `https://mcp.example.test/legacy/mcp`, an
14
+ * `initialize` handshake with sessions and SSE answers), built on the upstream `@emulators/core`
15
+ * custom runtime, with a request ledger, status and truncation faults, and an `/_emulate/*`
16
+ * control plane.
17
+ *
18
+ * It never imports SDK code: its answers are the sixteen synthetic `@yolk-sdk/mcp/conformance`
19
+ * fixtures copied as data (`src/mcp/recordings.ts`), and every manifest row names the conformance
20
+ * cases whose fixtures it answers (`mcpEmulatorRoutes`: one `RPC <origin><path>#<method>` row per
21
+ * recorded JSON-RPC method of each profile, plus the legacy `GET` row; no row writes anything in a
22
+ * real service). Response behaviour comes only from the fixtures, byte for byte: a JSON-RPC POST is
23
+ * answered only when it equals a recorded request within the latitude below, with the recorded
24
+ * answer, the request id substituted at exactly the recorded place (the top-level `id` of a JSON
25
+ * answer, or the `id` of the SSE response event's payload; notification events and SSE `id:` lines
26
+ * stay byte for byte; an answer that does not carry the recorded request id, such as the legacy era
27
+ * probe's `id: null` error, is unchanged). The legacy `initialize` mints a session
28
+ * `yolk-emu-session-<n>` (`n` from a counter that never resets, a form no seed holds), answered in
29
+ * the recorded `mcp-session-id` header; `notifications/initialized` on that session answers the
30
+ * recorded 202 and makes it ready; on a ready session `tools/list`, `tools/call`, and the standing
31
+ * `GET` (the recorded 405) answer the recordings with the session's id. At most 256 sessions are
32
+ * held: another `initialize` is refused before any fault. `reset` and `seed` clear the sessions.
33
+ * The seed only selects which recorded modern listing `tools/list` answers (`modernListing`:
34
+ * `one-page`, the default, or `two-pages`, whose first page issues the recorded cursor in the
35
+ * generation that first issues it, and `<cursor>.g<generation>` after a reset or seed; the second
36
+ * page answers only the cursor issued in the current generation). Every plan prepares its answer
37
+ * before anything is written; its commit (minting a session, readying one, issuing a cursor) runs
38
+ * only when no fault answers the request. Status faults (400-599) and `truncate-after-chunks`
39
+ * faults apply only after a request is admitted and planned, and a faulted request writes nothing:
40
+ * a truncation sends the prepared answer cut short and never runs the commit, so a truncated
41
+ * `initialize` holds no session and leaves the counter and the cap where they were, and a truncated
42
+ * first page issues no cursor. `match.route` selects one manifest row (a value naming no row is
43
+ * rejected when the fault is added); `match.method` is the HTTP method. Anything else answers one
44
+ * 400 not-emulated, ledgered with constant text only (`/<unrecognised>`, a standard method or
45
+ * `<other>`, an empty query, no headers or body, a constant reason, and the route template or row),
46
+ * that writes nothing and uses up no fault.
47
+ *
48
+ * Not emulated: `DELETE` (the client never sends it), `ping`, `resources/*`, `prompts/*`,
49
+ * `logging/*`, `completion/*`, `tasks/*`, JSON-RPC batches and client-sent responses, a JSON body
50
+ * repeating a key (the wrapper's opt-in `uniqueJsonKeys`), `mcp-*` headers no recording carries
51
+ * (such as `mcp-param-*`), cursors this emulator did not issue, any other tool or arguments, any
52
+ * other origin or path, and a missing `Authorization` (no fixture records the answer to one).
53
+ *
54
+ * Fail closed, on the shared wrapper's fail-closed mode as `/github`, `/google`, and
55
+ * `/linkedin-search` use it, with its opt-in `constantRefusals`, `guardAllHeaders`, and
56
+ * `guardOutput`: a request is recognised only on an emulated route shape, and any `Authorization`
57
+ * header is exactly `Bearer <token>` with a recognisable bearer (the RFC 6750 `b64token` syntax, at
58
+ * least 8 characters, a first character in `[G-Zg-z\-._~+/]` other than `n`, `r`, `t`, `u`, and a
59
+ * character outside `[0-9.eE+-]`). A recognised request that repeats the bearer anywhere (its raw
60
+ * path, the raw query or any query key or value, any request header name or value other than
61
+ * `Authorization`, or its body, through the wrapper's fixpoint closure of tolerant percent-decoding
62
+ * and JSON-unescaping, capped, where a cap refuses) is ledgered with constant text only. The
63
+ * prepared output is checked the same way before any fault is decided or anything is committed: an
64
+ * answer (every header and chunk) or a minted session id or cursor that would repeat the bearer is
65
+ * refused with the constant credential-repeat entry, no fault used and nothing written, so a bearer
66
+ * such as `yolk-emu-session-1`, or `synthetic-mcp` (inside the recorded `yolk-synthetic-mcp`),
67
+ * never reaches a response, the state, or `/_emulate/*`. The bearer is never stored, forwarded,
68
+ * ledgered, or echoed: routes see only its digest (the wrapper's opt-in `bearerDigest`; SHA-256 of
69
+ * the origin, a space, and the bearer), which they compare only with the digest of the public
70
+ * reserved invalid credential `yolk-conformance-invalid-credential-0000` (itself a recognisable
71
+ * bearer) to answer its recorded 401 byte for byte. Scope: the bearer is never copied from the
72
+ * request into a response, the state, or `/_emulate/*`; the output guard also refuses a prepared
73
+ * fixture answer, minted session id, or cursor that happens to contain it, but the emulator's other
74
+ * constants (state values such as `initializing`, wrapper headers such as `x-emulator-evidence`)
75
+ * and host-configured control-plane data (a fault body) may coincidentally equal a bearer and are
76
+ * not checked. `makeMcpEmulator` also throws when a copied recording is not canonical JSON (every
77
+ * JSON body and SSE `data:` payload equal to `JSON.stringify(JSON.parse(text))`), which id
78
+ * substitution relies on.
79
+ *
80
+ * Request-shape latitude (`/mcp`, the only accepted deviations): any bearer value in the RFC 6750
81
+ * `b64token` syntax (`[A-Za-z0-9\-._~+/]+=*`) of at least 8 characters, starting with a character
82
+ * in `[G-Zg-z\-._~+/]` other than `n`, `r`, `t`, `u`, with at least one outside `[0-9.eE+-]`, that
83
+ * occurs nowhere else in the request (any header name or value included) and in no answer or value
84
+ * the request would store (never stored or ledgered; only its digest is compared, with the digest
85
+ * of the public reserved invalid credential `yolk-conformance-invalid-credential-0000`, which
86
+ * answers the recorded 401 on the era probe); extra request headers, except `mcp-*` headers other
87
+ * than `mcp-method`, `mcp-name`, `mcp-protocol-version`, and `mcp-session-id`; a recorded header
88
+ * value sent as several headers that the HTTP layer joins into the recorded value; JSON key order;
89
+ * any JSON-RPC request id that is an integer from 0 to 2^53 - 1 or 1 to 64 printable ASCII
90
+ * characters where the recording has an id; any non-empty `name` and `version` (and no other key)
91
+ * in the `_meta` client info (`io.modelcontextprotocol/clientInfo`) of a modern request; a session
92
+ * id this emulator minted since the last reset or seed where the recording sends `mcp-session-id`
93
+ * (initializing for `notifications/initialized`, ready otherwise); and, with the seed's `two-pages`
94
+ * listing, the cursor this emulator issued in the current generation on the second page.
95
+ * `Authorization` must be exactly `Bearer <token>` (that spelling, one space). Everything else
96
+ * (another origin or path, any query, other HTTP methods such as `DELETE` or a `GET` on the modern
97
+ * profile, JSON-RPC methods no fixture of the profile records such as `ping`, `resources/*`, or
98
+ * `prompts/*`, batches and client-sent responses, other members, a JSON body repeating a key
99
+ * (compared after unescaping), a `null`, negative, or fractional id, other params (other tools,
100
+ * arguments, protocol versions, or capabilities, extra client-info keys, and a legacy `initialize`
101
+ * client info other than the recorded one), the MCP headers `accept`, `content-type`, `mcp-method`,
102
+ * `mcp-protocol-version`, `mcp-name`, and `last-event-id` other than the recorded values or present
103
+ * where none is recorded, any other `mcp-*` header (such as `mcp-param-*`), `mcp-session-id`
104
+ * missing where recorded or present where not, an unknown session or one in the wrong phase, a
105
+ * cursor not issued in the current generation, the reserved invalid credential on anything but the
106
+ * era probe, a bearer repeated anywhere in the request, and a bearer an answer or a minted session
107
+ * id or cursor would repeat) is not emulated.
108
+ *
109
+ * Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by
110
+ * `makeMcpEmulator` (importing this module has no side effects).
111
+ *
112
+ * @experimental
113
+ */
114
+ /**
115
+ * Route evidence manifest: one `RPC <origin><path>#<method>` row per recorded JSON-RPC method of
116
+ * each profile, plus the legacy `GET` row, with the conformance cases whose (synthetic,
117
+ * unverified) fixtures each answers. No row writes anything. Kept in sync with the handlers by
118
+ * construction (both come from one route table).
119
+ */
120
+ const mcpEmulatorRoutes = mcpApiRoutes.flatMap(routeManifest);
121
+ /**
122
+ * Optional fault filter; an omitted field matches every request. `method` is the HTTP method
123
+ * (`POST` or `GET`, never a row's `RPC`); `path` is the raw request path (ending in `*`, a
124
+ * prefix); `route` is a manifest row path (for example
125
+ * `https://mcp.example.test/legacy/mcp#tools/list`), and a value naming no row is rejected when
126
+ * the fault is added.
127
+ */
128
+ const McpFaultMatch = StatefulFaultMatch;
129
+ /**
130
+ * A status fault (400-599), or a `truncate-after-chunks` fault that sends the first `chunks`
131
+ * chunks of the prepared answer and then ends it cleanly (an SSE answer has two chunks, a JSON
132
+ * answer one). Only a request the emulator would answer reaches a fault: a request that is not
133
+ * emulated, by its shape or by the state, never uses one up. A faulted request writes nothing (a
134
+ * truncated `initialize` mints no session; a truncated first page issues no cursor). A truncation
135
+ * that cannot apply answers 500 and is not used up.
136
+ */
137
+ const McpFault = StatefulStreamFault;
138
+ /** Invalid emulator input from the JS API: a seed, a fault, or an option. A programmer error. */
139
+ var McpEmulatorInputInvalid = class extends Data.TaggedError("McpEmulatorInputInvalid") {
140
+ get message() {
141
+ return `Invalid MCP emulator ${this.input}: ${this.reason}`;
142
+ }
143
+ };
144
+ const inputInvalid = (input, reason) => new McpEmulatorInputInvalid({
145
+ input,
146
+ reason
147
+ });
148
+ /** The constant reason of a request on no emulated route shape. */
149
+ const unrecognisedReason = "no emulated MCP route for this method and path";
150
+ /** The constant reason of a request whose `Authorization` header is not one recognisable bearer. */
151
+ const unrecognisedAuthorizationReason = "an unrecognisable Authorization header is not emulated";
152
+ /**
153
+ * Create a stateful MCP emulator on the `@emulators/core` custom runtime. Each call has its own
154
+ * state, ledger, faults, and session counter. Rejects with `McpEmulatorInputInvalid` for an
155
+ * invalid seed or option. See `src/stateful-emulator.ts` for the request precedence.
156
+ */
157
+ const makeMcpEmulator = async (options = {}) => {
158
+ const initial = buildSeedState(options.seed ?? {});
159
+ if (Predicate.isString(initial)) throw inputInvalid("seed", initial);
160
+ checkBooleanDrills(options.drills, mcpEmulatorDrillKnobs, inputInvalid);
161
+ if (!isRecognisableBearerValue("yolk-conformance-invalid-credential-0000")) throw new Error("the reserved invalid MCP credential is not a recognisable bearer");
162
+ const recordingProblems = mcpRecordingProblems(mcpEmulatorFixtures);
163
+ if (recordingProblems.length > 0) throw new Error(`non-canonical MCP recordings: ${recordingProblems.join("; ")}`);
164
+ const drills = options.drills ?? {};
165
+ const runtime = makeMcpRuntime();
166
+ return makeChunkedStatefulEmulator({
167
+ routes: mcpApiRoutes,
168
+ env: {
169
+ drills: {
170
+ discoverCarriesErrorResponse: drills.discoverCarriesErrorResponse === true,
171
+ discoverWithoutResultType: drills.discoverWithoutResultType === true,
172
+ sessionIdNotVisibleAscii: drills.sessionIdNotVisibleAscii === true,
173
+ discoverAnsweredTwice: drills.discoverAnsweredTwice === true,
174
+ writeToolMarkedReadOnly: drills.writeToolMarkedReadOnly === true,
175
+ readCallAnswersToolError: drills.readCallAnswersToolError === true,
176
+ invalidCallAnswersRpcError: drills.invalidCallAnswersRpcError === true,
177
+ absentCallAnswersResult: drills.absentCallAnswersResult === true,
178
+ unauthorizedWithoutChallenge: drills.unauthorizedWithoutChallenge === true
179
+ },
180
+ reservedDigest: mcpBearerDigest(mcpEmulatorReservedInvalidCredential, mcpEmulatorOrigin),
181
+ runtime
182
+ },
183
+ initial,
184
+ buildSeed: buildSeedState,
185
+ recordHeaders: [
186
+ {
187
+ name: "accept",
188
+ json: false
189
+ },
190
+ {
191
+ name: "content-type",
192
+ json: false
193
+ },
194
+ {
195
+ name: "mcp-method",
196
+ json: false
197
+ },
198
+ {
199
+ name: "mcp-name",
200
+ json: false
201
+ },
202
+ {
203
+ name: "mcp-protocol-version",
204
+ json: false
205
+ },
206
+ {
207
+ name: "mcp-session-id",
208
+ json: false
209
+ }
210
+ ],
211
+ failClosed: {
212
+ unrecognised: unrecognisedReason,
213
+ unrecognisedAuthorization: unrecognisedAuthorizationReason
214
+ },
215
+ bearerDigest: mcpBearerDigest,
216
+ constantRefusals: true,
217
+ guardAllHeaders: true,
218
+ guardOutput: true,
219
+ uniqueJsonKeys: true,
220
+ clearRuntime: () => {
221
+ runtime.generation += 1;
222
+ runtime.issuedCursor = void 0;
223
+ },
224
+ runtimeState: () => ({
225
+ nextSession: runtime.nextSession,
226
+ cursorGeneration: runtime.generation,
227
+ issuedCursor: runtime.issuedCursor ?? null
228
+ }),
229
+ seedSummary: (state) => ({ modernListing: state.modernListing }),
230
+ inputInvalid
231
+ }, statefulCoreRuntime({
232
+ name: "mcp",
233
+ initial,
234
+ decodeState,
235
+ inputInvalid
236
+ }));
237
+ };
238
+ //#endregion
239
+ export { McpEmulatorInputInvalid, McpEmulatorModernListing, McpEmulatorSeed, McpEmulatorSession, McpEmulatorStateSchema, McpFault, McpFaultMatch, emulatorEvidenceHeader, isMcpEmulatedRequestId, makeMcpEmulator, mcpEmulatorDrillKnobs, mcpEmulatorFixtures, mcpEmulatorLegacyPath, mcpEmulatorModernPath, mcpEmulatorOrigin, mcpEmulatorReservedInvalidCredential, mcpEmulatorRoutes, mcpEmulatorSessionCap, mcpEmulatorSessionPrefix };
240
+
241
+ //# sourceMappingURL=mcp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.mjs","names":[],"sources":["../src/mcp.ts"],"sourcesContent":["/**\n * Stateful MCP emulator (the two synthetic servers of the MCP conformance fixtures: profile\n * `synthetic-modern` on `https://mcp.example.test/modern/mcp`, stateless `2026-07-28` with JSON\n * answers, and profile `synthetic-legacy` on `https://mcp.example.test/legacy/mcp`, an\n * `initialize` handshake with sessions and SSE answers), built on the upstream `@emulators/core`\n * custom runtime, with a request ledger, status and truncation faults, and an `/_emulate/*`\n * control plane.\n *\n * It never imports SDK code: its answers are the sixteen synthetic `@yolk-sdk/mcp/conformance`\n * fixtures copied as data (`src/mcp/recordings.ts`), and every manifest row names the conformance\n * cases whose fixtures it answers (`mcpEmulatorRoutes`: one `RPC <origin><path>#<method>` row per\n * recorded JSON-RPC method of each profile, plus the legacy `GET` row; no row writes anything in a\n * real service). Response behaviour comes only from the fixtures, byte for byte: a JSON-RPC POST is\n * answered only when it equals a recorded request within the latitude below, with the recorded\n * answer, the request id substituted at exactly the recorded place (the top-level `id` of a JSON\n * answer, or the `id` of the SSE response event's payload; notification events and SSE `id:` lines\n * stay byte for byte; an answer that does not carry the recorded request id, such as the legacy era\n * probe's `id: null` error, is unchanged). The legacy `initialize` mints a session\n * `yolk-emu-session-<n>` (`n` from a counter that never resets, a form no seed holds), answered in\n * the recorded `mcp-session-id` header; `notifications/initialized` on that session answers the\n * recorded 202 and makes it ready; on a ready session `tools/list`, `tools/call`, and the standing\n * `GET` (the recorded 405) answer the recordings with the session's id. At most 256 sessions are\n * held: another `initialize` is refused before any fault. `reset` and `seed` clear the sessions.\n * The seed only selects which recorded modern listing `tools/list` answers (`modernListing`:\n * `one-page`, the default, or `two-pages`, whose first page issues the recorded cursor in the\n * generation that first issues it, and `<cursor>.g<generation>` after a reset or seed; the second\n * page answers only the cursor issued in the current generation). Every plan prepares its answer\n * before anything is written; its commit (minting a session, readying one, issuing a cursor) runs\n * only when no fault answers the request. Status faults (400-599) and `truncate-after-chunks`\n * faults apply only after a request is admitted and planned, and a faulted request writes nothing:\n * a truncation sends the prepared answer cut short and never runs the commit, so a truncated\n * `initialize` holds no session and leaves the counter and the cap where they were, and a truncated\n * first page issues no cursor. `match.route` selects one manifest row (a value naming no row is\n * rejected when the fault is added); `match.method` is the HTTP method. Anything else answers one\n * 400 not-emulated, ledgered with constant text only (`/<unrecognised>`, a standard method or\n * `<other>`, an empty query, no headers or body, a constant reason, and the route template or row),\n * that writes nothing and uses up no fault.\n *\n * Not emulated: `DELETE` (the client never sends it), `ping`, `resources/*`, `prompts/*`,\n * `logging/*`, `completion/*`, `tasks/*`, JSON-RPC batches and client-sent responses, a JSON body\n * repeating a key (the wrapper's opt-in `uniqueJsonKeys`), `mcp-*` headers no recording carries\n * (such as `mcp-param-*`), cursors this emulator did not issue, any other tool or arguments, any\n * other origin or path, and a missing `Authorization` (no fixture records the answer to one).\n *\n * Fail closed, on the shared wrapper's fail-closed mode as `/github`, `/google`, and\n * `/linkedin-search` use it, with its opt-in `constantRefusals`, `guardAllHeaders`, and\n * `guardOutput`: a request is recognised only on an emulated route shape, and any `Authorization`\n * header is exactly `Bearer <token>` with a recognisable bearer (the RFC 6750 `b64token` syntax, at\n * least 8 characters, a first character in `[G-Zg-z\\-._~+/]` other than `n`, `r`, `t`, `u`, and a\n * character outside `[0-9.eE+-]`). A recognised request that repeats the bearer anywhere (its raw\n * path, the raw query or any query key or value, any request header name or value other than\n * `Authorization`, or its body, through the wrapper's fixpoint closure of tolerant percent-decoding\n * and JSON-unescaping, capped, where a cap refuses) is ledgered with constant text only. The\n * prepared output is checked the same way before any fault is decided or anything is committed: an\n * answer (every header and chunk) or a minted session id or cursor that would repeat the bearer is\n * refused with the constant credential-repeat entry, no fault used and nothing written, so a bearer\n * such as `yolk-emu-session-1`, or `synthetic-mcp` (inside the recorded `yolk-synthetic-mcp`),\n * never reaches a response, the state, or `/_emulate/*`. The bearer is never stored, forwarded,\n * ledgered, or echoed: routes see only its digest (the wrapper's opt-in `bearerDigest`; SHA-256 of\n * the origin, a space, and the bearer), which they compare only with the digest of the public\n * reserved invalid credential `yolk-conformance-invalid-credential-0000` (itself a recognisable\n * bearer) to answer its recorded 401 byte for byte. Scope: the bearer is never copied from the\n * request into a response, the state, or `/_emulate/*`; the output guard also refuses a prepared\n * fixture answer, minted session id, or cursor that happens to contain it, but the emulator's other\n * constants (state values such as `initializing`, wrapper headers such as `x-emulator-evidence`)\n * and host-configured control-plane data (a fault body) may coincidentally equal a bearer and are\n * not checked. `makeMcpEmulator` also throws when a copied recording is not canonical JSON (every\n * JSON body and SSE `data:` payload equal to `JSON.stringify(JSON.parse(text))`), which id\n * substitution relies on.\n *\n * Request-shape latitude (`/mcp`, the only accepted deviations): any bearer value in the RFC 6750\n * `b64token` syntax (`[A-Za-z0-9\\-._~+/]+=*`) of at least 8 characters, starting with a character\n * in `[G-Zg-z\\-._~+/]` other than `n`, `r`, `t`, `u`, with at least one outside `[0-9.eE+-]`, that\n * occurs nowhere else in the request (any header name or value included) and in no answer or value\n * the request would store (never stored or ledgered; only its digest is compared, with the digest\n * of the public reserved invalid credential `yolk-conformance-invalid-credential-0000`, which\n * answers the recorded 401 on the era probe); extra request headers, except `mcp-*` headers other\n * than `mcp-method`, `mcp-name`, `mcp-protocol-version`, and `mcp-session-id`; a recorded header\n * value sent as several headers that the HTTP layer joins into the recorded value; JSON key order;\n * any JSON-RPC request id that is an integer from 0 to 2^53 - 1 or 1 to 64 printable ASCII\n * characters where the recording has an id; any non-empty `name` and `version` (and no other key)\n * in the `_meta` client info (`io.modelcontextprotocol/clientInfo`) of a modern request; a session\n * id this emulator minted since the last reset or seed where the recording sends `mcp-session-id`\n * (initializing for `notifications/initialized`, ready otherwise); and, with the seed's `two-pages`\n * listing, the cursor this emulator issued in the current generation on the second page.\n * `Authorization` must be exactly `Bearer <token>` (that spelling, one space). Everything else\n * (another origin or path, any query, other HTTP methods such as `DELETE` or a `GET` on the modern\n * profile, JSON-RPC methods no fixture of the profile records such as `ping`, `resources/*`, or\n * `prompts/*`, batches and client-sent responses, other members, a JSON body repeating a key\n * (compared after unescaping), a `null`, negative, or fractional id, other params (other tools,\n * arguments, protocol versions, or capabilities, extra client-info keys, and a legacy `initialize`\n * client info other than the recorded one), the MCP headers `accept`, `content-type`, `mcp-method`,\n * `mcp-protocol-version`, `mcp-name`, and `last-event-id` other than the recorded values or present\n * where none is recorded, any other `mcp-*` header (such as `mcp-param-*`), `mcp-session-id`\n * missing where recorded or present where not, an unknown session or one in the wrong phase, a\n * cursor not issued in the current generation, the reserved invalid credential on anything but the\n * era probe, a bearer repeated anywhere in the request, and a bearer an answer or a minted session\n * id or cursor would repeat) is not emulated.\n *\n * Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by\n * `makeMcpEmulator` (importing this module has no side effects).\n *\n * @experimental\n */\nimport { Data, Predicate } from 'effect'\nimport {\n mcpApiRoutes,\n mcpEmulatorDrillKnobs,\n mcpRecordingProblems,\n type McpApiEnv,\n type McpEmulatorDrills\n} from './mcp/api.ts'\nimport { mcpEmulatorFixtures } from './mcp/recordings.ts'\nimport {\n buildSeedState,\n decodeState,\n makeMcpRuntime,\n mcpBearerDigest,\n mcpEmulatorOrigin,\n mcpEmulatorReservedInvalidCredential,\n type McpEmulatorSeed,\n type McpEmulatorState\n} from './mcp/state.ts'\nimport type { EmulatorRouteEvidence } from './route-evidence.ts'\nimport {\n StatefulFaultMatch,\n StatefulStreamFault,\n checkBooleanDrills,\n makeChunkedStatefulEmulator,\n routeManifest,\n type StatefulCoverage,\n type StatefulEmulatorApi,\n type StatefulFaultState,\n type StatefulInputKind,\n type StatefulLedgerEntry\n} from './stateful-emulator.ts'\nimport { statefulCoreRuntime } from './stateful-core.ts'\nimport { isRecognisableBearerValue } from './stateful-secrets.ts'\n\nexport type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'\n\nexport { emulatorEvidenceHeader } from './route-evidence.ts'\n\nexport { isMcpEmulatedRequestId, mcpEmulatorDrillKnobs, type McpEmulatorDrills } from './mcp/api.ts'\n\nexport {\n McpEmulatorModernListing,\n McpEmulatorSeed,\n McpEmulatorSession,\n McpEmulatorStateSchema,\n mcpEmulatorLegacyPath,\n mcpEmulatorModernPath,\n mcpEmulatorOrigin,\n mcpEmulatorReservedInvalidCredential,\n mcpEmulatorSessionCap,\n mcpEmulatorSessionPrefix,\n type McpEmulatorState\n} from './mcp/state.ts'\n\nexport {\n mcpEmulatorFixtures,\n type McpRecordedExchange,\n type McpRecordedFixture,\n type McpRecordedRequest,\n type McpRecordedResponse\n} from './mcp/recordings.ts'\n\n/**\n * Route evidence manifest: one `RPC <origin><path>#<method>` row per recorded JSON-RPC method of\n * each profile, plus the legacy `GET` row, with the conformance cases whose (synthetic,\n * unverified) fixtures each answers. No row writes anything. Kept in sync with the handlers by\n * construction (both come from one route table).\n */\nexport const mcpEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> =\n mcpApiRoutes.flatMap(routeManifest)\n\n/**\n * Optional fault filter; an omitted field matches every request. `method` is the HTTP method\n * (`POST` or `GET`, never a row's `RPC`); `path` is the raw request path (ending in `*`, a\n * prefix); `route` is a manifest row path (for example\n * `https://mcp.example.test/legacy/mcp#tools/list`), and a value naming no row is rejected when\n * the fault is added.\n */\nexport const McpFaultMatch = StatefulFaultMatch\n\nexport type McpFaultMatch = typeof StatefulFaultMatch.Type\n\n/**\n * A status fault (400-599), or a `truncate-after-chunks` fault that sends the first `chunks`\n * chunks of the prepared answer and then ends it cleanly (an SSE answer has two chunks, a JSON\n * answer one). Only a request the emulator would answer reaches a fault: a request that is not\n * emulated, by its shape or by the state, never uses one up. A faulted request writes nothing (a\n * truncated `initialize` mints no session; a truncated first page issues no cursor). A truncation\n * that cannot apply answers 500 and is not used up.\n */\nexport const McpFault = StatefulStreamFault\n\nexport type McpFault = StatefulStreamFault\n\nexport type McpFaultState = StatefulFaultState<McpFault>\n\nexport type McpLedgerEntry = StatefulLedgerEntry\n\nexport type McpCoverage = StatefulCoverage\n\n/** Invalid emulator input from the JS API: a seed, a fault, or an option. A programmer error. */\nexport class McpEmulatorInputInvalid extends Data.TaggedError('McpEmulatorInputInvalid')<{\n readonly input: StatefulInputKind\n readonly reason: string\n}> {\n override get message(): string {\n return `Invalid MCP emulator ${this.input}: ${this.reason}`\n }\n}\n\nexport type McpEmulatorOptions = {\n /** Typed seed; defaults to the one-page modern listing (sessions are never seeded). */\n readonly seed?: McpEmulatorSeed\n /** Drill knobs (tests only): make the emulator disagree with one conformance claim. */\n readonly drills?: McpEmulatorDrills\n}\n\nexport type McpEmulator = StatefulEmulatorApi<McpEmulatorState, McpEmulatorSeed, McpFault>\n\nconst inputInvalid = (input: StatefulInputKind, reason: string) =>\n new McpEmulatorInputInvalid({ input, reason })\n\n/** The constant reason of a request on no emulated route shape. */\nconst unrecognisedReason = 'no emulated MCP route for this method and path'\n\n/** The constant reason of a request whose `Authorization` header is not one recognisable bearer. */\nconst unrecognisedAuthorizationReason = 'an unrecognisable Authorization header is not emulated'\n\n/**\n * Create a stateful MCP emulator on the `@emulators/core` custom runtime. Each call has its own\n * state, ledger, faults, and session counter. Rejects with `McpEmulatorInputInvalid` for an\n * invalid seed or option. See `src/stateful-emulator.ts` for the request precedence.\n */\nexport const makeMcpEmulator = async (options: McpEmulatorOptions = {}): Promise<McpEmulator> => {\n const initial = buildSeedState(options.seed ?? {})\n\n if (Predicate.isString(initial)) {\n throw inputInvalid('seed', initial)\n }\n\n checkBooleanDrills(options.drills, mcpEmulatorDrillKnobs, inputInvalid)\n\n // The reserved invalid credential must reach the routes as a recognisable bearer's digest; a\n // value the bearer rule refused would never be answered its recorded 401.\n if (!isRecognisableBearerValue(mcpEmulatorReservedInvalidCredential)) {\n throw new Error('the reserved invalid MCP credential is not a recognisable bearer')\n }\n\n // Id substitution re-serialises the response message: a recording copied in a non-canonical\n // JSON form would answer other bytes, so it fails here, loudly.\n const recordingProblems = mcpRecordingProblems(mcpEmulatorFixtures)\n\n if (recordingProblems.length > 0) {\n throw new Error(`non-canonical MCP recordings: ${recordingProblems.join('; ')}`)\n }\n\n const drills = options.drills ?? {}\n const runtime = makeMcpRuntime()\n\n const env: McpApiEnv = {\n drills: {\n discoverCarriesErrorResponse: drills.discoverCarriesErrorResponse === true,\n discoverWithoutResultType: drills.discoverWithoutResultType === true,\n sessionIdNotVisibleAscii: drills.sessionIdNotVisibleAscii === true,\n discoverAnsweredTwice: drills.discoverAnsweredTwice === true,\n writeToolMarkedReadOnly: drills.writeToolMarkedReadOnly === true,\n readCallAnswersToolError: drills.readCallAnswersToolError === true,\n invalidCallAnswersRpcError: drills.invalidCallAnswersRpcError === true,\n absentCallAnswersResult: drills.absentCallAnswersResult === true,\n unauthorizedWithoutChallenge: drills.unauthorizedWithoutChallenge === true\n },\n reservedDigest: mcpBearerDigest(mcpEmulatorReservedInvalidCredential, mcpEmulatorOrigin),\n runtime\n }\n\n return makeChunkedStatefulEmulator<McpEmulatorState, McpApiEnv, McpEmulatorSeed>(\n {\n routes: mcpApiRoutes,\n env,\n initial,\n buildSeed: buildSeedState,\n recordHeaders: [\n { name: 'accept', json: false },\n { name: 'content-type', json: false },\n { name: 'mcp-method', json: false },\n { name: 'mcp-name', json: false },\n { name: 'mcp-protocol-version', json: false },\n { name: 'mcp-session-id', json: false }\n ],\n failClosed: {\n unrecognised: unrecognisedReason,\n unrecognisedAuthorization: unrecognisedAuthorizationReason\n },\n bearerDigest: mcpBearerDigest,\n constantRefusals: true,\n guardAllHeaders: true,\n guardOutput: true,\n uniqueJsonKeys: true,\n // Every reset and seed starts a cursor generation; the session counter never resets.\n clearRuntime: () => {\n runtime.generation += 1\n runtime.issuedCursor = undefined\n },\n runtimeState: () => ({\n nextSession: runtime.nextSession,\n cursorGeneration: runtime.generation,\n issuedCursor: runtime.issuedCursor ?? null\n }),\n seedSummary: state => ({ modernListing: state.modernListing }),\n inputInvalid\n },\n statefulCoreRuntime({ name: 'mcp', initial, decodeState, inputInvalid })\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6KA,MAAa,oBACX,aAAa,QAAQ,aAAa;;;;;;;;AASpC,MAAa,gBAAgB;;;;;;;;;AAY7B,MAAa,WAAW;;AAWxB,IAAa,0BAAb,cAA6C,KAAK,YAAY,yBAAyB,EAGpF;CACD,IAAa,UAAkB;EAC7B,OAAO,wBAAwB,KAAK,MAAM,IAAI,KAAK;CACrD;AACF;AAWA,MAAM,gBAAgB,OAA0B,WAC9C,IAAI,wBAAwB;CAAE;CAAO;AAAO,CAAC;;AAG/C,MAAM,qBAAqB;;AAG3B,MAAM,kCAAkC;;;;;;AAOxC,MAAa,kBAAkB,OAAO,UAA8B,CAAC,MAA4B;CAC/F,MAAM,UAAU,eAAe,QAAQ,QAAQ,CAAC,CAAC;CAEjD,IAAI,UAAU,SAAS,OAAO,GAC5B,MAAM,aAAa,QAAQ,OAAO;CAGpC,mBAAmB,QAAQ,QAAQ,uBAAuB,YAAY;CAItE,IAAI,CAAC,0BAAA,0CAA8D,GACjE,MAAM,IAAI,MAAM,kEAAkE;CAKpF,MAAM,oBAAoB,qBAAqB,mBAAmB;CAElE,IAAI,kBAAkB,SAAS,GAC7B,MAAM,IAAI,MAAM,iCAAiC,kBAAkB,KAAK,IAAI,GAAG;CAGjF,MAAM,SAAS,QAAQ,UAAU,CAAC;CAClC,MAAM,UAAU,eAAe;CAkB/B,OAAO,4BACL;EACE,QAAQ;EACR,KAAA;GAlBF,QAAQ;IACN,8BAA8B,OAAO,iCAAiC;IACtE,2BAA2B,OAAO,8BAA8B;IAChE,0BAA0B,OAAO,6BAA6B;IAC9D,uBAAuB,OAAO,0BAA0B;IACxD,yBAAyB,OAAO,4BAA4B;IAC5D,0BAA0B,OAAO,6BAA6B;IAC9D,4BAA4B,OAAO,+BAA+B;IAClE,yBAAyB,OAAO,4BAA4B;IAC5D,8BAA8B,OAAO,iCAAiC;GACxE;GACA,gBAAgB,gBAAgB,sCAAsC,iBAAiB;GACvF;EAMI;EACF;EACA,WAAW;EACX,eAAe;GACb;IAAE,MAAM;IAAU,MAAM;GAAM;GAC9B;IAAE,MAAM;IAAgB,MAAM;GAAM;GACpC;IAAE,MAAM;IAAc,MAAM;GAAM;GAClC;IAAE,MAAM;IAAY,MAAM;GAAM;GAChC;IAAE,MAAM;IAAwB,MAAM;GAAM;GAC5C;IAAE,MAAM;IAAkB,MAAM;GAAM;EACxC;EACA,YAAY;GACV,cAAc;GACd,2BAA2B;EAC7B;EACA,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,aAAa;EACb,gBAAgB;EAEhB,oBAAoB;GAClB,QAAQ,cAAc;GACtB,QAAQ,eAAe,KAAA;EACzB;EACA,qBAAqB;GACnB,aAAa,QAAQ;GACrB,kBAAkB,QAAQ;GAC1B,cAAc,QAAQ,gBAAgB;EACxC;EACA,cAAa,WAAU,EAAE,eAAe,MAAM,cAAc;EAC5D;CACF,GACA,oBAAoB;EAAE,MAAM;EAAO;EAAS;EAAa;CAAa,CAAC,CACzE;AACF"}
@@ -0,0 +1,183 @@
1
+ import { EmulatorEvidence, EmulatorRouteEvidence } from "./route-evidence.mjs";
2
+ import { EmulatorApi } from "./emulator-kernel.mjs";
3
+ import * as Schema from "effect/Schema";
4
+
5
+ //#region src/messages.d.ts
6
+ /** An Anthropic wire error: `type` (for example `overloaded_error`) and a message. */
7
+ declare const MessagesWireError: Schema.Struct<{
8
+ readonly type: Schema.NonEmptyString;
9
+ readonly message: Schema.String;
10
+ }>;
11
+ type MessagesWireError = typeof MessagesWireError.Type;
12
+ /**
13
+ * Send `chunks` SSE events, then one `event: error` event (default `overloaded_error`) and close
14
+ * without `message_stop`. Streamed responses only; it must come before `message_stop`.
15
+ */
16
+ declare const MessagesErrorEventFault: Schema.Struct<{
17
+ readonly match: Schema.optionalKey<Schema.Struct<{
18
+ readonly path: Schema.optionalKey<Schema.String>;
19
+ readonly model: Schema.optionalKey<Schema.String>;
20
+ }>>;
21
+ readonly count: Schema.optionalKey<Schema.Int>;
22
+ readonly kind: Schema.Literal<"error-event-after-chunks">;
23
+ readonly chunks: Schema.Int;
24
+ readonly error: Schema.optionalKey<Schema.Struct<{
25
+ readonly type: Schema.NonEmptyString;
26
+ readonly message: Schema.String;
27
+ }>>;
28
+ }>;
29
+ /**
30
+ * Wire faults: `status` (the body defaults to an Anthropic error envelope matching the status,
31
+ * for example `rate_limit_error` for 429 and `overloaded_error` for 529), `error-after-chunks`
32
+ * (a dropped connection), `truncate-after-chunks` (a clean close, for example before
33
+ * `message_stop`), and `error-event-after-chunks` (a mid-stream `error` event).
34
+ */
35
+ declare const MessagesFault: Schema.Union<readonly [Schema.Struct<{
36
+ readonly match: Schema.optionalKey<Schema.Struct<{
37
+ readonly path: Schema.optionalKey<Schema.String>;
38
+ readonly model: Schema.optionalKey<Schema.String>;
39
+ }>>;
40
+ readonly count: Schema.optionalKey<Schema.Int>;
41
+ readonly kind: Schema.Literal<"status">;
42
+ readonly status: Schema.Int;
43
+ readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
44
+ readonly body: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
45
+ }>, Schema.Struct<{
46
+ readonly match: Schema.optionalKey<Schema.Struct<{
47
+ readonly path: Schema.optionalKey<Schema.String>;
48
+ readonly model: Schema.optionalKey<Schema.String>;
49
+ }>>;
50
+ readonly count: Schema.optionalKey<Schema.Int>;
51
+ readonly kind: Schema.Literal<"error-after-chunks">;
52
+ readonly chunks: Schema.Int;
53
+ }>, Schema.Struct<{
54
+ readonly match: Schema.optionalKey<Schema.Struct<{
55
+ readonly path: Schema.optionalKey<Schema.String>;
56
+ readonly model: Schema.optionalKey<Schema.String>;
57
+ }>>;
58
+ readonly count: Schema.optionalKey<Schema.Int>;
59
+ readonly kind: Schema.Literal<"truncate-after-chunks">;
60
+ readonly chunks: Schema.Int;
61
+ }>, Schema.Struct<{
62
+ readonly match: Schema.optionalKey<Schema.Struct<{
63
+ readonly path: Schema.optionalKey<Schema.String>;
64
+ readonly model: Schema.optionalKey<Schema.String>;
65
+ }>>;
66
+ readonly count: Schema.optionalKey<Schema.Int>;
67
+ readonly kind: Schema.Literal<"error-event-after-chunks">;
68
+ readonly chunks: Schema.Int;
69
+ readonly error: Schema.optionalKey<Schema.Struct<{
70
+ readonly type: Schema.NonEmptyString;
71
+ readonly message: Schema.String;
72
+ }>>;
73
+ }>]>;
74
+ type MessagesFault = typeof MessagesFault.Type;
75
+ type MessagesFaultKind = MessagesFault['kind'];
76
+ /** Usage for a scripted turn (sent in `message_start` and `message_delta`). */
77
+ declare const MessagesScriptedUsage: Schema.Struct<{
78
+ readonly inputTokens: Schema.Int;
79
+ readonly outputTokens: Schema.Int;
80
+ }>;
81
+ type MessagesScriptedUsage = typeof MessagesScriptedUsage.Type;
82
+ /** One scripted `tool_use` block; its JSON input streams as these `input_json_delta` fragments. */
83
+ declare const MessagesScriptedToolUse: Schema.Struct<{
84
+ readonly name: Schema.NonEmptyString;
85
+ readonly inputFragments: Schema.$Array<Schema.String>;
86
+ readonly id: Schema.optionalKey<Schema.NonEmptyString>;
87
+ }>;
88
+ type MessagesScriptedToolUse = typeof MessagesScriptedToolUse.Type;
89
+ /**
90
+ * A scripted message. Every field is exact (nothing is filled in) except: a block is sent only
91
+ * when its field is present; `usage` omitted is synthesized and `null` drops `usage` from the
92
+ * wire; `stopReason` omitted is `tool_use` with tool uses, else `end_turn`; `order` defaults to
93
+ * `thinking-first` (`text-first` sends the thinking block after the text).
94
+ */
95
+ declare const MessagesScriptedMessage: Schema.Struct<{
96
+ readonly thinking: Schema.optionalKey<Schema.$Array<Schema.String>>;
97
+ readonly text: Schema.optionalKey<Schema.$Array<Schema.String>>;
98
+ readonly toolUses: Schema.optionalKey<Schema.$Array<Schema.Struct<{
99
+ readonly name: Schema.NonEmptyString;
100
+ readonly inputFragments: Schema.$Array<Schema.String>;
101
+ readonly id: Schema.optionalKey<Schema.NonEmptyString>;
102
+ }>>>;
103
+ readonly order: Schema.optionalKey<Schema.Literals<readonly ["thinking-first", "text-first"]>>;
104
+ readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
105
+ readonly inputTokens: Schema.Int;
106
+ readonly outputTokens: Schema.Int;
107
+ }>>>;
108
+ readonly stopReason: Schema.optionalKey<Schema.NonEmptyString>;
109
+ }>;
110
+ type MessagesScriptedMessage = typeof MessagesScriptedMessage.Type;
111
+ /** A turn queued for the next Messages request. */
112
+ declare const MessagesScriptedTurn: Schema.Union<readonly [Schema.Struct<{
113
+ readonly error: Schema.Struct<{
114
+ readonly status: Schema.Int;
115
+ readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
116
+ readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
117
+ }>;
118
+ }>, Schema.Struct<{
119
+ readonly thinking: Schema.optionalKey<Schema.$Array<Schema.String>>;
120
+ readonly text: Schema.optionalKey<Schema.$Array<Schema.String>>;
121
+ readonly toolUses: Schema.optionalKey<Schema.$Array<Schema.Struct<{
122
+ readonly name: Schema.NonEmptyString;
123
+ readonly inputFragments: Schema.$Array<Schema.String>;
124
+ readonly id: Schema.optionalKey<Schema.NonEmptyString>;
125
+ }>>>;
126
+ readonly order: Schema.optionalKey<Schema.Literals<readonly ["thinking-first", "text-first"]>>;
127
+ readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
128
+ readonly inputTokens: Schema.Int;
129
+ readonly outputTokens: Schema.Int;
130
+ }>>>;
131
+ readonly stopReason: Schema.optionalKey<Schema.NonEmptyString>;
132
+ }>]>;
133
+ type MessagesScriptedTurn = typeof MessagesScriptedTurn.Type;
134
+ type MessagesLedgerEntry = {
135
+ /** 1-based arrival order since the last ledger clear or reset. */readonly seq: number;
136
+ readonly method: string;
137
+ readonly path: string; /** Parsed JSON request body, when it was valid JSON. */
138
+ readonly body?: Schema.Json;
139
+ readonly model?: string;
140
+ readonly stream?: boolean; /** The request's `max_tokens`, when it is a number (non-positive or fractional answers 400). */
141
+ readonly maxTokens?: number;
142
+ readonly thinking?: Schema.Json;
143
+ readonly toolChoice?: Schema.Json;
144
+ readonly toolNames: ReadonlyArray<string>; /** Which header carried the credential (the value is never recorded). */
145
+ readonly credentialHeader?: 'x-api-key' | 'authorization';
146
+ readonly anthropicVersion?: string;
147
+ readonly anthropicBeta?: string; /** Kind of the fault that shaped the response. */
148
+ readonly fault?: MessagesFaultKind; /** Why a matching fault could not take effect (the response was a 500 emulator error). */
149
+ readonly faultError?: string;
150
+ /**
151
+ * Set when the emulator could not build the planned response; the request was answered with a
152
+ * 500 emulator error (still evidence-tagged) and no fault was used up.
153
+ */
154
+ readonly responseError?: string; /** Set when a scripted turn answered the request. */
155
+ readonly scripted?: 'message' | 'error'; /** Evidence of the matched route; `unknown-route` for requests that failed closed. */
156
+ readonly evidence: EmulatorEvidence | 'unknown-route';
157
+ readonly status: number; /** Body chunks handed to the transport so far (each produced when pulled). */
158
+ readonly bodyChunks: number;
159
+ };
160
+ type MessagesEmulator = EmulatorApi<MessagesScriptedTurn, MessagesFault, MessagesLedgerEntry>;
161
+ type MessagesEmulatorConfig = {
162
+ /** The Messages path, for example `/v1/messages`. */readonly path: string; /** Route evidence manifest; must list exactly the Messages route. */
163
+ readonly routes: ReadonlyArray<EmulatorRouteEvidence>;
164
+ readonly knownModels: ReadonlyArray<string>; /** Builds the error thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input. */
165
+ readonly inputInvalid: (input: 'fault' | 'turn', reason: string) => Error;
166
+ };
167
+ /** The Anthropic error envelope. */
168
+ declare const messagesErrorEnvelope: (error: MessagesWireError) => Schema.JsonObject;
169
+ /**
170
+ * Create a Messages emulator from its config. Each call has independent ledger, fault, and
171
+ * script state.
172
+ *
173
+ * Precedence per request: authentication, a supported `anthropic-version`, JSON and request
174
+ * validation (including a positive integer `max_tokens`, and no `thinking` with a forced
175
+ * `tool_choice`), then the first matching fault if it is a `status` fault, then the next
176
+ * scripted turn, then model validation and defaults; a first matching body fault then shapes the
177
+ * body. Only the first matching fault (in insertion order) applies. Credential headers are never
178
+ * recorded, and credential values are never checked or stored.
179
+ */
180
+ declare const makeMessagesEmulator: (config: MessagesEmulatorConfig) => MessagesEmulator;
181
+ //#endregion
182
+ export { MessagesEmulator, MessagesEmulatorConfig, MessagesErrorEventFault, MessagesFault, MessagesFaultKind, MessagesLedgerEntry, MessagesScriptedMessage, MessagesScriptedToolUse, MessagesScriptedTurn, MessagesScriptedUsage, MessagesWireError, makeMessagesEmulator, messagesErrorEnvelope };
183
+ //# sourceMappingURL=messages.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.mts","names":[],"sources":["../src/messages.ts"],"mappings":";;;;;;cAyDa,iBAAA,EAAiB,MAAA,CAAA,MAAA;EAAA;;;KAKlB,iBAAA,UAA2B,iBAAA,CAAkB,IAAI;;;;;cAMhD,uBAAA,EAAuB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;AANyB;AAM7D;;;;cAaa,aAAA,EAAa,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOd,aAAA,UAAuB,aAAA,CAAc,IAAI;AAAA,KAEzC,iBAAA,GAAoB,aAAa;;cAKhC,qBAAA,EAAqB,MAAA,CAAA,MAAA;EAAA;;;KAKtB,qBAAA,UAA+B,qBAAA,CAAsB,IAAI;;cAGxD,uBAAA,EAAuB,MAAA,CAAA,MAAA;EAAA;;;;KAMxB,uBAAA,UAAiC,uBAAA,CAAwB,IAAI;;;;AA5BzE;;;cAoCa,uBAAA,EAAuB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;KASxB,uBAAA,UAAiC,uBAAA,CAAwB,IAAI;;cAG5D,oBAAA,EAAoB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;KAErB,oBAAA,UAA8B,oBAAA,CAAqB,IAAI;AAAA,KAEvD,mBAAA;6EAED,GAAA;EAAA,SACA,MAAA;EAAA,SACA,IAAA;WAEA,IAAA,GAAO,MAAA,CAAO,IAAA;EAAA,SACd,KAAA;EAAA,SACA,MAAA;WAEA,SAAA;EAAA,SACA,QAAA,GAAW,MAAA,CAAO,IAAA;EAAA,SAClB,UAAA,GAAa,MAAA,CAAO,IAAA;EAAA,SACpB,SAAA,EAAW,aAAA;WAEX,gBAAA;EAAA,SACA,gBAAA;EAAA,SACA,aAAA,WArEe;EAAA,SAuEf,KAAA,GAAQ,iBAAA,EAvEO;EAAA,SAyEf,UAAA;EAzEe;;;;EAAA,SA8Ef,aAAA;WAEA,QAAA;WAEA,QAAA,EAAU,gBAAA;EAAA,SACV,MAAA;WAEA,UAAA;AAAA;AAAA,KAGC,gBAAA,GAAmB,WAAA,CAAY,oBAAA,EAAsB,aAAA,EAAe,mBAAA;AAAA,KAEpE,sBAAA;gEAED,IAAA;WAEA,MAAA,EAAQ,aAAA,CAAc,qBAAA;EAAA,SACtB,WAAA,EAAa,aAAA;WAEb,YAAA,GAAe,KAAA,oBAAyB,MAAA,aAAmB,KAAA;AAAA;;cA2XzD,qBAAA,GAAyB,KAAA,EAAO,iBAAA,KAAoB,MAAA,CAAO,UAGtE;;;;;;;;;;;;cAkFW,oBAAA,GAAwB,MAAA,EAAQ,sBAAA,KAAyB,gBAyMrE"}