@roj-ai/sdk 0.1.1 → 0.1.4

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 (493) hide show
  1. package/dist/bootstrap.js +191 -0
  2. package/dist/bootstrap.js.map +1 -0
  3. package/dist/builtin-events.js +8 -0
  4. package/dist/builtin-events.js.map +1 -0
  5. package/dist/bun-platform/fs.js +39 -0
  6. package/dist/bun-platform/fs.js.map +1 -0
  7. package/dist/bun-platform/index.js +18 -0
  8. package/dist/bun-platform/index.js.map +1 -0
  9. package/dist/bun-platform/process.js +21 -0
  10. package/dist/bun-platform/process.js.map +1 -0
  11. package/dist/config.js +54 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/config.test.js +155 -0
  14. package/dist/config.test.js.map +1 -0
  15. package/dist/core/agent-loop.integration.test.js +414 -0
  16. package/dist/core/agent-loop.integration.test.js.map +1 -0
  17. package/dist/core/agents/agent-config.test.js +194 -0
  18. package/dist/core/agents/agent-config.test.js.map +1 -0
  19. package/dist/core/agents/agent-roles.js +25 -0
  20. package/dist/core/agents/agent-roles.js.map +1 -0
  21. package/dist/core/agents/agent-shutdown.test.js +180 -0
  22. package/dist/core/agents/agent-shutdown.test.js.map +1 -0
  23. package/dist/core/agents/agent.js +1205 -0
  24. package/dist/core/agents/agent.js.map +1 -0
  25. package/dist/core/agents/agent.test.js +313 -0
  26. package/dist/core/agents/agent.test.js.map +1 -0
  27. package/dist/core/agents/communicator.js +13 -0
  28. package/dist/core/agents/communicator.js.map +1 -0
  29. package/dist/core/agents/config.js +5 -0
  30. package/dist/core/agents/config.js.map +1 -0
  31. package/dist/core/agents/context.js +2 -0
  32. package/dist/core/agents/context.js.map +1 -0
  33. package/dist/core/agents/debounce.js +74 -0
  34. package/dist/core/agents/debounce.js.map +1 -0
  35. package/dist/core/agents/handler-events.test.js +115 -0
  36. package/dist/core/agents/handler-events.test.js.map +1 -0
  37. package/dist/core/agents/index.js +2 -0
  38. package/dist/core/agents/index.js.map +1 -0
  39. package/dist/core/agents/response-sanitizer.js +46 -0
  40. package/dist/core/agents/response-sanitizer.js.map +1 -0
  41. package/dist/core/agents/response-sanitizer.test.js +101 -0
  42. package/dist/core/agents/response-sanitizer.test.js.map +1 -0
  43. package/dist/core/agents/retry.js +105 -0
  44. package/dist/core/agents/retry.js.map +1 -0
  45. package/dist/core/agents/schema.js +39 -0
  46. package/dist/core/agents/schema.js.map +1 -0
  47. package/dist/core/agents/state.js +90 -0
  48. package/dist/core/agents/state.js.map +1 -0
  49. package/dist/core/context/state.js +23 -0
  50. package/dist/core/context/state.js.map +1 -0
  51. package/dist/core/errors.js +38 -0
  52. package/dist/core/errors.js.map +1 -0
  53. package/dist/core/event-sourcing.integration.test.js +154 -0
  54. package/dist/core/event-sourcing.integration.test.js.map +1 -0
  55. package/dist/core/events/base-event-store.js +201 -0
  56. package/dist/core/events/base-event-store.js.map +1 -0
  57. package/dist/core/events/event-store.js +26 -0
  58. package/dist/core/events/event-store.js.map +1 -0
  59. package/dist/core/events/file.js +320 -0
  60. package/dist/core/events/file.js.map +1 -0
  61. package/dist/core/events/file.test.js +284 -0
  62. package/dist/core/events/file.test.js.map +1 -0
  63. package/dist/core/events/index.js +3 -0
  64. package/dist/core/events/index.js.map +1 -0
  65. package/dist/core/events/memory.js +101 -0
  66. package/dist/core/events/memory.js.map +1 -0
  67. package/dist/core/events/memory.test.js +502 -0
  68. package/dist/core/events/memory.test.js.map +1 -0
  69. package/dist/core/events/metadata-utils.js +107 -0
  70. package/dist/core/events/metadata-utils.js.map +1 -0
  71. package/dist/core/events/test-helpers.js +15 -0
  72. package/dist/core/events/test-helpers.js.map +1 -0
  73. package/dist/core/events/types.js +21 -0
  74. package/dist/core/events/types.js.map +1 -0
  75. package/dist/core/file-store/file-store.js +250 -0
  76. package/dist/core/file-store/file-store.js.map +1 -0
  77. package/dist/core/file-store/types.js +7 -0
  78. package/dist/core/file-store/types.js.map +1 -0
  79. package/dist/core/image/image-processor.js +106 -0
  80. package/dist/core/image/image-processor.js.map +1 -0
  81. package/dist/core/image/image-processor.test.js +171 -0
  82. package/dist/core/image/image-processor.test.js.map +1 -0
  83. package/dist/core/image/index.js +4 -0
  84. package/dist/core/image/index.js.map +1 -0
  85. package/dist/core/image/noop-resizer.js +6 -0
  86. package/dist/core/image/noop-resizer.js.map +1 -0
  87. package/dist/core/image/types.js +2 -0
  88. package/dist/core/image/types.js.map +1 -0
  89. package/dist/core/image/vips-resizer.js +100 -0
  90. package/dist/core/image/vips-resizer.js.map +1 -0
  91. package/dist/core/image/vips-resizer.test.js +324 -0
  92. package/dist/core/image/vips-resizer.test.js.map +1 -0
  93. package/dist/core/llm/anthropic.js +396 -0
  94. package/dist/core/llm/anthropic.js.map +1 -0
  95. package/dist/core/llm/anthropic.test.js +434 -0
  96. package/dist/core/llm/anthropic.test.js.map +1 -0
  97. package/dist/core/llm/cache-breakpoints.js +37 -0
  98. package/dist/core/llm/cache-breakpoints.js.map +1 -0
  99. package/dist/core/llm/cache-live.test.js +137 -0
  100. package/dist/core/llm/cache-live.test.js.map +1 -0
  101. package/dist/core/llm/index.js +9 -0
  102. package/dist/core/llm/index.js.map +1 -0
  103. package/dist/core/llm/llm-log-types.js +12 -0
  104. package/dist/core/llm/llm-log-types.js.map +1 -0
  105. package/dist/core/llm/logger.js +241 -0
  106. package/dist/core/llm/logger.js.map +1 -0
  107. package/dist/core/llm/logger.test.js +228 -0
  108. package/dist/core/llm/logger.test.js.map +1 -0
  109. package/dist/core/llm/logging-provider.js +49 -0
  110. package/dist/core/llm/logging-provider.js.map +1 -0
  111. package/dist/core/llm/middleware.js +114 -0
  112. package/dist/core/llm/middleware.js.map +1 -0
  113. package/dist/core/llm/mock.js +186 -0
  114. package/dist/core/llm/mock.js.map +1 -0
  115. package/dist/core/llm/mock.test.js +318 -0
  116. package/dist/core/llm/mock.test.js.map +1 -0
  117. package/dist/core/llm/openrouter-mapping.test.js +125 -0
  118. package/dist/core/llm/openrouter-mapping.test.js.map +1 -0
  119. package/dist/core/llm/openrouter.js +298 -0
  120. package/dist/core/llm/openrouter.js.map +1 -0
  121. package/dist/core/llm/openrouter.test.js +377 -0
  122. package/dist/core/llm/openrouter.test.js.map +1 -0
  123. package/dist/core/llm/provider-integration.test.js +350 -0
  124. package/dist/core/llm/provider-integration.test.js.map +1 -0
  125. package/dist/core/llm/provider.js +18 -0
  126. package/dist/core/llm/provider.js.map +1 -0
  127. package/dist/core/llm/routing-provider.js +52 -0
  128. package/dist/core/llm/routing-provider.js.map +1 -0
  129. package/dist/core/llm/routing-provider.test.js +94 -0
  130. package/dist/core/llm/routing-provider.test.js.map +1 -0
  131. package/dist/core/llm/schema.js +31 -0
  132. package/dist/core/llm/schema.js.map +1 -0
  133. package/dist/core/llm/snapshot-fetch.js +122 -0
  134. package/dist/core/llm/snapshot-fetch.js.map +1 -0
  135. package/dist/core/llm/snapshot-middleware.js +142 -0
  136. package/dist/core/llm/snapshot-middleware.js.map +1 -0
  137. package/dist/core/llm/snapshot-middleware.test.js +144 -0
  138. package/dist/core/llm/snapshot-middleware.test.js.map +1 -0
  139. package/dist/core/llm/state.js +48 -0
  140. package/dist/core/llm/state.js.map +1 -0
  141. package/dist/core/llm/tokens.js +40 -0
  142. package/dist/core/llm/tokens.js.map +1 -0
  143. package/dist/core/multi-agent.integration.test.js +298 -0
  144. package/dist/core/multi-agent.integration.test.js.map +1 -0
  145. package/dist/core/plugin-hooks.integration.test.js +344 -0
  146. package/dist/core/plugin-hooks.integration.test.js.map +1 -0
  147. package/dist/core/plugins/hook-types.js +5 -0
  148. package/dist/core/plugins/hook-types.js.map +1 -0
  149. package/dist/core/plugins/index.js +5 -0
  150. package/dist/core/plugins/index.js.map +1 -0
  151. package/dist/core/plugins/plugin-builder.js +321 -0
  152. package/dist/core/plugins/plugin-builder.js.map +1 -0
  153. package/dist/core/preset/config.js +54 -0
  154. package/dist/core/preset/config.js.map +1 -0
  155. package/dist/core/preset/index.js +6 -0
  156. package/dist/core/preset/index.js.map +1 -0
  157. package/dist/core/preset/preset-builder.js +63 -0
  158. package/dist/core/preset/preset-builder.js.map +1 -0
  159. package/dist/core/session-lifecycle.integration.test.js +159 -0
  160. package/dist/core/session-lifecycle.integration.test.js.map +1 -0
  161. package/dist/core/sessions/apply-event.js +41 -0
  162. package/dist/core/sessions/apply-event.js.map +1 -0
  163. package/dist/core/sessions/context.js +2 -0
  164. package/dist/core/sessions/context.js.map +1 -0
  165. package/dist/core/sessions/fork-utils.js +42 -0
  166. package/dist/core/sessions/fork-utils.js.map +1 -0
  167. package/dist/core/sessions/fork-utils.test.js +129 -0
  168. package/dist/core/sessions/fork-utils.test.js.map +1 -0
  169. package/dist/core/sessions/reducer.js +55 -0
  170. package/dist/core/sessions/reducer.js.map +1 -0
  171. package/dist/core/sessions/schema.js +66 -0
  172. package/dist/core/sessions/schema.js.map +1 -0
  173. package/dist/core/sessions/session-environment.js +2 -0
  174. package/dist/core/sessions/session-environment.js.map +1 -0
  175. package/dist/core/sessions/session-manager.js +650 -0
  176. package/dist/core/sessions/session-manager.js.map +1 -0
  177. package/dist/core/sessions/session-store.js +118 -0
  178. package/dist/core/sessions/session-store.js.map +1 -0
  179. package/dist/core/sessions/session.js +675 -0
  180. package/dist/core/sessions/session.js.map +1 -0
  181. package/dist/core/sessions/session.test.js +1095 -0
  182. package/dist/core/sessions/session.test.js.map +1 -0
  183. package/dist/core/sessions/state.js +377 -0
  184. package/dist/core/sessions/state.js.map +1 -0
  185. package/dist/core/system.js +66 -0
  186. package/dist/core/system.js.map +1 -0
  187. package/dist/core/tools/context.js +2 -0
  188. package/dist/core/tools/context.js.map +1 -0
  189. package/dist/core/tools/definition.js +4 -0
  190. package/dist/core/tools/definition.js.map +1 -0
  191. package/dist/core/tools/executor.js +82 -0
  192. package/dist/core/tools/executor.js.map +1 -0
  193. package/dist/core/tools/executor.test.js +143 -0
  194. package/dist/core/tools/executor.test.js.map +1 -0
  195. package/dist/core/tools/index.js +4 -0
  196. package/dist/core/tools/index.js.map +1 -0
  197. package/dist/core/tools/schema.js +20 -0
  198. package/dist/core/tools/schema.js.map +1 -0
  199. package/dist/core/tools/state.js +29 -0
  200. package/dist/core/tools/state.js.map +1 -0
  201. package/dist/index.js +70 -0
  202. package/dist/index.js.map +1 -0
  203. package/dist/lib/json/index.js +5 -0
  204. package/dist/lib/json/index.js.map +1 -0
  205. package/dist/lib/logger/console.js +147 -0
  206. package/dist/lib/logger/console.js.map +1 -0
  207. package/dist/lib/logger/console.test.js +258 -0
  208. package/dist/lib/logger/console.test.js.map +1 -0
  209. package/dist/lib/logger/file.js +54 -0
  210. package/dist/lib/logger/file.js.map +1 -0
  211. package/dist/lib/logger/index.js +4 -0
  212. package/dist/lib/logger/index.js.map +1 -0
  213. package/dist/lib/logger/logger.js +28 -0
  214. package/dist/lib/logger/logger.js.map +1 -0
  215. package/dist/lib/logger/ring-buffer.js +61 -0
  216. package/dist/lib/logger/ring-buffer.js.map +1 -0
  217. package/dist/lib/logger/tee.js +43 -0
  218. package/dist/lib/logger/tee.js.map +1 -0
  219. package/dist/lib/mime.js +22 -0
  220. package/dist/lib/mime.js.map +1 -0
  221. package/dist/lib/never.js +4 -0
  222. package/dist/lib/never.js.map +1 -0
  223. package/dist/lib/utils/hash.js +35 -0
  224. package/dist/lib/utils/hash.js.map +1 -0
  225. package/dist/lib/utils/result.js +21 -0
  226. package/dist/lib/utils/result.js.map +1 -0
  227. package/dist/platform/fs.js +8 -0
  228. package/dist/platform/fs.js.map +1 -0
  229. package/dist/platform/index.js +9 -0
  230. package/dist/platform/index.js.map +1 -0
  231. package/dist/platform/process.js +8 -0
  232. package/dist/platform/process.js.map +1 -0
  233. package/dist/plugins/agent-status/plugin.js +77 -0
  234. package/dist/plugins/agent-status/plugin.js.map +1 -0
  235. package/dist/plugins/agents/agents.integration.test.js +683 -0
  236. package/dist/plugins/agents/agents.integration.test.js.map +1 -0
  237. package/dist/plugins/agents/index.js +2 -0
  238. package/dist/plugins/agents/index.js.map +1 -0
  239. package/dist/plugins/agents/plugin.js +199 -0
  240. package/dist/plugins/agents/plugin.js.map +1 -0
  241. package/dist/plugins/context-compact/context-compact.integration.test.js +174 -0
  242. package/dist/plugins/context-compact/context-compact.integration.test.js.map +1 -0
  243. package/dist/plugins/context-compact/context-compactor.js +238 -0
  244. package/dist/plugins/context-compact/context-compactor.js.map +1 -0
  245. package/dist/plugins/context-compact/context-compactor.test.js +763 -0
  246. package/dist/plugins/context-compact/context-compactor.test.js.map +1 -0
  247. package/dist/plugins/context-compact/history-offloader.js +42 -0
  248. package/dist/plugins/context-compact/history-offloader.js.map +1 -0
  249. package/dist/plugins/context-compact/history-offloader.test.js +77 -0
  250. package/dist/plugins/context-compact/history-offloader.test.js.map +1 -0
  251. package/dist/plugins/context-compact/index.js +4 -0
  252. package/dist/plugins/context-compact/index.js.map +1 -0
  253. package/dist/plugins/context-compact/plugin.js +37 -0
  254. package/dist/plugins/context-compact/plugin.js.map +1 -0
  255. package/dist/plugins/filesystem/filesystem.integration.test.js +411 -0
  256. package/dist/plugins/filesystem/filesystem.integration.test.js.map +1 -0
  257. package/dist/plugins/filesystem/helpers.js +170 -0
  258. package/dist/plugins/filesystem/helpers.js.map +1 -0
  259. package/dist/plugins/filesystem/index.js +3 -0
  260. package/dist/plugins/filesystem/index.js.map +1 -0
  261. package/dist/plugins/filesystem/listing.js +247 -0
  262. package/dist/plugins/filesystem/listing.js.map +1 -0
  263. package/dist/plugins/filesystem/plugin.js +364 -0
  264. package/dist/plugins/filesystem/plugin.js.map +1 -0
  265. package/dist/plugins/filesystem/schema.js +2 -0
  266. package/dist/plugins/filesystem/schema.js.map +1 -0
  267. package/dist/plugins/git-status/index.js +2 -0
  268. package/dist/plugins/git-status/index.js.map +1 -0
  269. package/dist/plugins/git-status/plugin.js +144 -0
  270. package/dist/plugins/git-status/plugin.js.map +1 -0
  271. package/dist/plugins/limits-guard/config.js +5 -0
  272. package/dist/plugins/limits-guard/config.js.map +1 -0
  273. package/dist/plugins/limits-guard/index.js +3 -0
  274. package/dist/plugins/limits-guard/index.js.map +1 -0
  275. package/dist/plugins/limits-guard/limit-guard.js +125 -0
  276. package/dist/plugins/limits-guard/limit-guard.js.map +1 -0
  277. package/dist/plugins/limits-guard/limit-guard.test.js +121 -0
  278. package/dist/plugins/limits-guard/limit-guard.test.js.map +1 -0
  279. package/dist/plugins/limits-guard/limits-guard.integration.test.js +378 -0
  280. package/dist/plugins/limits-guard/limits-guard.integration.test.js.map +1 -0
  281. package/dist/plugins/limits-guard/plugin.js +240 -0
  282. package/dist/plugins/limits-guard/plugin.js.map +1 -0
  283. package/dist/plugins/llm-debug/index.js +2 -0
  284. package/dist/plugins/llm-debug/index.js.map +1 -0
  285. package/dist/plugins/llm-debug/llm-debug.integration.test.js +157 -0
  286. package/dist/plugins/llm-debug/llm-debug.integration.test.js.map +1 -0
  287. package/dist/plugins/llm-debug/plugin.js +148 -0
  288. package/dist/plugins/llm-debug/plugin.js.map +1 -0
  289. package/dist/plugins/logs/index.js +2 -0
  290. package/dist/plugins/logs/index.js.map +1 -0
  291. package/dist/plugins/logs/plugin.js +38 -0
  292. package/dist/plugins/logs/plugin.js.map +1 -0
  293. package/dist/plugins/mailbox/helpers.js +66 -0
  294. package/dist/plugins/mailbox/helpers.js.map +1 -0
  295. package/dist/plugins/mailbox/index.js +9 -0
  296. package/dist/plugins/mailbox/index.js.map +1 -0
  297. package/dist/plugins/mailbox/mailbox.integration.test.js +605 -0
  298. package/dist/plugins/mailbox/mailbox.integration.test.js.map +1 -0
  299. package/dist/plugins/mailbox/plugin.js +204 -0
  300. package/dist/plugins/mailbox/plugin.js.map +1 -0
  301. package/dist/plugins/mailbox/prompts.js +93 -0
  302. package/dist/plugins/mailbox/prompts.js.map +1 -0
  303. package/dist/plugins/mailbox/query.js +38 -0
  304. package/dist/plugins/mailbox/query.js.map +1 -0
  305. package/dist/plugins/mailbox/schema.js +32 -0
  306. package/dist/plugins/mailbox/schema.js.map +1 -0
  307. package/dist/plugins/mailbox/state.js +41 -0
  308. package/dist/plugins/mailbox/state.js.map +1 -0
  309. package/dist/plugins/resources/index.js +4 -0
  310. package/dist/plugins/resources/index.js.map +1 -0
  311. package/dist/plugins/resources/manifest.js +20 -0
  312. package/dist/plugins/resources/manifest.js.map +1 -0
  313. package/dist/plugins/resources/plugin.js +171 -0
  314. package/dist/plugins/resources/plugin.js.map +1 -0
  315. package/dist/plugins/resources/post-inject.js +32 -0
  316. package/dist/plugins/resources/post-inject.js.map +1 -0
  317. package/dist/plugins/resources/state.js +16 -0
  318. package/dist/plugins/resources/state.js.map +1 -0
  319. package/dist/plugins/result-eviction/index.js +2 -0
  320. package/dist/plugins/result-eviction/index.js.map +1 -0
  321. package/dist/plugins/result-eviction/plugin.js +43 -0
  322. package/dist/plugins/result-eviction/plugin.js.map +1 -0
  323. package/dist/plugins/result-eviction/result-eviction.integration.test.js +217 -0
  324. package/dist/plugins/result-eviction/result-eviction.integration.test.js.map +1 -0
  325. package/dist/plugins/services/plugin.js +453 -0
  326. package/dist/plugins/services/plugin.js.map +1 -0
  327. package/dist/plugins/services/port-pool.js +70 -0
  328. package/dist/plugins/services/port-pool.js.map +1 -0
  329. package/dist/plugins/services/prompt.js +40 -0
  330. package/dist/plugins/services/prompt.js.map +1 -0
  331. package/dist/plugins/services/schema.js +9 -0
  332. package/dist/plugins/services/schema.js.map +1 -0
  333. package/dist/plugins/services/service.js +470 -0
  334. package/dist/plugins/services/service.js.map +1 -0
  335. package/dist/plugins/services/services.integration.test.js +485 -0
  336. package/dist/plugins/services/services.integration.test.js.map +1 -0
  337. package/dist/plugins/session-lifecycle/index.js +2 -0
  338. package/dist/plugins/session-lifecycle/index.js.map +1 -0
  339. package/dist/plugins/session-lifecycle/plugin.js +273 -0
  340. package/dist/plugins/session-lifecycle/plugin.js.map +1 -0
  341. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js +498 -0
  342. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js.map +1 -0
  343. package/dist/plugins/session-state/plugin.js +159 -0
  344. package/dist/plugins/session-state/plugin.js.map +1 -0
  345. package/dist/plugins/session-stats/index.js +3 -0
  346. package/dist/plugins/session-stats/index.js.map +1 -0
  347. package/dist/plugins/session-stats/plugin.js +81 -0
  348. package/dist/plugins/session-stats/plugin.js.map +1 -0
  349. package/dist/plugins/shell/executor.js +339 -0
  350. package/dist/plugins/shell/executor.js.map +1 -0
  351. package/dist/plugins/shell/index.js +6 -0
  352. package/dist/plugins/shell/index.js.map +1 -0
  353. package/dist/plugins/shell/plugin.js +66 -0
  354. package/dist/plugins/shell/plugin.js.map +1 -0
  355. package/dist/plugins/shell/shell.integration.test.js +234 -0
  356. package/dist/plugins/shell/shell.integration.test.js.map +1 -0
  357. package/dist/plugins/shell/shell.test.js +236 -0
  358. package/dist/plugins/shell/shell.test.js.map +1 -0
  359. package/dist/plugins/skills/discovery.js +205 -0
  360. package/dist/plugins/skills/discovery.js.map +1 -0
  361. package/dist/plugins/skills/discovery.test.js +312 -0
  362. package/dist/plugins/skills/discovery.test.js.map +1 -0
  363. package/dist/plugins/skills/index.js +12 -0
  364. package/dist/plugins/skills/index.js.map +1 -0
  365. package/dist/plugins/skills/plugin.js +293 -0
  366. package/dist/plugins/skills/plugin.js.map +1 -0
  367. package/dist/plugins/skills/prompts.js +70 -0
  368. package/dist/plugins/skills/prompts.js.map +1 -0
  369. package/dist/plugins/skills/schema.js +18 -0
  370. package/dist/plugins/skills/schema.js.map +1 -0
  371. package/dist/plugins/skills/skills.integration.test.js +475 -0
  372. package/dist/plugins/skills/skills.integration.test.js.map +1 -0
  373. package/dist/plugins/snapshotting/index.js +3 -0
  374. package/dist/plugins/snapshotting/index.js.map +1 -0
  375. package/dist/plugins/snapshotting/jj-snapshotter.js +106 -0
  376. package/dist/plugins/snapshotting/jj-snapshotter.js.map +1 -0
  377. package/dist/plugins/snapshotting/plugin.js +28 -0
  378. package/dist/plugins/snapshotting/plugin.js.map +1 -0
  379. package/dist/plugins/snapshotting/snapshotter.js +2 -0
  380. package/dist/plugins/snapshotting/snapshotter.js.map +1 -0
  381. package/dist/plugins/todo/index.js +7 -0
  382. package/dist/plugins/todo/index.js.map +1 -0
  383. package/dist/plugins/todo/plugin.js +319 -0
  384. package/dist/plugins/todo/plugin.js.map +1 -0
  385. package/dist/plugins/todo/prompts.js +54 -0
  386. package/dist/plugins/todo/prompts.js.map +1 -0
  387. package/dist/plugins/todo/schema.js +18 -0
  388. package/dist/plugins/todo/schema.js.map +1 -0
  389. package/dist/plugins/todo/todo.integration.test.js +605 -0
  390. package/dist/plugins/todo/todo.integration.test.js.map +1 -0
  391. package/dist/plugins/uploads/index.js +8 -0
  392. package/dist/plugins/uploads/index.js.map +1 -0
  393. package/dist/plugins/uploads/plugin.js +346 -0
  394. package/dist/plugins/uploads/plugin.js.map +1 -0
  395. package/dist/plugins/uploads/preprocessor.js +44 -0
  396. package/dist/plugins/uploads/preprocessor.js.map +1 -0
  397. package/dist/plugins/uploads/preprocessors/image-classifier.js +127 -0
  398. package/dist/plugins/uploads/preprocessors/image-classifier.js.map +1 -0
  399. package/dist/plugins/uploads/preprocessors/index.js +7 -0
  400. package/dist/plugins/uploads/preprocessors/index.js.map +1 -0
  401. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js +204 -0
  402. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js.map +1 -0
  403. package/dist/plugins/uploads/preprocessors/zip-preprocessor.js +172 -0
  404. package/dist/plugins/uploads/preprocessors/zip-preprocessor.js.map +1 -0
  405. package/dist/plugins/uploads/schema.js +20 -0
  406. package/dist/plugins/uploads/schema.js.map +1 -0
  407. package/dist/plugins/uploads/state.js +22 -0
  408. package/dist/plugins/uploads/state.js.map +1 -0
  409. package/dist/plugins/uploads/uploads.integration.test.js +496 -0
  410. package/dist/plugins/uploads/uploads.integration.test.js.map +1 -0
  411. package/dist/plugins/user-chat/index.js +5 -0
  412. package/dist/plugins/user-chat/index.js.map +1 -0
  413. package/dist/plugins/user-chat/plugin.js +544 -0
  414. package/dist/plugins/user-chat/plugin.js.map +1 -0
  415. package/dist/plugins/user-chat/prompts.js +29 -0
  416. package/dist/plugins/user-chat/prompts.js.map +1 -0
  417. package/dist/plugins/user-chat/schema.js +46 -0
  418. package/dist/plugins/user-chat/schema.js.map +1 -0
  419. package/dist/plugins/user-chat/user-chat.integration.test.js +668 -0
  420. package/dist/plugins/user-chat/user-chat.integration.test.js.map +1 -0
  421. package/dist/plugins/workers/context.js +143 -0
  422. package/dist/plugins/workers/context.js.map +1 -0
  423. package/dist/plugins/workers/definition.js +30 -0
  424. package/dist/plugins/workers/definition.js.map +1 -0
  425. package/dist/plugins/workers/index.js +7 -0
  426. package/dist/plugins/workers/index.js.map +1 -0
  427. package/dist/plugins/workers/plugin.js +578 -0
  428. package/dist/plugins/workers/plugin.js.map +1 -0
  429. package/dist/plugins/workers/worker.js +18 -0
  430. package/dist/plugins/workers/worker.js.map +1 -0
  431. package/dist/plugins/workers/workers.integration.test.js +629 -0
  432. package/dist/plugins/workers/workers.integration.test.js.map +1 -0
  433. package/dist/prompts/base.js +239 -0
  434. package/dist/prompts/base.js.map +1 -0
  435. package/dist/prompts/builder.js +131 -0
  436. package/dist/prompts/builder.js.map +1 -0
  437. package/dist/prompts/index.js +20 -0
  438. package/dist/prompts/index.js.map +1 -0
  439. package/dist/prompts/macros.js +26 -0
  440. package/dist/prompts/macros.js.map +1 -0
  441. package/dist/prompts/macros.test.js +80 -0
  442. package/dist/prompts/macros.test.js.map +1 -0
  443. package/dist/testing/bootstrap-for-testing.js +28 -0
  444. package/dist/testing/bootstrap-for-testing.js.map +1 -0
  445. package/dist/testing/index.js +7 -0
  446. package/dist/testing/index.js.map +1 -0
  447. package/dist/testing/node-platform.js +65 -0
  448. package/dist/testing/node-platform.js.map +1 -0
  449. package/dist/testing/notification-collector.js +82 -0
  450. package/dist/testing/notification-collector.js.map +1 -0
  451. package/dist/testing/preset-helpers.js +37 -0
  452. package/dist/testing/preset-helpers.js.map +1 -0
  453. package/dist/testing/test-harness.js +226 -0
  454. package/dist/testing/test-harness.js.map +1 -0
  455. package/dist/testing/test-harness.test.js +51 -0
  456. package/dist/testing/test-harness.test.js.map +1 -0
  457. package/dist/testing/wait-helpers.js +64 -0
  458. package/dist/testing/wait-helpers.js.map +1 -0
  459. package/dist/transport/adapter/client-adapter.js +64 -0
  460. package/dist/transport/adapter/client-adapter.js.map +1 -0
  461. package/dist/transport/adapter/index.js +24 -0
  462. package/dist/transport/adapter/index.js.map +1 -0
  463. package/dist/transport/adapter/server-adapter.js +73 -0
  464. package/dist/transport/adapter/server-adapter.js.map +1 -0
  465. package/dist/transport/adapter/types.js +8 -0
  466. package/dist/transport/adapter/types.js.map +1 -0
  467. package/dist/transport/http/app.js +86 -0
  468. package/dist/transport/http/app.js.map +1 -0
  469. package/dist/transport/http/index.js +6 -0
  470. package/dist/transport/http/index.js.map +1 -0
  471. package/dist/transport/http/middleware/bearer-auth.js +33 -0
  472. package/dist/transport/http/middleware/bearer-auth.js.map +1 -0
  473. package/dist/transport/http/middleware/error-handler.js +56 -0
  474. package/dist/transport/http/middleware/error-handler.js.map +1 -0
  475. package/dist/transport/http/routes/files.js +237 -0
  476. package/dist/transport/http/routes/files.js.map +1 -0
  477. package/dist/transport/http/routes/resources.js +77 -0
  478. package/dist/transport/http/routes/resources.js.map +1 -0
  479. package/dist/transport/http/routes/rpc.integration.test.js +189 -0
  480. package/dist/transport/http/routes/rpc.integration.test.js.map +1 -0
  481. package/dist/transport/http/routes/rpc.js +110 -0
  482. package/dist/transport/http/routes/rpc.js.map +1 -0
  483. package/dist/transport/http/routes/rpc.test.js +316 -0
  484. package/dist/transport/http/routes/rpc.test.js.map +1 -0
  485. package/dist/transport/http/routes/upload.js +205 -0
  486. package/dist/transport/http/routes/upload.js.map +1 -0
  487. package/dist/transport/rpc/index.js +7 -0
  488. package/dist/transport/rpc/index.js.map +1 -0
  489. package/dist/transport/rpc/methods.js +8 -0
  490. package/dist/transport/rpc/methods.js.map +1 -0
  491. package/dist/user-config.js +14 -0
  492. package/dist/user-config.js.map +1 -0
  493. package/package.json +47 -57
@@ -0,0 +1,434 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { ModelId } from '../../core/llm/schema.js';
3
+ import { ToolCallId } from '../../core/tools/schema.js';
4
+ import { AnthropicProvider } from './anthropic.js';
5
+ import { applyCacheBreakpoint } from './cache-breakpoints.js';
6
+ // ============================================================================
7
+ // Helpers — access private methods via prototype for testing
8
+ // ============================================================================
9
+ const createProvider = () => new AnthropicProvider({
10
+ apiKey: 'test-key',
11
+ imageProcessor: {
12
+ resolveContent: async (content) => content,
13
+ },
14
+ });
15
+ // Access private methods for unit testing the mapping logic
16
+ const provider = createProvider();
17
+ const mapMessage = provider.mapMessage.bind(provider);
18
+ const mergeConsecutiveMessages = provider.mergeConsecutiveMessages.bind(provider);
19
+ const mapStopReason = provider.mapStopReason.bind(provider);
20
+ const mapError = provider.mapError.bind(provider);
21
+ // ============================================================================
22
+ // Message Mapping
23
+ // ============================================================================
24
+ describe('AnthropicProvider message mapping', () => {
25
+ test('maps user message with string content', async () => {
26
+ const result = await mapMessage({ role: 'user', content: 'Hello' });
27
+ expect(result).toEqual({ role: 'user', content: 'Hello' });
28
+ });
29
+ test('maps user message with multimodal content', async () => {
30
+ const result = await mapMessage({
31
+ role: 'user',
32
+ content: [
33
+ { type: 'text', text: 'Look at this image' },
34
+ { type: 'image_url', imageUrl: { url: 'data:image/png;base64,abc123' } },
35
+ ],
36
+ });
37
+ expect(result).toEqual({
38
+ role: 'user',
39
+ content: [
40
+ { type: 'text', text: 'Look at this image' },
41
+ { type: 'image', source: { type: 'base64', media_type: 'image/png', data: 'abc123' } },
42
+ ],
43
+ });
44
+ });
45
+ test('maps user message with HTTP image URL', async () => {
46
+ const result = await mapMessage({
47
+ role: 'user',
48
+ content: [
49
+ { type: 'image_url', imageUrl: { url: 'https://example.com/img.jpg' } },
50
+ ],
51
+ });
52
+ expect(result).toEqual({
53
+ role: 'user',
54
+ content: [
55
+ { type: 'image', source: { type: 'url', url: 'https://example.com/img.jpg' } },
56
+ ],
57
+ });
58
+ });
59
+ test('maps assistant message with content only', async () => {
60
+ const result = await mapMessage({ role: 'assistant', content: 'Hello back' });
61
+ expect(result).toEqual({
62
+ role: 'assistant',
63
+ content: [{ type: 'text', text: 'Hello back' }],
64
+ });
65
+ });
66
+ test('maps assistant message with tool calls', async () => {
67
+ const result = await mapMessage({
68
+ role: 'assistant',
69
+ content: 'Let me help',
70
+ toolCalls: [{ id: ToolCallId('tc_1'), name: 'search', input: { query: 'test' } }],
71
+ });
72
+ expect(result).toEqual({
73
+ role: 'assistant',
74
+ content: [
75
+ { type: 'text', text: 'Let me help' },
76
+ { type: 'tool_use', id: 'tc_1', name: 'search', input: { query: 'test' } },
77
+ ],
78
+ });
79
+ });
80
+ test('maps assistant message with empty content and tool calls', async () => {
81
+ const result = await mapMessage({
82
+ role: 'assistant',
83
+ content: '',
84
+ toolCalls: [{ id: ToolCallId('tc_1'), name: 'search', input: { query: 'test' } }],
85
+ });
86
+ expect(result).toEqual({
87
+ role: 'assistant',
88
+ content: [
89
+ { type: 'tool_use', id: 'tc_1', name: 'search', input: { query: 'test' } },
90
+ ],
91
+ });
92
+ });
93
+ test('maps tool result to user role with tool_result block', async () => {
94
+ const result = await mapMessage({
95
+ role: 'tool',
96
+ content: 'result data',
97
+ toolCallId: ToolCallId('tc_1'),
98
+ });
99
+ expect(result).toEqual({
100
+ role: 'user',
101
+ content: [{ type: 'tool_result', tool_use_id: 'tc_1', content: 'result data' }],
102
+ });
103
+ });
104
+ test('maps tool error result with ERROR prefix', async () => {
105
+ const result = await mapMessage({
106
+ role: 'tool',
107
+ content: 'something failed',
108
+ toolCallId: ToolCallId('tc_1'),
109
+ isError: true,
110
+ });
111
+ expect(result).toEqual({
112
+ role: 'user',
113
+ content: [{ type: 'tool_result', tool_use_id: 'tc_1', content: '[ERROR] something failed' }],
114
+ });
115
+ });
116
+ test('maps system message to user with [System] prefix', async () => {
117
+ const result = await mapMessage({ role: 'system', content: 'Context information' });
118
+ expect(result).toEqual({
119
+ role: 'user',
120
+ content: [{ type: 'text', text: '[System] Context information' }],
121
+ });
122
+ });
123
+ });
124
+ // ============================================================================
125
+ // Message Alternation
126
+ // ============================================================================
127
+ describe('AnthropicProvider message alternation', () => {
128
+ test('merges consecutive user messages', () => {
129
+ const messages = [
130
+ { role: 'user', content: 'Hello' },
131
+ { role: 'user', content: 'How are you?' },
132
+ ];
133
+ const result = mergeConsecutiveMessages(messages);
134
+ expect(result).toEqual([{
135
+ role: 'user',
136
+ content: [
137
+ { type: 'text', text: 'Hello' },
138
+ { type: 'text', text: 'How are you?' },
139
+ ],
140
+ }]);
141
+ });
142
+ test('merges consecutive user messages with mixed content types', () => {
143
+ const messages = [
144
+ { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'tc_1', content: 'result1' }] },
145
+ { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'tc_2', content: 'result2' }] },
146
+ ];
147
+ const result = mergeConsecutiveMessages(messages);
148
+ expect(result).toHaveLength(1);
149
+ expect(result[0].role).toBe('user');
150
+ expect(Array.isArray(result[0].content)).toBe(true);
151
+ expect(result[0].content.length).toBe(2);
152
+ });
153
+ test('does not merge messages with different roles', () => {
154
+ const messages = [
155
+ { role: 'user', content: 'Hello' },
156
+ { role: 'assistant', content: 'Hi' },
157
+ { role: 'user', content: 'How are you?' },
158
+ ];
159
+ const result = mergeConsecutiveMessages(messages);
160
+ expect(result).toHaveLength(3);
161
+ });
162
+ test('handles empty input', () => {
163
+ expect(mergeConsecutiveMessages([])).toEqual([]);
164
+ });
165
+ });
166
+ // ============================================================================
167
+ // Cache Breakpoints
168
+ // ============================================================================
169
+ describe('applyCacheBreakpoint (shared helper)', () => {
170
+ test('marks the last message when uncachedSuffixCount is 0', () => {
171
+ const messages = [
172
+ { role: 'user', content: 'Hello' },
173
+ { role: 'assistant', content: 'Hi' },
174
+ { role: 'user', content: 'Question' },
175
+ ];
176
+ const result = applyCacheBreakpoint(messages, 0);
177
+ expect(result[2].cacheControl).toEqual({ type: 'ephemeral' });
178
+ expect(result[0].cacheControl).toBeUndefined();
179
+ expect(result[1].cacheControl).toBeUndefined();
180
+ });
181
+ test('marks second-to-last when uncachedSuffixCount is 1', () => {
182
+ const messages = [
183
+ { role: 'user', content: 'Hello' },
184
+ { role: 'assistant', content: 'Hi' },
185
+ { role: 'user', content: 'Question' },
186
+ ];
187
+ const result = applyCacheBreakpoint(messages, 1);
188
+ expect(result[1].cacheControl).toEqual({ type: 'ephemeral' });
189
+ expect(result[2].cacheControl).toBeUndefined();
190
+ });
191
+ test('no-op when suffix exceeds message count', () => {
192
+ const messages = [{ role: 'user', content: 'Hello' }];
193
+ const result = applyCacheBreakpoint(messages, 5);
194
+ expect(result[0].cacheControl).toBeUndefined();
195
+ });
196
+ });
197
+ describe('AnthropicProvider cache breakpoint placement', () => {
198
+ test('adds cache_control to last block of flagged user string message', async () => {
199
+ const result = await mapMessage({
200
+ role: 'user',
201
+ content: 'Hello',
202
+ cacheControl: { type: 'ephemeral' },
203
+ });
204
+ expect(Array.isArray(result.content)).toBe(true);
205
+ const content = result.content;
206
+ expect(content[content.length - 1].cache_control).toEqual({ type: 'ephemeral' });
207
+ });
208
+ test('adds cache_control to outer tool_result block (not inner content)', async () => {
209
+ const result = await mapMessage({
210
+ role: 'tool',
211
+ content: 'result data',
212
+ toolCallId: ToolCallId('tc_1'),
213
+ cacheControl: { type: 'ephemeral' },
214
+ });
215
+ const content = result.content;
216
+ expect(content).toHaveLength(1);
217
+ expect(content[0].type).toBe('tool_result');
218
+ expect(content[0].cache_control).toEqual({ type: 'ephemeral' });
219
+ });
220
+ test('adds cache_control to last block of assistant with text + tool_use', async () => {
221
+ const result = await mapMessage({
222
+ role: 'assistant',
223
+ content: 'Let me help',
224
+ toolCalls: [{ id: ToolCallId('tc_1'), name: 'search', input: { query: 'test' } }],
225
+ cacheControl: { type: 'ephemeral' },
226
+ });
227
+ const content = result.content;
228
+ // Last block is the tool_use — that's where cache_control must land
229
+ expect(content[content.length - 1].type).toBe('tool_use');
230
+ expect(content[content.length - 1].cache_control).toEqual({ type: 'ephemeral' });
231
+ });
232
+ test('no cache_control on messages without flag', async () => {
233
+ const result = await mapMessage({ role: 'user', content: 'Hello' });
234
+ expect(result).toEqual({ role: 'user', content: 'Hello' });
235
+ });
236
+ });
237
+ const testModel = ModelId('claude-haiku-4-5-20251001');
238
+ const buildRequest = (messages) => ({
239
+ model: testModel,
240
+ systemPrompt: 'You are helpful.',
241
+ messages,
242
+ });
243
+ const getBodyMessages = (body) => {
244
+ const b = body;
245
+ return b.messages;
246
+ };
247
+ describe('AnthropicProvider buildHttpRequest cache placement', () => {
248
+ test('pure tool_result target: cache_control lands on outer tool_result block', async () => {
249
+ const messages = applyCacheBreakpoint([
250
+ { role: 'user', content: 'What is the weather?' },
251
+ {
252
+ role: 'assistant',
253
+ content: '',
254
+ toolCalls: [{ id: ToolCallId('call_1'), name: 'get_weather', input: { city: 'Prague' } }],
255
+ },
256
+ { role: 'tool', toolCallId: ToolCallId('call_1'), content: 'Sunny, 22°C' },
257
+ ], 0);
258
+ const http = await createProvider().buildHttpRequest(buildRequest(messages));
259
+ const msgs = getBodyMessages(http.body);
260
+ // Last message is the merged user containing the tool_result
261
+ const last = msgs[msgs.length - 1];
262
+ expect(last.role).toBe('user');
263
+ expect(Array.isArray(last.content)).toBe(true);
264
+ const lastBlock = last.content[last.content.length - 1];
265
+ expect(lastBlock.type).toBe('tool_result');
266
+ expect(lastBlock.cache_control).toEqual({ type: 'ephemeral' });
267
+ });
268
+ test('consecutive tool_results merged: cache_control lands on LAST merged tool_result', async () => {
269
+ const messages = applyCacheBreakpoint([
270
+ { role: 'user', content: 'Check two cities' },
271
+ {
272
+ role: 'assistant',
273
+ content: '',
274
+ toolCalls: [
275
+ { id: ToolCallId('call_1'), name: 'get_weather', input: { city: 'Prague' } },
276
+ { id: ToolCallId('call_2'), name: 'get_weather', input: { city: 'London' } },
277
+ ],
278
+ },
279
+ { role: 'tool', toolCallId: ToolCallId('call_1'), content: 'Sunny' },
280
+ { role: 'tool', toolCallId: ToolCallId('call_2'), content: 'Rainy' },
281
+ ], 0);
282
+ const http = await createProvider().buildHttpRequest(buildRequest(messages));
283
+ const msgs = getBodyMessages(http.body);
284
+ const last = msgs[msgs.length - 1];
285
+ expect(last.role).toBe('user');
286
+ // Two tool_results merged into one user message
287
+ expect(last.content.length).toBe(2);
288
+ expect(last.content[0].type).toBe('tool_result');
289
+ expect(last.content[1].type).toBe('tool_result');
290
+ expect(last.content[0].cache_control).toBeUndefined();
291
+ // cache_control is on the LAST tool_result (the target message's block after merge)
292
+ expect(last.content[1].cache_control).toEqual({ type: 'ephemeral' });
293
+ });
294
+ test('assistant [text, tool_use, tool_use] target: cache_control lands on LAST tool_use', async () => {
295
+ const messages = applyCacheBreakpoint([
296
+ { role: 'user', content: 'Check weather and search' },
297
+ {
298
+ role: 'assistant',
299
+ content: 'Let me check both',
300
+ toolCalls: [
301
+ { id: ToolCallId('call_1'), name: 'get_weather', input: { city: 'Prague' } },
302
+ { id: ToolCallId('call_2'), name: 'search', input: { query: 'weather' } },
303
+ ],
304
+ },
305
+ ], 0);
306
+ const http = await createProvider().buildHttpRequest(buildRequest(messages));
307
+ const msgs = getBodyMessages(http.body);
308
+ const assistant = msgs[msgs.length - 1];
309
+ expect(assistant.role).toBe('assistant');
310
+ expect(assistant.content.length).toBe(3); // text + 2 tool_use
311
+ expect(assistant.content[0].type).toBe('text');
312
+ expect(assistant.content[0].cache_control).toBeUndefined();
313
+ expect(assistant.content[1].type).toBe('tool_use');
314
+ expect(assistant.content[1].cache_control).toBeUndefined();
315
+ // cache_control lands on the LAST block (last tool_use), not the first text block
316
+ expect(assistant.content[2].type).toBe('tool_use');
317
+ expect(assistant.content[2].cache_control).toEqual({ type: 'ephemeral' });
318
+ });
319
+ test('ephemeral suffix: breakpoint at idx-1, ephemeral user merges after as uncached suffix', async () => {
320
+ const history = [
321
+ { role: 'user', content: 'Initial question' },
322
+ {
323
+ role: 'assistant',
324
+ content: '',
325
+ toolCalls: [{ id: ToolCallId('call_1'), name: 'get_weather', input: { city: 'Prague' } }],
326
+ },
327
+ { role: 'tool', toolCallId: ToolCallId('call_1'), content: 'Sunny' },
328
+ // simulate agent.ts pushing ephemeral session context last
329
+ { role: 'user', content: '<session-context>plugin status</session-context>' },
330
+ ];
331
+ const messages = applyCacheBreakpoint(history, 1); // uncachedSuffixCount = 1 (ephemeral tail)
332
+ const http = await createProvider().buildHttpRequest(buildRequest(messages));
333
+ const msgs = getBodyMessages(http.body);
334
+ // mergeConsecutiveMessages folds the tool_result and ephemeral into one user message
335
+ const last = msgs[msgs.length - 1];
336
+ expect(last.role).toBe('user');
337
+ // Content: [tool_result (cached), text (ephemeral, uncached)]
338
+ expect(last.content.length).toBe(2);
339
+ expect(last.content[0].type).toBe('tool_result');
340
+ expect(last.content[0].cache_control).toEqual({ type: 'ephemeral' });
341
+ expect(last.content[1].type).toBe('text');
342
+ // Ephemeral comes AFTER the cache checkpoint, so it's fresh each call
343
+ expect(last.content[1].cache_control).toBeUndefined();
344
+ });
345
+ test('no flag on any message: only system prompt has cache_control', async () => {
346
+ const http = await createProvider().buildHttpRequest(buildRequest([
347
+ { role: 'user', content: 'What is 2+2?' },
348
+ { role: 'assistant', content: '4' },
349
+ { role: 'user', content: 'And 3+3?' },
350
+ ]));
351
+ const msgs = getBodyMessages(http.body);
352
+ for (const msg of msgs) {
353
+ for (const block of msg.content) {
354
+ expect(block.cache_control).toBeUndefined();
355
+ }
356
+ }
357
+ // System still has cache_control (hardcoded in provider)
358
+ const system = http.body.system;
359
+ expect(system[0].cache_control).toEqual({ type: 'ephemeral' });
360
+ });
361
+ });
362
+ // ============================================================================
363
+ // Stop Reason Mapping
364
+ // ============================================================================
365
+ describe('AnthropicProvider stop reason mapping', () => {
366
+ test('maps end_turn to stop', () => {
367
+ expect(mapStopReason('end_turn')).toBe('stop');
368
+ });
369
+ test('maps tool_use to tool_calls', () => {
370
+ expect(mapStopReason('tool_use')).toBe('tool_calls');
371
+ });
372
+ test('maps max_tokens to length', () => {
373
+ expect(mapStopReason('max_tokens')).toBe('length');
374
+ });
375
+ test('maps null to stop', () => {
376
+ expect(mapStopReason(null)).toBe('stop');
377
+ });
378
+ test('maps unknown reason to stop', () => {
379
+ expect(mapStopReason('something_new')).toBe('stop');
380
+ });
381
+ });
382
+ // ============================================================================
383
+ // Error Mapping
384
+ // ============================================================================
385
+ describe('AnthropicProvider error mapping', () => {
386
+ test('maps AbortError', () => {
387
+ const err = new Error('aborted');
388
+ err.name = 'AbortError';
389
+ const result = mapError(err);
390
+ expect(result.type).toBe('aborted');
391
+ });
392
+ test('maps unknown error to network_error', () => {
393
+ const result = mapError(new Error('something'));
394
+ expect(result.type).toBe('network_error');
395
+ expect(result.message).toBe('something');
396
+ });
397
+ test('maps string error', () => {
398
+ const result = mapError('boom');
399
+ expect(result.type).toBe('network_error');
400
+ expect(result.message).toBe('boom');
401
+ });
402
+ });
403
+ // ============================================================================
404
+ // Model Routing (canHandle / normalizeModel)
405
+ // ============================================================================
406
+ describe('AnthropicProvider model routing', () => {
407
+ test('handles anthropic/ prefixed models', () => {
408
+ expect(provider.canHandle('anthropic/claude-sonnet-4.5')).toBe(true);
409
+ expect(provider.canHandle('anthropic/claude-haiku-4.5')).toBe(true);
410
+ expect(provider.canHandle('anthropic/claude-3.5-haiku')).toBe(true);
411
+ });
412
+ test('handles claude- prefixed models without vendor prefix', () => {
413
+ expect(provider.canHandle('claude-sonnet-4-5-20250514')).toBe(true);
414
+ expect(provider.canHandle('claude-3-5-haiku-20241022')).toBe(true);
415
+ });
416
+ test('does not handle non-Anthropic models', () => {
417
+ expect(provider.canHandle('openai/gpt-4o')).toBe(false);
418
+ expect(provider.canHandle('google/gemini-pro')).toBe(false);
419
+ expect(provider.canHandle('meta-llama/llama-3')).toBe(false);
420
+ });
421
+ test('strips anthropic/ prefix and converts dots to dashes', () => {
422
+ expect(provider.normalizeModel('anthropic/claude-opus-4.6')).toBe('claude-opus-4-6');
423
+ expect(provider.normalizeModel('anthropic/claude-sonnet-4.5')).toBe('claude-sonnet-4-5');
424
+ expect(provider.normalizeModel('anthropic/claude-haiku-4.5')).toBe('claude-haiku-4-5');
425
+ });
426
+ test('converts dots to dashes without prefix', () => {
427
+ expect(provider.normalizeModel('claude-opus-4.6')).toBe('claude-opus-4-6');
428
+ });
429
+ test('keeps model ID as-is when already in Anthropic format', () => {
430
+ expect(provider.normalizeModel('claude-sonnet-4-5-20250514')).toBe('claude-sonnet-4-5-20250514');
431
+ expect(provider.normalizeModel('claude-opus-4-6')).toBe('claude-opus-4-6');
432
+ });
433
+ });
434
+ //# sourceMappingURL=anthropic.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.test.js","sourceRoot":"","sources":["../../../src/core/llm/anthropic.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAEjD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAG7D,+EAA+E;AAC/E,6DAA6D;AAC7D,+EAA+E;AAE/E,MAAM,cAAc,GAAG,GAAG,EAAE,CAC3B,IAAI,iBAAiB,CAAC;IACrB,MAAM,EAAE,UAAU;IAClB,cAAc,EAAE;QACf,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO;KAC1C;CACD,CAAC,CAAA;AAEH,4DAA4D;AAC5D,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAA;AACjC,MAAM,UAAU,GAAI,QAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAqE,CAAA;AAClI,MAAM,wBAAwB,GAAI,QAAgB,CAAC,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAEhD,CAAA;AACzC,MAAM,aAAa,GAAI,QAAgB,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAsC,CAAA;AACzG,MAAM,QAAQ,GAAI,QAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAA8B,CAAA;AAEvF,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAClD,IAAI,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE;gBAC5C,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,8BAA8B,EAAE,EAAE;aACxE;SACD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE;gBAC5C,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;aACtF;SACD,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACR,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,6BAA6B,EAAE,EAAE;aACvE;SACD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACR,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,6BAA6B,EAAE,EAAE;aAC9E;SACD,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAA;QAC7E,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;SAC/C,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;SACjF,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE;gBACrC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;aAC1E;SACD,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;SACjF,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE;gBACR,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;aAC1E;SACD,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,aAAa;YACtB,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC;SAC9B,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;SAC/E,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,kBAAkB;YAC3B,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC;YAC9B,OAAO,EAAE,IAAI;SACb,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;SAC5F,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAA;QACnF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC;SACjE,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACtD,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC7C,MAAM,QAAQ,GAAG;YAChB,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,OAAO,EAAE;YAC3C,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,cAAc,EAAE;SAClD,CAAA;QACD,MAAM,MAAM,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;gBACvB,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACR,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;oBAC/B,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE;iBACtC;aACD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACtE,MAAM,QAAQ,GAAG;YAChB,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAsB,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE;YAC/G,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAsB,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE;SAC/G,CAAA;QACD,MAAM,MAAM,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnD,MAAM,CAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACzD,MAAM,QAAQ,GAAG;YAChB,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,OAAO,EAAE;YAC3C,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE,IAAI,EAAE;YAC7C,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,cAAc,EAAE;SAClD,CAAA;QACD,MAAM,MAAM,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACrD,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;QACjE,MAAM,QAAQ,GAAiB;YAC9B,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;YAClC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE;YACpC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;SACrC,CAAA;QACD,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;QAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,aAAa,EAAE,CAAA;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,aAAa,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC/D,MAAM,QAAQ,GAAiB;YAC9B,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;YAClC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE;YACpC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;SACrC,CAAA;QACD,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;QAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,aAAa,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACpD,MAAM,QAAQ,GAAiB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;QACnE,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,aAAa,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,8CAA8C,EAAE,GAAG,EAAE;IAC7D,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,OAAO;YAChB,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;SACnC,CAAC,CAAA;QACF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAA2D,CAAA;QAClF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IACjF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,aAAa;YACtB,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC;YAC9B,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;SACnC,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAA2D,CAAA;QAClF,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC/B,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;YACjF,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;SACnC,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAA2D,CAAA;QAClF,oEAAoE;QACpE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACzD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IACjF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAaF,MAAM,SAAS,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAA;AAEtD,MAAM,YAAY,GAAG,CAAC,QAAsB,EAAuB,EAAE,CAAC,CAAC;IACtE,KAAK,EAAE,SAAS;IAChB,YAAY,EAAE,kBAAkB;IAChC,QAAQ;CACR,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC,IAAa,EAAsB,EAAE;IAC7D,MAAM,CAAC,GAAG,IAAwC,CAAA;IAClD,OAAO,CAAC,CAAC,QAAQ,CAAA;AAClB,CAAC,CAAA;AAED,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IACnE,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,QAAQ,GAAG,oBAAoB,CAAC;YACrC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE;YACjD;gBACC,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;aACzF;YACD,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE;SAC1E,EAAE,CAAC,CAAC,CAAA;QAEL,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC5E,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEvC,6DAA6D;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACvD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC1C,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,QAAQ,GAAG,oBAAoB,CAAC;YACrC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE;YAC7C;gBACC,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE;oBACV,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBAC5E,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;iBAC5E;aACD;YACD,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;YACpE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;SACpE,EAAE,CAAC,CAAC,CAAA;QAEL,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC5E,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9B,gDAAgD;QAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,CAAA;QACrD,oFAAoF;QACpF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;QACpG,MAAM,QAAQ,GAAG,oBAAoB,CAAC;YACrC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,0BAA0B,EAAE;YACrD;gBACC,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,mBAAmB;gBAC5B,SAAS,EAAE;oBACV,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBAC5E,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;iBACzE;aACD;SACD,EAAE,CAAC,CAAC,CAAA;QAEL,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC5E,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACxC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA,CAAC,oBAAoB;QAC7D,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9C,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,CAAA;QAC1D,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAClD,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,CAAA;QAC1D,kFAAkF;QAClF,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAClD,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACxG,MAAM,OAAO,GAAiB;YAC7B,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE;YAC7C;gBACC,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;aACzF;YACD,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;YACpE,2DAA2D;YAC3D,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kDAAkD,EAAE;SAC7E,CAAA;QACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA,CAAC,2CAA2C;QAE7F,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC5E,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEvC,qFAAqF;QACrF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9B,8DAA8D;QAC9D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;QACpE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACzC,sEAAsE;QACtE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC;YACjE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE;YACzC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE;YACnC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;SACrC,CAAC,CAAC,CAAA;QACH,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEvC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,CAAA;YAC5C,CAAC;QACF,CAAC;QACD,yDAAyD;QACzD,MAAM,MAAM,GAAI,IAAI,CAAC,IAA+B,CAAC,MAAM,CAAA;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACtD,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAChD,IAAI,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC5B,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAA;QAChC,GAAG,CAAC,IAAI,GAAG,YAAY,CAAA;QACvB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAQ,CAAA;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAQ,CAAA;QACtD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACzC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC9B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAQ,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACzC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,6CAA6C;AAC7C,+EAA+E;AAE/E,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAChD,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACnE,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3D,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACpF,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QACxF,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACvF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;QAChG,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Mark the prompt cache breakpoint on a message list.
3
+ *
4
+ * Flag-based: the target message gets a `cacheControl` marker. Providers that
5
+ * support ephemeral prompt caching (anthropic, openrouter) react to the flag
6
+ * during `buildHttpRequest` and place `cache_control: { type: 'ephemeral' }`
7
+ * on the LAST content block of the mapped message — regardless of block type
8
+ * (text / tool_use / tool_result / image). This matches the API semantics
9
+ * "cache the prefix up to and including this block".
10
+ *
11
+ * Target index is `messages.length - 1 - uncachedSuffixCount`. The suffix is
12
+ * the tail of messages that must remain fresh (e.g. ephemeral session context
13
+ * rebuilt each inference).
14
+ */
15
+ export function applyCacheBreakpoint(messages, uncachedSuffixCount) {
16
+ const idx = messages.length - 1 - uncachedSuffixCount;
17
+ if (idx < 0)
18
+ return messages;
19
+ const target = messages[idx];
20
+ const result = [...messages];
21
+ switch (target.role) {
22
+ case 'user':
23
+ result[idx] = { ...target, cacheControl: { type: 'ephemeral' } };
24
+ break;
25
+ case 'assistant':
26
+ result[idx] = { ...target, cacheControl: { type: 'ephemeral' } };
27
+ break;
28
+ case 'system':
29
+ result[idx] = { ...target, cacheControl: { type: 'ephemeral' } };
30
+ break;
31
+ case 'tool':
32
+ result[idx] = { ...target, cacheControl: { type: 'ephemeral' } };
33
+ break;
34
+ }
35
+ return result;
36
+ }
37
+ //# sourceMappingURL=cache-breakpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-breakpoints.js","sourceRoot":"","sources":["../../../src/core/llm/cache-breakpoints.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAsB,EAAE,mBAA2B;IACvF,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,mBAAmB,CAAA;IACrD,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAA;IAE5B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAA;IAC5B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,MAAM;YACV,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAA;YAChE,MAAK;QACN,KAAK,WAAW;YACf,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAA;YAChE,MAAK;QACN,KAAK,QAAQ;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAA;YAChE,MAAK;QACN,KAAK,MAAM;YACV,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAA;YAChE,MAAK;IACP,CAAC;IACD,OAAO,MAAM,CAAA;AACd,CAAC"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Live cache verification tests for Anthropic + OpenRouter providers.
3
+ *
4
+ * Opt-in: run with `LIVE_TESTS=1 ANTHROPIC_API_KEY=… OPENROUTER_API_KEY=…`.
5
+ * Skipped otherwise so the default `bun test` run stays hermetic.
6
+ *
7
+ * These tests bypass snapshot-fetch entirely (use real `globalThis.fetch`) so
8
+ * two sequential identical calls actually land on the live API — proving that
9
+ * the new message-level `cacheControl` flag → last-block placement is both
10
+ * accepted and honored as a prompt cache checkpoint.
11
+ *
12
+ * The system prompt is padded to comfortably exceed Anthropic's 1024-token
13
+ * minimum cacheable prefix for Haiku / Sonnet.
14
+ */
15
+ import { describe, expect, test } from 'bun:test';
16
+ import z4 from 'zod/v4';
17
+ import { ToolCallId } from '../../core/tools/schema.js';
18
+ import { AnthropicProvider } from './anthropic.js';
19
+ import { applyCacheBreakpoint } from './cache-breakpoints.js';
20
+ import { OpenRouterProvider } from './openrouter.js';
21
+ import { ModelId } from './schema.js';
22
+ const liveEnabled = process.env.LIVE_TESTS === '1';
23
+ const anthropicApiKey = liveEnabled ? process.env.ANTHROPIC_API_KEY : undefined;
24
+ const openRouterApiKey = liveEnabled ? process.env.OPENROUTER_API_KEY : undefined;
25
+ const noopImageProcessor = {
26
+ resolveContent: async (content) => content,
27
+ };
28
+ const weatherTool = {
29
+ name: 'get_weather',
30
+ description: 'Get current weather for a city',
31
+ input: z4.object({ city: z4.string() }),
32
+ execute: async () => ({ ok: true, value: 'not implemented' }),
33
+ };
34
+ /**
35
+ * Large filler system prompt to push the cacheable prefix comfortably past
36
+ * Anthropic's 1024-token minimum. Content is deterministic so successive
37
+ * calls reuse the exact same prefix.
38
+ */
39
+ const LARGE_SYSTEM_PROMPT = [
40
+ 'You are a meticulous assistant helping with data analysis tasks.',
41
+ 'Always respond concisely and accurately. Never speculate beyond the data.',
42
+ 'When you use tools, interpret the results carefully and explain your reasoning.',
43
+ 'Follow these rules strictly:',
44
+ ...Array.from({ length: 120 }, (_, i) => `- Rule ${i + 1}: When asked about topic ${i + 1}, prefer factual sources and cite them when possible. Decline to speculate.`),
45
+ 'End of instructions.',
46
+ ].join('\n');
47
+ const describeLive = (name, apiKey, fn) => {
48
+ if (!apiKey) {
49
+ describe.skip(`${name} (skipped — API key missing)`, fn);
50
+ return;
51
+ }
52
+ describe(name, fn);
53
+ };
54
+ describeLive('Anthropic live cache verification', anthropicApiKey, () => {
55
+ test('cacheControl on tool_result target causes cache write then cache read', async () => {
56
+ const provider = new AnthropicProvider({
57
+ apiKey: anthropicApiKey,
58
+ imageProcessor: noopImageProcessor,
59
+ defaultModel: 'claude-haiku-4-5-20251001',
60
+ });
61
+ const history = [
62
+ { role: 'user', content: 'What is the weather in Prague?' },
63
+ {
64
+ role: 'assistant',
65
+ content: '',
66
+ toolCalls: [{ id: ToolCallId('call_1'), name: 'get_weather', input: { city: 'Prague' } }],
67
+ },
68
+ {
69
+ role: 'tool',
70
+ toolCallId: ToolCallId('call_1'),
71
+ content: 'Sunny, 22°C, light breeze from the west.',
72
+ },
73
+ ];
74
+ const messages = applyCacheBreakpoint(history, 0);
75
+ const request = {
76
+ model: ModelId('claude-haiku-4-5-20251001'),
77
+ systemPrompt: LARGE_SYSTEM_PROMPT,
78
+ messages,
79
+ tools: [weatherTool],
80
+ };
81
+ // First call — primes the cache
82
+ const first = await provider.inference(request);
83
+ if (!first.ok) {
84
+ if (first.error.message?.includes('credit balance')) {
85
+ console.warn('⚠️ Anthropic live cache test skipped: credit balance too low');
86
+ return;
87
+ }
88
+ throw new Error(`first call failed: ${JSON.stringify(first.error)}`);
89
+ }
90
+ expect(first.value.metrics.promptTokens).toBeGreaterThan(1024);
91
+ // Second call — cache read proves the write on call 1 was honored
92
+ const second = await provider.inference(request);
93
+ if (!second.ok)
94
+ throw new Error(`second call failed: ${JSON.stringify(second.error)}`);
95
+ expect(second.value.metrics.cachedTokens ?? 0).toBeGreaterThan(1024);
96
+ }, 60_000);
97
+ });
98
+ describeLive('OpenRouter live cache verification', openRouterApiKey, () => {
99
+ test('cacheControl on tool_result target produces cache hit on second call', async () => {
100
+ const provider = new OpenRouterProvider({
101
+ apiKey: openRouterApiKey,
102
+ imageProcessor: noopImageProcessor,
103
+ defaultModel: 'anthropic/claude-haiku-4.5',
104
+ });
105
+ const history = [
106
+ { role: 'user', content: 'What is the weather in Prague?' },
107
+ {
108
+ role: 'assistant',
109
+ content: '',
110
+ toolCalls: [{ id: ToolCallId('call_1'), name: 'get_weather', input: { city: 'Prague' } }],
111
+ },
112
+ {
113
+ role: 'tool',
114
+ toolCallId: ToolCallId('call_1'),
115
+ content: 'Sunny, 22°C, light breeze from the west.',
116
+ },
117
+ ];
118
+ const messages = applyCacheBreakpoint(history, 0);
119
+ const request = {
120
+ model: ModelId('anthropic/claude-haiku-4.5'),
121
+ systemPrompt: LARGE_SYSTEM_PROMPT,
122
+ messages,
123
+ tools: [weatherTool],
124
+ };
125
+ // First call primes the cache
126
+ const first = await provider.inference(request);
127
+ if (!first.ok)
128
+ throw new Error(`first call failed: ${JSON.stringify(first.error)}`);
129
+ expect(first.value.metrics.promptTokens).toBeGreaterThan(1024);
130
+ // Second call — same prefix → cache read proves the write on call 1 was honored
131
+ const second = await provider.inference(request);
132
+ if (!second.ok)
133
+ throw new Error(`second call failed: ${JSON.stringify(second.error)}`);
134
+ expect(second.value.metrics.cachedTokens ?? 0).toBeGreaterThan(1024);
135
+ }, 60_000);
136
+ });
137
+ //# sourceMappingURL=cache-live.test.js.map