@anthropic-ai/sdk 0.125.0 → 0.127.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/client.d.mts +12 -11
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +12 -11
  5. package/client.d.ts.map +1 -1
  6. package/client.js +865 -845
  7. package/client.js.map +1 -1
  8. package/client.mjs +866 -840
  9. package/client.mjs.map +1 -1
  10. package/core/api-promise.js +71 -68
  11. package/core/api-promise.js.map +1 -1
  12. package/core/api-promise.mjs +71 -64
  13. package/core/api-promise.mjs.map +1 -1
  14. package/core/error.js +5 -2
  15. package/core/error.js.map +1 -1
  16. package/core/error.mjs +5 -2
  17. package/core/error.mjs.map +1 -1
  18. package/core/pagination.js +56 -50
  19. package/core/pagination.js.map +1 -1
  20. package/core/pagination.mjs +56 -41
  21. package/core/pagination.mjs.map +1 -1
  22. package/core/streaming.js +212 -209
  23. package/core/streaming.js.map +1 -1
  24. package/core/streaming.mjs +212 -209
  25. package/core/streaming.mjs.map +1 -1
  26. package/helpers/beta/mcp.js +14 -19
  27. package/helpers/beta/mcp.js.map +1 -1
  28. package/helpers/beta/mcp.mjs +14 -13
  29. package/helpers/beta/mcp.mjs.map +1 -1
  30. package/internal/constants.js +1 -1
  31. package/internal/constants.js.map +1 -1
  32. package/internal/decoders/jsonl.js +27 -24
  33. package/internal/decoders/jsonl.js.map +1 -1
  34. package/internal/decoders/jsonl.mjs +27 -24
  35. package/internal/decoders/jsonl.mjs.map +1 -1
  36. package/internal/decoders/line.js +52 -49
  37. package/internal/decoders/line.js.map +1 -1
  38. package/internal/decoders/line.mjs +52 -43
  39. package/internal/decoders/line.mjs.map +1 -1
  40. package/internal/file-store.js +256 -258
  41. package/internal/file-store.js.map +1 -1
  42. package/internal/file-store.mjs +256 -243
  43. package/internal/file-store.mjs.map +1 -1
  44. package/internal/node.browser.d.mts.map +1 -1
  45. package/internal/node.browser.d.ts.map +1 -1
  46. package/internal/node.browser.js.map +1 -1
  47. package/internal/node.browser.mjs +7 -7
  48. package/internal/node.browser.mjs.map +1 -1
  49. package/internal/parse.d.mts.map +1 -1
  50. package/internal/parse.d.ts.map +1 -1
  51. package/internal/parse.js +2 -2
  52. package/internal/parse.js.map +1 -1
  53. package/internal/parse.mjs +3 -3
  54. package/internal/parse.mjs.map +1 -1
  55. package/internal/shim-types.js +0 -6
  56. package/internal/shim-types.js.map +1 -1
  57. package/internal/shim-types.mjs +0 -6
  58. package/internal/shim-types.mjs.map +1 -1
  59. package/internal/shims.d.mts +3 -3
  60. package/internal/shims.d.mts.map +1 -1
  61. package/internal/shims.d.ts +3 -3
  62. package/internal/shims.d.ts.map +1 -1
  63. package/internal/shims.js +0 -6
  64. package/internal/shims.js.map +1 -1
  65. package/internal/shims.mjs +0 -6
  66. package/internal/shims.mjs.map +1 -1
  67. package/internal/stainless-helper-header.js +6 -6
  68. package/internal/stainless-helper-header.js.map +1 -1
  69. package/internal/utils/async-queue.js +66 -63
  70. package/internal/utils/async-queue.js.map +1 -1
  71. package/internal/utils/async-queue.mjs +66 -56
  72. package/internal/utils/async-queue.mjs.map +1 -1
  73. package/internal/utils/bytes.d.mts +1 -1
  74. package/internal/utils/bytes.d.mts.map +1 -1
  75. package/internal/utils/bytes.d.ts +1 -1
  76. package/internal/utils/bytes.d.ts.map +1 -1
  77. package/internal/utils/log.d.mts +7 -12
  78. package/internal/utils/log.d.mts.map +1 -1
  79. package/internal/utils/log.d.ts +7 -12
  80. package/internal/utils/log.d.ts.map +1 -1
  81. package/internal/utils/log.js +12 -0
  82. package/internal/utils/log.js.map +1 -1
  83. package/internal/utils/log.mjs +11 -0
  84. package/internal/utils/log.mjs.map +1 -1
  85. package/lib/BetaMessageStream.d.mts.map +1 -1
  86. package/lib/BetaMessageStream.d.ts.map +1 -1
  87. package/lib/BetaMessageStream.js +595 -590
  88. package/lib/BetaMessageStream.js.map +1 -1
  89. package/lib/BetaMessageStream.mjs +595 -590
  90. package/lib/BetaMessageStream.mjs.map +1 -1
  91. package/lib/MessageStream.js +544 -541
  92. package/lib/MessageStream.js.map +1 -1
  93. package/lib/MessageStream.mjs +544 -541
  94. package/lib/MessageStream.mjs.map +1 -1
  95. package/lib/beta-parser.d.mts +1 -3
  96. package/lib/beta-parser.d.mts.map +1 -1
  97. package/lib/beta-parser.d.ts +1 -3
  98. package/lib/beta-parser.d.ts.map +1 -1
  99. package/lib/beta-parser.js.map +1 -1
  100. package/lib/beta-parser.mjs.map +1 -1
  101. package/lib/environments/poller.js +180 -174
  102. package/lib/environments/poller.js.map +1 -1
  103. package/lib/environments/poller.mjs +180 -153
  104. package/lib/environments/poller.mjs.map +1 -1
  105. package/lib/environments/worker.js +375 -369
  106. package/lib/environments/worker.js.map +1 -1
  107. package/lib/environments/worker.mjs +374 -329
  108. package/lib/environments/worker.mjs.map +1 -1
  109. package/lib/internal/stub.d.mts +2 -0
  110. package/lib/internal/stub.d.mts.map +1 -0
  111. package/lib/internal/stub.d.ts +2 -0
  112. package/lib/internal/stub.d.ts.map +1 -0
  113. package/lib/internal/stub.js +6 -0
  114. package/lib/internal/stub.js.map +1 -0
  115. package/lib/internal/stub.mjs +3 -0
  116. package/lib/internal/stub.mjs.map +1 -0
  117. package/lib/internal/types.d.mts +5 -0
  118. package/lib/internal/types.d.mts.map +1 -0
  119. package/lib/internal/types.d.ts +5 -0
  120. package/lib/internal/types.d.ts.map +1 -0
  121. package/lib/internal/types.js +3 -0
  122. package/lib/internal/types.js.map +1 -0
  123. package/lib/internal/types.mjs +2 -0
  124. package/lib/internal/types.mjs.map +1 -0
  125. package/lib/middleware.js +6 -1
  126. package/lib/middleware.js.map +1 -1
  127. package/lib/middleware.mjs +6 -1
  128. package/lib/middleware.mjs.map +1 -1
  129. package/lib/parser.d.mts +1 -3
  130. package/lib/parser.d.mts.map +1 -1
  131. package/lib/parser.d.ts +1 -3
  132. package/lib/parser.d.ts.map +1 -1
  133. package/lib/parser.js.map +1 -1
  134. package/lib/parser.mjs.map +1 -1
  135. package/lib/tools/BetaToolRunner.d.mts +21 -6
  136. package/lib/tools/BetaToolRunner.d.mts.map +1 -1
  137. package/lib/tools/BetaToolRunner.d.ts +21 -6
  138. package/lib/tools/BetaToolRunner.d.ts.map +1 -1
  139. package/lib/tools/BetaToolRunner.js +415 -310
  140. package/lib/tools/BetaToolRunner.js.map +1 -1
  141. package/lib/tools/BetaToolRunner.mjs +414 -303
  142. package/lib/tools/BetaToolRunner.mjs.map +1 -1
  143. package/lib/tools/SessionToolRunner.js +241 -235
  144. package/lib/tools/SessionToolRunner.js.map +1 -1
  145. package/lib/tools/SessionToolRunner.mjs +241 -192
  146. package/lib/tools/SessionToolRunner.mjs.map +1 -1
  147. package/lib/tools/ToolError.js +39 -36
  148. package/lib/tools/ToolError.js.map +1 -1
  149. package/lib/tools/ToolError.mjs +39 -13
  150. package/lib/tools/ToolError.mjs.map +1 -1
  151. package/lib/transform-json-schema.js +7 -5
  152. package/lib/transform-json-schema.js.map +1 -1
  153. package/lib/transform-json-schema.mjs +7 -5
  154. package/lib/transform-json-schema.mjs.map +1 -1
  155. package/package.json +4 -3
  156. package/resources/beta/agents/agents.js +135 -132
  157. package/resources/beta/agents/agents.js.map +1 -1
  158. package/resources/beta/agents/agents.mjs +135 -132
  159. package/resources/beta/agents/agents.mjs.map +1 -1
  160. package/resources/beta/beta.d.mts +5 -5
  161. package/resources/beta/beta.d.mts.map +1 -1
  162. package/resources/beta/beta.d.ts +5 -5
  163. package/resources/beta/beta.d.ts.map +1 -1
  164. package/resources/beta/beta.js +39 -36
  165. package/resources/beta/beta.js.map +1 -1
  166. package/resources/beta/beta.mjs +39 -36
  167. package/resources/beta/beta.mjs.map +1 -1
  168. package/resources/beta/deployment-runs.d.mts +4 -0
  169. package/resources/beta/deployment-runs.d.mts.map +1 -1
  170. package/resources/beta/deployment-runs.d.ts +4 -0
  171. package/resources/beta/deployment-runs.d.ts.map +1 -1
  172. package/resources/beta/deployments.d.mts +5 -0
  173. package/resources/beta/deployments.d.mts.map +1 -1
  174. package/resources/beta/deployments.d.ts +5 -0
  175. package/resources/beta/deployments.d.ts.map +1 -1
  176. package/resources/beta/dreams.d.mts +19 -28
  177. package/resources/beta/dreams.d.mts.map +1 -1
  178. package/resources/beta/dreams.d.ts +19 -28
  179. package/resources/beta/dreams.d.ts.map +1 -1
  180. package/resources/beta/environments/environments.js +157 -154
  181. package/resources/beta/environments/environments.js.map +1 -1
  182. package/resources/beta/environments/environments.mjs +157 -154
  183. package/resources/beta/environments/environments.mjs.map +1 -1
  184. package/resources/beta/environments/work.js +255 -252
  185. package/resources/beta/environments/work.js.map +1 -1
  186. package/resources/beta/environments/work.mjs +255 -252
  187. package/resources/beta/environments/work.mjs.map +1 -1
  188. package/resources/beta/index.d.mts +2 -2
  189. package/resources/beta/index.d.mts.map +1 -1
  190. package/resources/beta/index.d.ts +2 -2
  191. package/resources/beta/index.d.ts.map +1 -1
  192. package/resources/beta/index.js.map +1 -1
  193. package/resources/beta/index.mjs.map +1 -1
  194. package/resources/beta/memory-stores/memories.d.mts +6 -0
  195. package/resources/beta/memory-stores/memories.d.mts.map +1 -1
  196. package/resources/beta/memory-stores/memories.d.ts +6 -0
  197. package/resources/beta/memory-stores/memories.d.ts.map +1 -1
  198. package/resources/beta/memory-stores/memory-stores.js +150 -147
  199. package/resources/beta/memory-stores/memory-stores.js.map +1 -1
  200. package/resources/beta/memory-stores/memory-stores.mjs +150 -147
  201. package/resources/beta/memory-stores/memory-stores.mjs.map +1 -1
  202. package/resources/beta/memory-stores/memory-versions.d.mts +7 -0
  203. package/resources/beta/memory-stores/memory-versions.d.mts.map +1 -1
  204. package/resources/beta/memory-stores/memory-versions.d.ts +7 -0
  205. package/resources/beta/memory-stores/memory-versions.d.ts.map +1 -1
  206. package/resources/beta/messages/batches.d.mts +12 -1
  207. package/resources/beta/messages/batches.d.mts.map +1 -1
  208. package/resources/beta/messages/batches.d.ts +12 -1
  209. package/resources/beta/messages/batches.d.ts.map +1 -1
  210. package/resources/beta/messages/index.d.mts +1 -1
  211. package/resources/beta/messages/index.d.mts.map +1 -1
  212. package/resources/beta/messages/index.d.ts +1 -1
  213. package/resources/beta/messages/index.d.ts.map +1 -1
  214. package/resources/beta/messages/index.js.map +1 -1
  215. package/resources/beta/messages/index.mjs.map +1 -1
  216. package/resources/beta/messages/messages.d.mts +239 -101
  217. package/resources/beta/messages/messages.d.mts.map +1 -1
  218. package/resources/beta/messages/messages.d.ts +239 -101
  219. package/resources/beta/messages/messages.d.ts.map +1 -1
  220. package/resources/beta/messages/messages.js +113 -110
  221. package/resources/beta/messages/messages.js.map +1 -1
  222. package/resources/beta/messages/messages.mjs +113 -110
  223. package/resources/beta/messages/messages.mjs.map +1 -1
  224. package/resources/beta/models.d.mts +22 -1
  225. package/resources/beta/models.d.mts.map +1 -1
  226. package/resources/beta/models.d.ts +22 -1
  227. package/resources/beta/models.d.ts.map +1 -1
  228. package/resources/beta/organization/federation/federation.js +11 -8
  229. package/resources/beta/organization/federation/federation.js.map +1 -1
  230. package/resources/beta/organization/federation/federation.mjs +11 -8
  231. package/resources/beta/organization/federation/federation.mjs.map +1 -1
  232. package/resources/beta/organization/federation/rules/rules.js +187 -184
  233. package/resources/beta/organization/federation/rules/rules.js.map +1 -1
  234. package/resources/beta/organization/federation/rules/rules.mjs +187 -184
  235. package/resources/beta/organization/federation/rules/rules.mjs.map +1 -1
  236. package/resources/beta/organization/index.d.mts +1 -1
  237. package/resources/beta/organization/index.d.mts.map +1 -1
  238. package/resources/beta/organization/index.d.ts +1 -1
  239. package/resources/beta/organization/index.d.ts.map +1 -1
  240. package/resources/beta/organization/index.js.map +1 -1
  241. package/resources/beta/organization/index.mjs.map +1 -1
  242. package/resources/beta/organization/organization.d.mts +2 -2
  243. package/resources/beta/organization/organization.d.mts.map +1 -1
  244. package/resources/beta/organization/organization.d.ts +2 -2
  245. package/resources/beta/organization/organization.d.ts.map +1 -1
  246. package/resources/beta/organization/organization.js +38 -35
  247. package/resources/beta/organization/organization.js.map +1 -1
  248. package/resources/beta/organization/organization.mjs +38 -35
  249. package/resources/beta/organization/organization.mjs.map +1 -1
  250. package/resources/beta/organization/rate-limits.d.mts +87 -5
  251. package/resources/beta/organization/rate-limits.d.mts.map +1 -1
  252. package/resources/beta/organization/rate-limits.d.ts +87 -5
  253. package/resources/beta/organization/rate-limits.d.ts.map +1 -1
  254. package/resources/beta/organization/service-accounts/service-accounts.js +163 -160
  255. package/resources/beta/organization/service-accounts/service-accounts.js.map +1 -1
  256. package/resources/beta/organization/service-accounts/service-accounts.mjs +163 -160
  257. package/resources/beta/organization/service-accounts/service-accounts.mjs.map +1 -1
  258. package/resources/beta/organization/workspaces/rate-limits.d.mts +9 -4
  259. package/resources/beta/organization/workspaces/rate-limits.d.mts.map +1 -1
  260. package/resources/beta/organization/workspaces/rate-limits.d.ts +9 -4
  261. package/resources/beta/organization/workspaces/rate-limits.d.ts.map +1 -1
  262. package/resources/beta/organization/workspaces/rate-limits.js.map +1 -1
  263. package/resources/beta/organization/workspaces/rate-limits.mjs.map +1 -1
  264. package/resources/beta/organization/workspaces/workspaces.d.mts +3 -3
  265. package/resources/beta/organization/workspaces/workspaces.d.mts.map +1 -1
  266. package/resources/beta/organization/workspaces/workspaces.d.ts +3 -3
  267. package/resources/beta/organization/workspaces/workspaces.d.ts.map +1 -1
  268. package/resources/beta/organization/workspaces/workspaces.js +97 -94
  269. package/resources/beta/organization/workspaces/workspaces.js.map +1 -1
  270. package/resources/beta/organization/workspaces/workspaces.mjs +97 -94
  271. package/resources/beta/organization/workspaces/workspaces.mjs.map +1 -1
  272. package/resources/beta/sessions/events.d.mts +12 -21
  273. package/resources/beta/sessions/events.d.mts.map +1 -1
  274. package/resources/beta/sessions/events.d.ts +12 -21
  275. package/resources/beta/sessions/events.d.ts.map +1 -1
  276. package/resources/beta/sessions/events.js +118 -115
  277. package/resources/beta/sessions/events.js.map +1 -1
  278. package/resources/beta/sessions/events.mjs +118 -115
  279. package/resources/beta/sessions/events.mjs.map +1 -1
  280. package/resources/beta/sessions/resources.d.mts +0 -3
  281. package/resources/beta/sessions/resources.d.mts.map +1 -1
  282. package/resources/beta/sessions/resources.d.ts +0 -3
  283. package/resources/beta/sessions/resources.d.ts.map +1 -1
  284. package/resources/beta/sessions/sessions.d.mts +8 -2
  285. package/resources/beta/sessions/sessions.d.mts.map +1 -1
  286. package/resources/beta/sessions/sessions.d.ts +8 -2
  287. package/resources/beta/sessions/sessions.d.ts.map +1 -1
  288. package/resources/beta/sessions/sessions.js +161 -158
  289. package/resources/beta/sessions/sessions.js.map +1 -1
  290. package/resources/beta/sessions/sessions.mjs +161 -158
  291. package/resources/beta/sessions/sessions.mjs.map +1 -1
  292. package/resources/beta/sessions/threads/threads.js +86 -83
  293. package/resources/beta/sessions/threads/threads.js.map +1 -1
  294. package/resources/beta/sessions/threads/threads.mjs +86 -83
  295. package/resources/beta/sessions/threads/threads.mjs.map +1 -1
  296. package/resources/beta/skills/skills.js +104 -101
  297. package/resources/beta/skills/skills.js.map +1 -1
  298. package/resources/beta/skills/skills.mjs +104 -101
  299. package/resources/beta/skills/skills.mjs.map +1 -1
  300. package/resources/beta/tunnels/certificates.d.mts +2 -2
  301. package/resources/beta/tunnels/certificates.d.ts +2 -2
  302. package/resources/beta/tunnels/tunnels.js +188 -185
  303. package/resources/beta/tunnels/tunnels.js.map +1 -1
  304. package/resources/beta/tunnels/tunnels.mjs +188 -185
  305. package/resources/beta/tunnels/tunnels.mjs.map +1 -1
  306. package/resources/beta/user-profiles.d.mts +45 -0
  307. package/resources/beta/user-profiles.d.mts.map +1 -1
  308. package/resources/beta/user-profiles.d.ts +45 -0
  309. package/resources/beta/user-profiles.d.ts.map +1 -1
  310. package/resources/beta/user-profiles.js +25 -10
  311. package/resources/beta/user-profiles.js.map +1 -1
  312. package/resources/beta/user-profiles.mjs +25 -10
  313. package/resources/beta/user-profiles.mjs.map +1 -1
  314. package/resources/beta/vaults/credentials.d.mts +19 -19
  315. package/resources/beta/vaults/credentials.d.mts.map +1 -1
  316. package/resources/beta/vaults/credentials.d.ts +19 -19
  317. package/resources/beta/vaults/credentials.d.ts.map +1 -1
  318. package/resources/beta/vaults/vaults.js +156 -153
  319. package/resources/beta/vaults/vaults.js.map +1 -1
  320. package/resources/beta/vaults/vaults.mjs +156 -153
  321. package/resources/beta/vaults/vaults.mjs.map +1 -1
  322. package/resources/completions.d.mts +1 -1
  323. package/resources/completions.d.ts +1 -1
  324. package/resources/index.d.mts +1 -1
  325. package/resources/index.d.mts.map +1 -1
  326. package/resources/index.d.ts +1 -1
  327. package/resources/index.d.ts.map +1 -1
  328. package/resources/index.js.map +1 -1
  329. package/resources/index.mjs.map +1 -1
  330. package/resources/messages/index.d.mts +1 -1
  331. package/resources/messages/index.d.mts.map +1 -1
  332. package/resources/messages/index.d.ts +1 -1
  333. package/resources/messages/index.d.ts.map +1 -1
  334. package/resources/messages/index.js.map +1 -1
  335. package/resources/messages/index.mjs.map +1 -1
  336. package/resources/messages/messages.d.mts +100 -63
  337. package/resources/messages/messages.d.mts.map +1 -1
  338. package/resources/messages/messages.d.ts +100 -63
  339. package/resources/messages/messages.d.ts.map +1 -1
  340. package/resources/messages/messages.js +115 -112
  341. package/resources/messages/messages.js.map +1 -1
  342. package/resources/messages/messages.mjs +115 -112
  343. package/resources/messages/messages.mjs.map +1 -1
  344. package/resources/skills/skills.js +88 -85
  345. package/resources/skills/skills.js.map +1 -1
  346. package/resources/skills/skills.mjs +88 -85
  347. package/resources/skills/skills.mjs.map +1 -1
  348. package/resources/top-level.js +0 -1
  349. package/resources/top-level.js.map +1 -1
  350. package/resources/top-level.mjs +0 -1
  351. package/resources/top-level.mjs.map +1 -1
  352. package/src/client.ts +95 -72
  353. package/src/internal/node.browser.ts +7 -7
  354. package/src/internal/parse.ts +8 -11
  355. package/src/internal/shims.ts +4 -3
  356. package/src/internal/utils/bytes.ts +1 -1
  357. package/src/internal/utils/log.ts +16 -2
  358. package/src/lib/BetaMessageStream.ts +7 -5
  359. package/src/lib/beta-parser.ts +1 -3
  360. package/src/lib/internal/stub.ts +2 -0
  361. package/src/lib/internal/types.ts +2 -0
  362. package/src/lib/middleware.ts +6 -1
  363. package/src/lib/parser.ts +1 -3
  364. package/src/lib/tools/BetaToolRunner.ts +157 -24
  365. package/src/lib/transform-json-schema.ts +8 -6
  366. package/src/resources/beta/beta.ts +24 -1
  367. package/src/resources/beta/deployment-runs.ts +4 -0
  368. package/src/resources/beta/deployments.ts +5 -0
  369. package/src/resources/beta/dreams.ts +19 -28
  370. package/src/resources/beta/index.ts +11 -0
  371. package/src/resources/beta/memory-stores/memories.ts +6 -0
  372. package/src/resources/beta/memory-stores/memory-versions.ts +7 -0
  373. package/src/resources/beta/messages/batches.ts +13 -1
  374. package/src/resources/beta/messages/index.ts +10 -0
  375. package/src/resources/beta/messages/messages.ts +289 -100
  376. package/src/resources/beta/models.ts +25 -0
  377. package/src/resources/beta/organization/index.ts +6 -0
  378. package/src/resources/beta/organization/organization.ts +12 -0
  379. package/src/resources/beta/organization/rate-limits.ts +112 -4
  380. package/src/resources/beta/organization/workspaces/rate-limits.ts +16 -4
  381. package/src/resources/beta/organization/workspaces/workspaces.ts +3 -3
  382. package/src/resources/beta/sessions/events.ts +12 -21
  383. package/src/resources/beta/sessions/resources.ts +0 -3
  384. package/src/resources/beta/sessions/sessions.ts +8 -2
  385. package/src/resources/beta/tunnels/certificates.ts +2 -2
  386. package/src/resources/beta/user-profiles.ts +75 -10
  387. package/src/resources/beta/vaults/credentials.ts +19 -19
  388. package/src/resources/completions.ts +1 -1
  389. package/src/resources/index.ts +6 -0
  390. package/src/resources/messages/index.ts +6 -0
  391. package/src/resources/messages/messages.ts +128 -62
  392. package/src/tsconfig.json +13 -3
  393. package/src/version.ts +1 -1
  394. package/tools/agent-toolset/fs-util.js +0 -6
  395. package/tools/agent-toolset/fs-util.js.map +1 -1
  396. package/tools/agent-toolset/fs-util.mjs +0 -6
  397. package/tools/agent-toolset/fs-util.mjs.map +1 -1
  398. package/tools/agent-toolset/memories.js +4 -4
  399. package/tools/agent-toolset/memories.js.map +1 -1
  400. package/tools/agent-toolset/memories.mjs +2 -2
  401. package/tools/agent-toolset/memories.mjs.map +1 -1
  402. package/tools/agent-toolset/node.browser.js +12 -12
  403. package/tools/agent-toolset/node.browser.js.map +1 -1
  404. package/tools/agent-toolset/node.js +142 -139
  405. package/tools/agent-toolset/node.js.map +1 -1
  406. package/tools/agent-toolset/node.mjs +132 -125
  407. package/tools/agent-toolset/node.mjs.map +1 -1
  408. package/tools/agent-toolset/skills.js +5 -5
  409. package/tools/agent-toolset/skills.js.map +1 -1
  410. package/tools/agent-toolset/sync-interval.js +3 -3
  411. package/tools/agent-toolset/sync-interval.js.map +1 -1
  412. package/tools/memory/node.browser.js +2 -2
  413. package/tools/memory/node.browser.js.map +1 -1
  414. package/version.d.mts +1 -1
  415. package/version.d.ts +1 -1
  416. package/version.js +1 -1
  417. package/version.mjs +1 -1
@@ -92,332 +92,374 @@ export function sessionsTokenFromSecret(secret) {
92
92
  * await client.beta.environments.work.worker({ workdir: '/workspace' }).handleItem();
93
93
  * ```
94
94
  */
95
- export class EnvironmentWorker {
96
- constructor(opts) {
97
- _EnvironmentWorker_instances.add(this);
98
- _EnvironmentWorker_signal.set(this, void 0);
99
- if (opts.unrestrictedPaths !== undefined) {
100
- throw new AnthropicError('The `unrestrictedPaths` option you passed to EnvironmentWorker (or ' +
101
- 'client.beta.environments.work.worker()) is no longer supported. ' +
102
- "The worker's file tools (read, write, edit, glob, grep) are now always confined to `workdir` " +
103
- "plus the session's memory folders. Remove `unrestrictedPaths` from your options; to let the " +
104
- 'file tools reach any other directory, add it to `AgentToolContext.allowedRoots` from a ' +
105
- '`tools` factory.');
106
- }
107
- this.client = opts.client;
108
- this.environmentId = opts.environmentId;
109
- this.environmentKey = opts.environmentKey;
110
- this.tools = opts.tools;
111
- this.workdir = opts.workdir ?? process.cwd();
112
- this.maxFileBytes = opts.maxFileBytes;
113
- this.maxIdleMs = opts.maxIdleMs;
114
- if (opts.memorySyncIntervalMs != null) {
115
- checkMemorySyncInterval(opts.memorySyncIntervalMs, 'memorySyncIntervalMs');
116
- }
117
- this.memorySyncIntervalMs = opts.memorySyncIntervalMs;
118
- this.memorySyncDeletions = opts.memorySyncDeletions ?? 'enabled';
119
- this.workerId = opts.workerId;
120
- this.requestOptions = opts.requestOptions;
121
- __classPrivateFieldSet(this, _EnvironmentWorker_signal, opts.signal, "f");
122
- }
95
+ export var EnvironmentWorker = /* @__PURE__ */ (() => {
123
96
  /**
124
- * Poll the environment and service each claimed session until the supplied
125
- * signal (or the one passed to the constructor) aborts. Throws if
126
- * `environmentId` / `environmentKey` were not provided to the constructor.
97
+ * The self-hosted environment runner, composed from the control-plane
98
+ * {@link WorkPoller} and the per-session {@link SessionToolRunner}.
99
+ *
100
+ * For each claimed `session` work item it: builds the per-session
101
+ * {@link AgentToolContext}, downloads the session agent's skills
102
+ * (`setupSkills`), then runs a {@link SessionToolRunner} for the session
103
+ * while heartbeating the work-item lease on the same event loop; on exit it
104
+ * force-stops the work item (unless the lease was lost, in which case the item
105
+ * is left to whoever holds it now), cleans up the downloaded skills, and loops
106
+ * to the next one. The lease heartbeat reports `state === "stopping"` / a lost
107
+ * lease back into the run by aborting the session runner.
108
+ *
109
+ * The `environmentKey` is the worker's standing credential. When a claimed
110
+ * work item carries a per-item `secret` (a short-lived payload the poll
111
+ * response may populate), the sessions token extracted from it is preferred
112
+ * over the environment key for that item's heartbeat / force-stop /
113
+ * skill-download / session calls; polling itself always uses the environment
114
+ * key, and items without a usable secret fall back to it entirely.
115
+ *
116
+ * Use {@link EnvironmentWorker.handleItem} if you already hold a claimed work
117
+ * item (e.g. a `worker poll --on-work` script handed one to a fresh process) and
118
+ * just want the per-item flow without the poll loop — with no arguments it reads
119
+ * the `ANTHROPIC_*` env vars that command sets.
120
+ *
121
+ * Construct it via `client.beta.environments.work.worker({ ... })` (or
122
+ * `new EnvironmentWorker({ client, ... })` directly).
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * // Long-running daemon: poll for work, serve each session, loop.
127
+ * await client.beta.environments.work
128
+ * .worker({ environmentId, environmentKey, workdir: '/workspace' })
129
+ * .run(AbortSignal.timeout(60 * 60_000));
130
+ *
131
+ * // Already-claimed item (e.g. inside `ant worker poll --on-work ...`):
132
+ * await client.beta.environments.work.worker({ workdir: '/workspace' }).handleItem();
133
+ * ```
127
134
  */
128
- async run(signal) {
129
- const { environmentId, environmentKey } = this;
130
- if (environmentId === undefined || environmentKey === undefined) {
131
- throw new AnthropicError('EnvironmentWorker.run: environmentId and environmentKey are required to poll for work');
135
+ class EnvironmentWorker {
136
+ constructor(opts) {
137
+ _EnvironmentWorker_instances.add(this);
138
+ _EnvironmentWorker_signal.set(this, void 0);
139
+ if (opts.unrestrictedPaths !== undefined) {
140
+ throw new AnthropicError('The `unrestrictedPaths` option you passed to EnvironmentWorker (or ' +
141
+ 'client.beta.environments.work.worker()) is no longer supported. ' +
142
+ "The worker's file tools (read, write, edit, glob, grep) are now always confined to `workdir` " +
143
+ "plus the session's memory folders. Remove `unrestrictedPaths` from your options; to let the " +
144
+ 'file tools reach any other directory, add it to `AgentToolContext.allowedRoots` from a ' +
145
+ '`tools` factory.');
146
+ }
147
+ this.client = opts.client;
148
+ this.environmentId = opts.environmentId;
149
+ this.environmentKey = opts.environmentKey;
150
+ this.tools = opts.tools;
151
+ this.workdir = opts.workdir ?? process.cwd();
152
+ this.maxFileBytes = opts.maxFileBytes;
153
+ this.maxIdleMs = opts.maxIdleMs;
154
+ if (opts.memorySyncIntervalMs != null) {
155
+ checkMemorySyncInterval(opts.memorySyncIntervalMs, 'memorySyncIntervalMs');
156
+ }
157
+ this.memorySyncIntervalMs = opts.memorySyncIntervalMs;
158
+ this.memorySyncDeletions = opts.memorySyncDeletions ?? 'enabled';
159
+ this.workerId = opts.workerId;
160
+ this.requestOptions = opts.requestOptions;
161
+ __classPrivateFieldSet(this, _EnvironmentWorker_signal, opts.signal, "f");
132
162
  }
133
- const externalSignal = signal ?? __classPrivateFieldGet(this, _EnvironmentWorker_signal, "f");
134
- const poller = new WorkPoller({
135
- client: this.client,
136
- environmentId,
137
- environmentKey,
138
- ...(this.workerId !== undefined ? { workerId: this.workerId } : {}),
139
- ...(externalSignal ? { signal: externalSignal } : {}),
140
- ...(this.requestOptions !== undefined ? { requestOptions: this.requestOptions } : {}),
141
- // The per-item handler stops or releases every work item on exit; let it
142
- // be the single owner of `work.stop` rather than double-posting from the
143
- // poller.
144
- autoStop: false,
145
- });
146
- for await (const work of poller) {
147
- try {
148
- await __classPrivateFieldGet(this, _EnvironmentWorker_instances, "m", _EnvironmentWorker_handleItem).call(this, work, environmentKey, poller.signal);
163
+ /**
164
+ * Poll the environment and service each claimed session until the supplied
165
+ * signal (or the one passed to the constructor) aborts. Throws if
166
+ * `environmentId` / `environmentKey` were not provided to the constructor.
167
+ */
168
+ async run(signal) {
169
+ const { environmentId, environmentKey } = this;
170
+ if (environmentId === undefined || environmentKey === undefined) {
171
+ throw new AnthropicError('EnvironmentWorker.run: environmentId and environmentKey are required to poll for work');
149
172
  }
150
- catch (e) {
151
- // One bad item fails that item, not the worker: the handler's teardown
152
- // already stopped or released it, so the next poll claims the next
153
- // item. A store directory left behind by a killed worker would
154
- // otherwise crashloop this process forever.
155
- if (poller.signal?.aborted)
156
- throw e;
157
- loggerFor(this.client).error('work item failed', { work_id: work.id, error: String(e) });
173
+ const externalSignal = signal ?? __classPrivateFieldGet(this, _EnvironmentWorker_signal, "f");
174
+ const poller = new WorkPoller({
175
+ client: this.client,
176
+ environmentId,
177
+ environmentKey,
178
+ ...(this.workerId !== undefined ? { workerId: this.workerId } : {}),
179
+ ...(externalSignal ? { signal: externalSignal } : {}),
180
+ ...(this.requestOptions !== undefined ? { requestOptions: this.requestOptions } : {}),
181
+ // The per-item handler stops or releases every work item on exit; let it
182
+ // be the single owner of `work.stop` rather than double-posting from the
183
+ // poller.
184
+ autoStop: false,
185
+ });
186
+ for await (const work of poller) {
187
+ try {
188
+ await __classPrivateFieldGet(this, _EnvironmentWorker_instances, "m", _EnvironmentWorker_handleItem).call(this, work, environmentKey, poller.signal);
189
+ }
190
+ catch (e) {
191
+ // One bad item fails that item, not the worker: the handler's teardown
192
+ // already stopped or released it, so the next poll claims the next
193
+ // item. A store directory left behind by a killed worker would
194
+ // otherwise crashloop this process forever.
195
+ if (poller.signal?.aborted)
196
+ throw e;
197
+ loggerFor(this.client).error('work item failed', { work_id: work.id, error: String(e) });
198
+ }
199
+ }
200
+ }
201
+ /**
202
+ * Service a single, already-claimed work item without the poll loop: build the
203
+ * per-session {@link AgentToolContext} (workdir from this worker's options),
204
+ * download the session agent's skills (`setupSkills`), run a
205
+ * {@link SessionToolRunner} for the session while heartbeating the work-item
206
+ * lease, and force-stop the work item on exit (whether the runner finishes
207
+ * normally, throws, or the control plane signals shutdown). The one
208
+ * exception is a lost lease: the item then belongs to the queue or another
209
+ * worker and is left alone.
210
+ *
211
+ * Use this when something else does the claiming — e.g. a `worker poll
212
+ * --on-work` script that hands an already-claimed item to a fresh process. The
213
+ * work id / environment id / session id each fall back to `ANTHROPIC_WORK_ID` /
214
+ * `ANTHROPIC_ENVIRONMENT_ID` / `ANTHROPIC_SESSION_ID` (the env vars that
215
+ * command sets) when not passed; the environment key resolves from this
216
+ * option, then the worker's own `environmentKey`, then
217
+ * `ANTHROPIC_ENVIRONMENT_KEY`, and is needed only when the work item's
218
+ * `secret` yields no sessions token — a host that receives only the
219
+ * per-item secret runs without ever holding the key. With no arguments
220
+ * inside that command it just works. Throws a clear error naming the first
221
+ * required value still missing after resolution, and — rather than ever
222
+ * running unauthenticated — when neither a sessions token nor an
223
+ * environment key resolved. Throws `SessionMemoryError` when the
224
+ * session has memory stores attached but they cannot be mounted — the work
225
+ * item carried no sessions token (unless `memorySyncIntervalMs` turned
226
+ * memory off), or a store failed to download.
227
+ *
228
+ * `workSecret` is the work item's per-item `secret` payload from the poll
229
+ * response, falling back to `ANTHROPIC_WORK_SECRET`; unlike the others it is
230
+ * optional — when present, the sessions token extracted from it is preferred
231
+ * as the Bearer credential for this item's heartbeat / force-stop / session
232
+ * calls; when absent (or undecodable) those calls use the environment key.
233
+ */
234
+ async handleItem(opts) {
235
+ const workId = opts?.workId ?? readEnv('ANTHROPIC_WORK_ID');
236
+ const environmentId = opts?.environmentId ?? readEnv('ANTHROPIC_ENVIRONMENT_ID');
237
+ const sessionId = opts?.sessionId ?? readEnv('ANTHROPIC_SESSION_ID');
238
+ // Trailing `|| undefined` / `||` between fallbacks so an empty value reads
239
+ // as absent (matching how `readEnv` treats empty values).
240
+ const environmentKey = (opts?.environmentKey ?? this.environmentKey ?? readEnv('ANTHROPIC_ENVIRONMENT_KEY')) || undefined;
241
+ const workSecret = opts?.workSecret || readEnv('ANTHROPIC_WORK_SECRET') || null;
242
+ if (!workId) {
243
+ throw new AnthropicError('handleItem: workId is required — pass it or set ANTHROPIC_WORK_ID');
244
+ }
245
+ if (!environmentId) {
246
+ throw new AnthropicError('handleItem: environmentId is required — pass it or set ANTHROPIC_ENVIRONMENT_ID');
247
+ }
248
+ if (!sessionId) {
249
+ throw new AnthropicError('handleItem: sessionId is required — pass it or set ANTHROPIC_SESSION_ID');
250
+ }
251
+ if (!environmentKey && !workSecret) {
252
+ throw new AnthropicError('handleItem: environmentKey is required when there is no work secret — pass it, construct the worker with it, or set ANTHROPIC_ENVIRONMENT_KEY');
158
253
  }
254
+ const work = {
255
+ id: workId,
256
+ environment_id: environmentId,
257
+ secret: workSecret,
258
+ data: { type: 'session', id: sessionId },
259
+ };
260
+ await __classPrivateFieldGet(this, _EnvironmentWorker_instances, "m", _EnvironmentWorker_handleItem).call(this, work, environmentKey, opts?.signal ?? __classPrivateFieldGet(this, _EnvironmentWorker_signal, "f"));
159
261
  }
160
262
  }
263
+ _EnvironmentWorker_signal = new WeakMap(), _EnvironmentWorker_instances = new WeakSet(), _EnvironmentWorker_handleItem =
161
264
  /**
162
- * Service a single, already-claimed work item without the poll loop: build the
163
- * per-session {@link AgentToolContext} (workdir from this worker's options),
164
- * download the session agent's skills (`setupSkills`), run a
165
- * {@link SessionToolRunner} for the session while heartbeating the work-item
166
- * lease, and force-stop the work item on exit (whether the runner finishes
167
- * normally, throws, or the control plane signals shutdown). The one
168
- * exception is a lost lease: the item then belongs to the queue or another
169
- * worker and is left alone.
265
+ * The per-item body shared by {@link EnvironmentWorker.run}'s poll loop and
266
+ * {@link EnvironmentWorker.handleItem}: run a {@link SessionToolRunner} for the
267
+ * work item's session while heartbeating its lease, force-stopping on exit
268
+ * unless the lease was lost. Non-session work items are ignored.
170
269
  *
171
- * Use this when something else does the claiming — e.g. a `worker poll
172
- * --on-work` script that hands an already-claimed item to a fresh process. The
173
- * work id / environment id / session id each fall back to `ANTHROPIC_WORK_ID` /
174
- * `ANTHROPIC_ENVIRONMENT_ID` / `ANTHROPIC_SESSION_ID` (the env vars that
175
- * command sets) when not passed; the environment key resolves from this
176
- * option, then the worker's own `environmentKey`, then
177
- * `ANTHROPIC_ENVIRONMENT_KEY`, and is needed only when the work item's
178
- * `secret` yields no sessions token — a host that receives only the
179
- * per-item secret runs without ever holding the key. With no arguments
180
- * inside that command it just works. Throws a clear error naming the first
181
- * required value still missing after resolution, and — rather than ever
182
- * running unauthenticated — when neither a sessions token nor an
183
- * environment key resolved. Throws `SessionMemoryError` when the
184
- * session has memory stores attached but they cannot be mounted — the work
185
- * item carried no sessions token (unless `memorySyncIntervalMs` turned
186
- * memory off), or a store failed to download.
187
- *
188
- * `workSecret` is the work item's per-item `secret` payload from the poll
189
- * response, falling back to `ANTHROPIC_WORK_SECRET`; unlike the others it is
190
- * optional — when present, the sessions token extracted from it is preferred
191
- * as the Bearer credential for this item's heartbeat / force-stop / session
192
- * calls; when absent (or undecodable) those calls use the environment key.
270
+ * When the poll response carried a per-item `secret` (a short-lived payload
271
+ * scoped to this work item), the sessions token extracted from it is
272
+ * preferred over `environmentKey` as the Bearer credential for those
273
+ * per-item calls; a missing/undecodable secret falls back to
274
+ * `environmentKey` unchanged.
193
275
  */
194
- async handleItem(opts) {
195
- const workId = opts?.workId ?? readEnv('ANTHROPIC_WORK_ID');
196
- const environmentId = opts?.environmentId ?? readEnv('ANTHROPIC_ENVIRONMENT_ID');
197
- const sessionId = opts?.sessionId ?? readEnv('ANTHROPIC_SESSION_ID');
198
- // Trailing `|| undefined` / `||` between fallbacks so an empty value reads
199
- // as absent (matching how `readEnv` treats empty values).
200
- const environmentKey = (opts?.environmentKey ?? this.environmentKey ?? readEnv('ANTHROPIC_ENVIRONMENT_KEY')) || undefined;
201
- const workSecret = opts?.workSecret || readEnv('ANTHROPIC_WORK_SECRET') || null;
202
- if (!workId) {
203
- throw new AnthropicError('handleItem: workId is required pass it or set ANTHROPIC_WORK_ID');
204
- }
205
- if (!environmentId) {
206
- throw new AnthropicError('handleItem: environmentId is required — pass it or set ANTHROPIC_ENVIRONMENT_ID');
207
- }
208
- if (!sessionId) {
209
- throw new AnthropicError('handleItem: sessionId is required — pass it or set ANTHROPIC_SESSION_ID');
210
- }
211
- if (!environmentKey && !workSecret) {
212
- throw new AnthropicError('handleItem: environmentKey is required when there is no work secret — pass it, construct the worker with it, or set ANTHROPIC_ENVIRONMENT_KEY');
213
- }
214
- const work = {
215
- id: workId,
216
- environment_id: environmentId,
217
- secret: workSecret,
218
- data: { type: 'session', id: sessionId },
219
- };
220
- await __classPrivateFieldGet(this, _EnvironmentWorker_instances, "m", _EnvironmentWorker_handleItem).call(this, work, environmentKey, opts?.signal ?? __classPrivateFieldGet(this, _EnvironmentWorker_signal, "f"));
221
- }
222
- }
223
- _EnvironmentWorker_signal = new WeakMap(), _EnvironmentWorker_instances = new WeakSet(), _EnvironmentWorker_handleItem =
224
- /**
225
- * The per-item body shared by {@link EnvironmentWorker.run}'s poll loop and
226
- * {@link EnvironmentWorker.handleItem}: run a {@link SessionToolRunner} for the
227
- * work item's session while heartbeating its lease, force-stopping on exit
228
- * unless the lease was lost. Non-session work items are ignored.
229
- *
230
- * When the poll response carried a per-item `secret` (a short-lived payload
231
- * scoped to this work item), the sessions token extracted from it is
232
- * preferred over `environmentKey` as the Bearer credential for those
233
- * per-item calls; a missing/undecodable secret falls back to
234
- * `environmentKey` unchanged.
235
- */
236
- async function _EnvironmentWorker_handleItem(work, environmentKey, externalSignal) {
237
- const log = loggerFor(this.client);
238
- // The per-item credential: the sessions token carried inside the work
239
- // item's secret payload when the server issued one, otherwise the
240
- // environment key. Never log this value.
241
- const sessionsToken = sessionsTokenFromSecret(work.secret);
242
- const itemCredential = sessionsToken ?? environmentKey;
243
- if (itemCredential === undefined) {
244
- throw new AnthropicError('handleItem: the work item carried a secret payload but no sessions token could be extracted, ' +
245
- 'and there is no environment key to fall back to; the poller must issue a secret whose ' +
246
- 'payload carries `sessions_token`, or provide the environment key (pass it, construct the ' +
247
- 'worker with it, or set ANTHROPIC_ENVIRONMENT_KEY)');
248
- }
249
- if (work.secret && sessionsToken === null) {
250
- log.warn('work item carried a secret payload but no sessions token could be extracted; ' +
251
- 'falling back to the environment key', { work_id: work.id });
252
- }
253
- // Every per-session call — the SessionToolRunner event stream/list/send, the
254
- // lease heartbeat, the skill download, and the work force-stop —
255
- // authenticates with the per-item credential. Scope a client to it once and
256
- // thread that through. `copyClientForHelper` also clears the parent's
257
- // `apiKey`, so the sub-client emits *only* the bearer credential on the
258
- // wire (a plain `withOptions({authToken})` would leave `X-Api-Key` set as
259
- // well).
260
- const sessionClient = copyClientForHelper(this.client, {
261
- authToken: itemCredential,
262
- helper: 'environments-worker',
263
- });
264
- // The poller runs with `autoStop: false`, so the per-item handler is the
265
- // single owner of `work.stop` for every claimed item.
266
- const sessionId = work.data.id;
267
- // A per-session controller: aborts when the supplied signal aborts, when the
268
- // session runner finishes, or when the lease heartbeat says to stop.
269
- const ctrl = new AbortController();
270
- const detachExternal = linkAbort(externalSignal, ctrl);
271
- const lease = new Lease(ctrl);
272
- // Lazily load the Node-only toolset module — see the import note at the top.
273
- const agentToolset = await import("../../tools/agent-toolset/node.mjs");
274
- // Start the lease heartbeat BEFORE the session fetch and the skill /
275
- // memory downloads: those can take longer than the lease TTL, and an
276
- // unheartbeated lease lapsing mid-download would let another worker
277
- // reclaim the item and serve the same session (split-brain).
278
- //
279
- // Each heartbeat reports the lease TTL the server is enforcing; it becomes
280
- // the runner's tool-result send retry window so a send keeps retrying
281
- // exactly as long as the lease could still be live. The runner is only
282
- // built after the downloads, so hold the latest TTL until then.
283
- let leaseTtlMs;
284
- let runner;
285
- const heartbeatPromise = heartbeatLoop(sessionClient, work, lease, log, this.requestOptions, (ttlMs) => {
286
- leaseTtlMs = ttlMs;
287
- runner?._setSendRetryWindow(ttlMs);
288
- }).catch((e) => {
289
- if (!ctrl.signal.aborted)
290
- log.error('heartbeat loop failed', { work_id: work.id, error: String(e) });
291
- ctrl.abort();
292
- });
293
- let cleanupSkills = async () => { };
294
- let stores;
295
- let cleanEnd = false;
296
- try {
297
- if (work.data.type !== 'session') {
298
- log.debug('skipping non-session work item', { work_id: work.id, type: work.data.type });
299
- return;
300
- }
301
- // One session fetch, shared by the skills download and the memory-store
302
- // download — two fetches could disagree about the attached resources.
303
- // A failed fetch fails the work item (the teardown below still stops
304
- // or releases it).
305
- const session = await sessionClient.beta.sessions.retrieve(sessionId);
306
- // Only with the session in hand can we tell one that simply has no
307
- // memory from one whose memory we cannot mount. Turning memory off
308
- // with the interval knob is a deliberate opt-out and stays quiet.
309
- if (sessionsToken === null && this.memorySyncIntervalMs !== null && hasMemoryStore(session)) {
310
- throw new agentToolset.SessionMemoryError(`cannot mount the session's memories: the work item carried no sessions token ` +
311
- `(work_id=${work.id}, session_id=${sessionId}); ` +
312
- 'the memory endpoints reject the environment key, so the poller must issue a per-item ' +
313
- '`secret` carrying `sessions_token`, or set `memorySyncIntervalMs: null` to run without memory');
314
- }
315
- const ctx = {
316
- workdir: this.workdir,
317
- // The scoped sub-client, not the parent: the skill download
318
- // `setupSkills` performs for this session rides the same per-item
319
- // credential as every other per-item call.
320
- client: sessionClient,
321
- session,
322
- ...(this.maxFileBytes !== undefined ? { maxFileBytes: this.maxFileBytes } : {}),
323
- };
324
- try {
325
- cleanupSkills = await agentToolset.setupSkills(ctx);
326
- }
327
- catch (e) {
328
- log.warn('skill setup failed', { session_id: sessionId, work_id: work.id, error: String(e) });
329
- }
330
- // Memory stores: the memory_stores endpoints accept the per-item sessions
331
- // token but reject the environment key, so download and sync only run when
332
- // the item carried a usable secret (and the interval is set).
333
- // `sessionClient` is already scoped to that token then, so the memory
334
- // calls ride the same sub-client. A store that cannot be materialised
335
- // throws `SessionMemoryError` out of `download` and fails the item.
336
- if (sessionsToken !== null && this.memorySyncIntervalMs !== null) {
337
- stores = new agentToolset.SessionMemoryStores(sessionClient, {
338
- workdir: this.workdir,
339
- ...(this.memorySyncIntervalMs !== undefined ? { syncIntervalMs: this.memorySyncIntervalMs } : {}),
340
- syncDeletions: this.memorySyncDeletions,
341
- });
342
- await stores.download(session);
343
- // A store mounted outside the workdir must stay reachable by the file
344
- // tools; read-only stores still refuse writes.
345
- ctx.allowedRoots = stores.roots;
346
- ctx.readOnlyRoots = stores.readOnlyRoots;
276
+ async function _EnvironmentWorker_handleItem(work, environmentKey, externalSignal) {
277
+ const log = loggerFor(this.client);
278
+ // The per-item credential: the sessions token carried inside the work
279
+ // item's secret payload when the server issued one, otherwise the
280
+ // environment key. Never log this value.
281
+ const sessionsToken = sessionsTokenFromSecret(work.secret);
282
+ const itemCredential = sessionsToken ?? environmentKey;
283
+ if (itemCredential === undefined) {
284
+ throw new AnthropicError('handleItem: the work item carried a secret payload but no sessions token could be extracted, ' +
285
+ 'and there is no environment key to fall back to; the poller must issue a secret whose ' +
286
+ 'payload carries `sessions_token`, or provide the environment key (pass it, construct the ' +
287
+ 'worker with it, or set ANTHROPIC_ENVIRONMENT_KEY)');
347
288
  }
348
- else {
349
- log.debug('memory stores disabled for this item', { work_id: work.id });
289
+ if (work.secret && sessionsToken === null) {
290
+ log.warn('work item carried a secret payload but no sessions token could be extracted; ' +
291
+ 'falling back to the environment key', { work_id: work.id });
350
292
  }
351
- const tools = typeof this.tools === 'function' ?
352
- this.tools(ctx)
353
- : this.tools ?? agentToolset.betaAgentToolset20260401(ctx);
354
- runner = new SessionToolRunner(sessionId, {
355
- client: sessionClient,
356
- tools,
357
- ...(this.maxIdleMs !== undefined ? { maxIdleMs: this.maxIdleMs } : {}),
358
- ...(this.requestOptions !== undefined ? { requestOptions: this.requestOptions } : {}),
359
- signal: ctrl.signal,
293
+ // Every per-session call the SessionToolRunner event stream/list/send, the
294
+ // lease heartbeat, the skill download, and the work force-stop —
295
+ // authenticates with the per-item credential. Scope a client to it once and
296
+ // thread that through. `copyClientForHelper` also clears the parent's
297
+ // `apiKey`, so the sub-client emits *only* the bearer credential on the
298
+ // wire (a plain `withOptions({authToken})` would leave `X-Api-Key` set as
299
+ // well).
300
+ const sessionClient = copyClientForHelper(this.client, {
301
+ authToken: itemCredential,
302
+ helper: 'environments-worker',
360
303
  });
361
- if (leaseTtlMs !== undefined)
362
- runner._setSendRetryWindow(leaseTtlMs);
363
- for await (const _ of runner) {
364
- // Drive the runner to completion; per-call observability is not part
365
- // of this composition's surface use `SessionToolRunner` directly
366
- // (via `client.beta.sessions.events.toolRunner`) if you want it.
367
- if (stores)
368
- await stores.syncIfDue();
369
- }
370
- // Only a clean stream end earns the last full sync; it runs in the
371
- // teardown below.
372
- cleanEnd = !ctrl.signal.aborted;
373
- }
374
- finally {
375
- // The heartbeat keeps the lease alive until this teardown is done.
304
+ // The poller runs with `autoStop: false`, so the per-item handler is the
305
+ // single owner of `work.stop` for every claimed item.
306
+ const sessionId = work.data.id;
307
+ // A per-session controller: aborts when the supplied signal aborts, when the
308
+ // session runner finishes, or when the lease heartbeat says to stop.
309
+ const ctrl = new AbortController();
310
+ const detachExternal = linkAbort(externalSignal, ctrl);
311
+ const lease = new Lease(ctrl);
312
+ // Lazily load the Node-only toolset module — see the import note at the top.
313
+ const agentToolset = await import("../../tools/agent-toolset/node.mjs");
314
+ // Start the lease heartbeat BEFORE the session fetch and the skill /
315
+ // memory downloads: those can take longer than the lease TTL, and an
316
+ // unheartbeated lease lapsing mid-download would let another worker
317
+ // reclaim the item and serve the same session (split-brain).
318
+ //
319
+ // Each heartbeat reports the lease TTL the server is enforcing; it becomes
320
+ // the runner's tool-result send retry window so a send keeps retrying
321
+ // exactly as long as the lease could still be live. The runner is only
322
+ // built after the downloads, so hold the latest TTL until then.
323
+ let leaseTtlMs;
324
+ let runner;
325
+ const heartbeatPromise = heartbeatLoop(sessionClient, work, lease, log, this.requestOptions, (ttlMs) => {
326
+ leaseTtlMs = ttlMs;
327
+ runner?._setSendRetryWindow(ttlMs);
328
+ }).catch((e) => {
329
+ if (!ctrl.signal.aborted)
330
+ log.error('heartbeat loop failed', { work_id: work.id, error: String(e) });
331
+ ctrl.abort();
332
+ });
333
+ let cleanupSkills = async () => { };
334
+ let stores;
335
+ let cleanEnd = false;
376
336
  try {
377
- // cleanupSkills first, so its failure cannot skip the memory flush.
378
- await cleanupSkills().catch((e) => {
379
- log.warn('skill cleanup failed', { session_id: sessionId, work_id: work.id, error: String(e) });
337
+ if (work.data.type !== 'session') {
338
+ log.debug('skipping non-session work item', { work_id: work.id, type: work.data.type });
339
+ return;
340
+ }
341
+ // One session fetch, shared by the skills download and the memory-store
342
+ // download — two fetches could disagree about the attached resources.
343
+ // A failed fetch fails the work item (the teardown below still stops
344
+ // or releases it).
345
+ const session = await sessionClient.beta.sessions.retrieve(sessionId);
346
+ // Only with the session in hand can we tell one that simply has no
347
+ // memory from one whose memory we cannot mount. Turning memory off
348
+ // with the interval knob is a deliberate opt-out and stays quiet.
349
+ if (sessionsToken === null && this.memorySyncIntervalMs !== null && hasMemoryStore(session)) {
350
+ throw new agentToolset.SessionMemoryError(`cannot mount the session's memories: the work item carried no sessions token ` +
351
+ `(work_id=${work.id}, session_id=${sessionId}); ` +
352
+ 'the memory endpoints reject the environment key, so the poller must issue a per-item ' +
353
+ '`secret` carrying `sessions_token`, or set `memorySyncIntervalMs: null` to run without memory');
354
+ }
355
+ const ctx = {
356
+ workdir: this.workdir,
357
+ // The scoped sub-client, not the parent: the skill download
358
+ // `setupSkills` performs for this session rides the same per-item
359
+ // credential as every other per-item call.
360
+ client: sessionClient,
361
+ session,
362
+ ...(this.maxFileBytes !== undefined ? { maxFileBytes: this.maxFileBytes } : {}),
363
+ };
364
+ try {
365
+ cleanupSkills = await agentToolset.setupSkills(ctx);
366
+ }
367
+ catch (e) {
368
+ log.warn('skill setup failed', { session_id: sessionId, work_id: work.id, error: String(e) });
369
+ }
370
+ // Memory stores: the memory_stores endpoints accept the per-item sessions
371
+ // token but reject the environment key, so download and sync only run when
372
+ // the item carried a usable secret (and the interval is set).
373
+ // `sessionClient` is already scoped to that token then, so the memory
374
+ // calls ride the same sub-client. A store that cannot be materialised
375
+ // throws `SessionMemoryError` out of `download` and fails the item.
376
+ if (sessionsToken !== null && this.memorySyncIntervalMs !== null) {
377
+ stores = new agentToolset.SessionMemoryStores(sessionClient, {
378
+ workdir: this.workdir,
379
+ ...(this.memorySyncIntervalMs !== undefined ? { syncIntervalMs: this.memorySyncIntervalMs } : {}),
380
+ syncDeletions: this.memorySyncDeletions,
381
+ });
382
+ await stores.download(session);
383
+ // A store mounted outside the workdir must stay reachable by the file
384
+ // tools; read-only stores still refuse writes.
385
+ ctx.allowedRoots = stores.roots;
386
+ ctx.readOnlyRoots = stores.readOnlyRoots;
387
+ }
388
+ else {
389
+ log.debug('memory stores disabled for this item', { work_id: work.id });
390
+ }
391
+ const tools = typeof this.tools === 'function' ?
392
+ this.tools(ctx)
393
+ : this.tools ?? agentToolset.betaAgentToolset20260401(ctx);
394
+ runner = new SessionToolRunner(sessionId, {
395
+ client: sessionClient,
396
+ tools,
397
+ ...(this.maxIdleMs !== undefined ? { maxIdleMs: this.maxIdleMs } : {}),
398
+ ...(this.requestOptions !== undefined ? { requestOptions: this.requestOptions } : {}),
399
+ signal: ctrl.signal,
380
400
  });
401
+ if (leaseTtlMs !== undefined)
402
+ runner._setSendRetryWindow(leaseTtlMs);
403
+ for await (const _ of runner) {
404
+ // Drive the runner to completion; per-call observability is not part
405
+ // of this composition's surface — use `SessionToolRunner` directly
406
+ // (via `client.beta.sessions.events.toolRunner`) if you want it.
407
+ if (stores)
408
+ await stores.syncIfDue();
409
+ }
410
+ // Only a clean stream end earns the last full sync; it runs in the
411
+ // teardown below.
412
+ cleanEnd = !ctrl.signal.aborted;
381
413
  }
382
414
  finally {
383
- if (stores) {
384
- const boundMs = agentToolset.MEMORY_FLUSH_TIMEOUT_MS;
385
- if (cleanEnd) {
386
- const finishCutOff = await withTimeout(stores.finish(), boundMs);
387
- if (finishCutOff) {
388
- log.warn(`final memory sync cut off after ${boundMs}ms; the flush that follows still uploads changed files`, { session_id: sessionId, work_id: work.id });
415
+ // The heartbeat keeps the lease alive until this teardown is done.
416
+ try {
417
+ // cleanupSkills first, so its failure cannot skip the memory flush.
418
+ await cleanupSkills().catch((e) => {
419
+ log.warn('skill cleanup failed', { session_id: sessionId, work_id: work.id, error: String(e) });
420
+ });
421
+ }
422
+ finally {
423
+ if (stores) {
424
+ const boundMs = agentToolset.MEMORY_FLUSH_TIMEOUT_MS;
425
+ if (cleanEnd) {
426
+ const finishCutOff = await withTimeout(stores.finish(), boundMs);
427
+ if (finishCutOff) {
428
+ log.warn(`final memory sync cut off after ${boundMs}ms; the flush that follows still uploads changed files`, { session_id: sessionId, work_id: work.id });
429
+ }
389
430
  }
390
- }
391
- // Also after finish(): it swallows its own failures, and a
392
- // clean flush is a no-op.
393
- const flushBound = new AbortController();
394
- const flushCutOff = await withTimeout(stores.flushWrites(flushBound.signal), boundMs);
395
- if (flushCutOff) {
396
- flushBound.abort();
397
- log.warn(`memory flush cut off after ${boundMs}ms; changed files it had not uploaded yet are not saved`, { session_id: sessionId, work_id: work.id });
398
- }
399
- await stores.dispose().catch((e) => {
400
- log.warn('memory store cleanup failed', {
401
- session_id: sessionId,
402
- work_id: work.id,
403
- error: String(e),
431
+ // Also after finish(): it swallows its own failures, and a
432
+ // clean flush is a no-op.
433
+ const flushBound = new AbortController();
434
+ const flushCutOff = await withTimeout(stores.flushWrites(flushBound.signal), boundMs);
435
+ if (flushCutOff) {
436
+ flushBound.abort();
437
+ log.warn(`memory flush cut off after ${boundMs}ms; changed files it had not uploaded yet are not saved`, { session_id: sessionId, work_id: work.id });
438
+ }
439
+ await stores.dispose().catch((e) => {
440
+ log.warn('memory store cleanup failed', {
441
+ session_id: sessionId,
442
+ work_id: work.id,
443
+ error: String(e),
444
+ });
404
445
  });
405
- });
446
+ }
447
+ }
448
+ lease.finish('runner_done');
449
+ detachExternal();
450
+ await heartbeatPromise;
451
+ // Stop only an item this worker still holds — after a lost lease it
452
+ // belongs to the queue or another worker.
453
+ if (lease.lost) {
454
+ log.info('lease lost; released without stopping it', { session_id: sessionId, work_id: work.id });
455
+ }
456
+ else {
457
+ await forceStop(sessionClient, work, log, this.requestOptions);
406
458
  }
407
459
  }
408
- lease.finish('runner_done');
409
- detachExternal();
410
- await heartbeatPromise;
411
- // Stop only an item this worker still holds — after a lost lease it
412
- // belongs to the queue or another worker.
413
- if (lease.lost) {
414
- log.info('lease lost; released without stopping it', { session_id: sessionId, work_id: work.id });
415
- }
416
- else {
417
- await forceStop(sessionClient, work, log, this.requestOptions);
418
- }
419
- }
420
- };
460
+ };
461
+ return EnvironmentWorker;
462
+ })();
421
463
  /**
422
464
  * Resolve when `p` settles or `ms` elapses — `true` when `ms` elapsed
423
465
  * first. A timed-out `p` keeps running — JS cannot cancel a promise.
@@ -452,31 +494,34 @@ async function forceStop(client, work, log, requestOptions) {
452
494
  }
453
495
  }
454
496
  }
455
- /**
456
- * This worker's view of one work-item lease: the per-item abort signal plus
457
- * why heartbeating ended. The first recorded reason wins, so a run aborted
458
- * *because* the lease was lost still reads as lost afterwards; an abort with
459
- * no recorded reason (the external signal) is not lost.
460
- */
461
- class Lease {
462
- constructor(ctrl) {
463
- _Lease_ctrl.set(this, void 0);
464
- _Lease_endReason.set(this, void 0);
465
- __classPrivateFieldSet(this, _Lease_ctrl, ctrl, "f");
466
- }
467
- get signal() {
468
- return __classPrivateFieldGet(this, _Lease_ctrl, "f").signal;
469
- }
470
- finish(reason) {
471
- __classPrivateFieldSet(this, _Lease_endReason, __classPrivateFieldGet(this, _Lease_endReason, "f") ?? reason, "f");
472
- __classPrivateFieldGet(this, _Lease_ctrl, "f").abort();
473
- }
474
- /** True once the item belongs to the queue or another worker. */
475
- get lost() {
476
- return __classPrivateFieldGet(this, _Lease_endReason, "f") === 'lease_lost' || __classPrivateFieldGet(this, _Lease_endReason, "f") === 'assumed_lost';
497
+ var Lease = /* @__PURE__ */ (() => {
498
+ /**
499
+ * This worker's view of one work-item lease: the per-item abort signal plus
500
+ * why heartbeating ended. The first recorded reason wins, so a run aborted
501
+ * *because* the lease was lost still reads as lost afterwards; an abort with
502
+ * no recorded reason (the external signal) is not lost.
503
+ */
504
+ class Lease {
505
+ constructor(ctrl) {
506
+ _Lease_ctrl.set(this, void 0);
507
+ _Lease_endReason.set(this, void 0);
508
+ __classPrivateFieldSet(this, _Lease_ctrl, ctrl, "f");
509
+ }
510
+ get signal() {
511
+ return __classPrivateFieldGet(this, _Lease_ctrl, "f").signal;
512
+ }
513
+ finish(reason) {
514
+ __classPrivateFieldSet(this, _Lease_endReason, __classPrivateFieldGet(this, _Lease_endReason, "f") ?? reason, "f");
515
+ __classPrivateFieldGet(this, _Lease_ctrl, "f").abort();
516
+ }
517
+ /** True once the item belongs to the queue or another worker. */
518
+ get lost() {
519
+ return __classPrivateFieldGet(this, _Lease_endReason, "f") === 'lease_lost' || __classPrivateFieldGet(this, _Lease_endReason, "f") === 'assumed_lost';
520
+ }
477
521
  }
478
- }
479
- _Lease_ctrl = new WeakMap(), _Lease_endReason = new WeakMap();
522
+ _Lease_ctrl = new WeakMap(), _Lease_endReason = new WeakMap();
523
+ return Lease;
524
+ })();
480
525
  /** The server's view of the lease carried by a 412 heartbeat response, or empty if absent. */
481
526
  function serverLeaseState(e) {
482
527
  let node = e instanceof APIError ? e.error : undefined;