@loopingai/core 0.5.0 → 0.6.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 (304) hide show
  1. package/README.md +6 -4
  2. package/dist/a2a/agent-stub.d.ts +0 -1
  3. package/dist/a2a/agent-stub.js +0 -1
  4. package/dist/a2a/caller.d.ts +0 -1
  5. package/dist/a2a/caller.js +0 -1
  6. package/dist/a2a/card.d.ts +0 -1
  7. package/dist/a2a/card.js +0 -1
  8. package/dist/a2a/context.d.ts +0 -1
  9. package/dist/a2a/context.js +0 -1
  10. package/dist/a2a/executor.d.ts +0 -1
  11. package/dist/a2a/executor.js +0 -1
  12. package/dist/a2a/index.d.ts +0 -1
  13. package/dist/a2a/index.js +0 -1
  14. package/dist/a2a/notify.d.ts +4 -4
  15. package/dist/a2a/notify.js +4 -4
  16. package/dist/a2a/parts.d.ts +0 -1
  17. package/dist/a2a/parts.js +0 -1
  18. package/dist/a2a/push.d.ts +0 -1
  19. package/dist/a2a/push.js +0 -1
  20. package/dist/a2a/task-store.d.ts +0 -1
  21. package/dist/a2a/task-store.js +0 -1
  22. package/dist/a2a/task.d.ts +0 -1
  23. package/dist/a2a/task.js +0 -1
  24. package/dist/a2a/verify.d.ts +0 -1
  25. package/dist/a2a/verify.js +0 -1
  26. package/dist/agent/anthropic/index.d.ts +15 -0
  27. package/dist/agent/anthropic/index.js +19 -0
  28. package/dist/agent/anthropic/language-model.d.ts +59 -0
  29. package/dist/agent/anthropic/language-model.js +442 -0
  30. package/dist/agent/anthropic/prompt.d.ts +84 -0
  31. package/dist/agent/anthropic/prompt.js +541 -0
  32. package/dist/agent/anthropic/runtime.d.ts +79 -0
  33. package/dist/agent/anthropic/runtime.js +130 -0
  34. package/dist/agent/budget.d.ts +0 -1
  35. package/dist/agent/budget.js +0 -1
  36. package/dist/agent/control.d.ts +0 -1
  37. package/dist/agent/control.js +10 -10
  38. package/dist/agent/errors.d.ts +85 -0
  39. package/dist/agent/errors.js +64 -0
  40. package/dist/agent/final-reply.d.ts +14 -14
  41. package/dist/agent/final-reply.js +28 -12
  42. package/dist/agent/history.d.ts +3 -4
  43. package/dist/agent/history.js +2 -3
  44. package/dist/agent/index.d.ts +4 -3
  45. package/dist/agent/index.js +4 -3
  46. package/dist/agent/inference.d.ts +58 -2
  47. package/dist/agent/inference.js +44 -1
  48. package/dist/agent/model.d.ts +42 -26
  49. package/dist/agent/model.js +1 -49
  50. package/dist/agent/session.d.ts +6 -8
  51. package/dist/agent/session.js +3 -4
  52. package/dist/agent/workers-ai/index.d.ts +23 -0
  53. package/dist/agent/workers-ai/index.js +23 -0
  54. package/dist/agent/workers-ai/runtime.d.ts +42 -0
  55. package/dist/agent/workers-ai/runtime.js +63 -0
  56. package/dist/config.d.ts +49 -16
  57. package/dist/config.js +30 -2
  58. package/dist/contract/index.d.ts +0 -1
  59. package/dist/contract/index.js +0 -1
  60. package/dist/contract/plugin.d.ts +63 -4
  61. package/dist/contract/plugin.js +76 -1
  62. package/dist/contract/recipe.d.ts +16 -18
  63. package/dist/contract/recipe.js +0 -1
  64. package/dist/contract/validation.d.ts +0 -1
  65. package/dist/contract/validation.js +0 -1
  66. package/dist/db/db.d.ts +0 -2
  67. package/dist/db/db.js +0 -1
  68. package/dist/db/index.d.ts +0 -1
  69. package/dist/db/index.js +0 -1
  70. package/dist/db/migrations/index.d.ts +0 -1
  71. package/dist/db/migrations/index.js +8 -2
  72. package/dist/db/models/subtasks.d.ts +24 -26
  73. package/dist/db/models/subtasks.js +33 -77
  74. package/dist/db/models/tasks.d.ts +0 -1
  75. package/dist/db/models/tasks.js +0 -1
  76. package/dist/db/schema.d.ts +2 -22
  77. package/dist/db/schema.js +2 -5
  78. package/dist/env.d.ts +0 -1
  79. package/dist/env.js +0 -1
  80. package/dist/host/agent.d.ts +58 -5
  81. package/dist/host/agent.js +63 -10
  82. package/dist/host/index.d.ts +0 -1
  83. package/dist/host/index.js +0 -1
  84. package/dist/host/plugin-host.d.ts +0 -1
  85. package/dist/host/plugin-host.js +0 -1
  86. package/dist/index.d.ts +2 -3
  87. package/dist/index.js +2 -3
  88. package/dist/platform.d.ts +74 -12
  89. package/dist/platform.js +76 -14
  90. package/dist/round/agent.d.ts +36 -32
  91. package/dist/round/agent.js +61 -90
  92. package/dist/round/index.d.ts +3 -3
  93. package/dist/round/index.js +2 -3
  94. package/dist/round/policy.d.ts +2 -3
  95. package/dist/round/policy.js +0 -1
  96. package/dist/round/subagent.d.ts +19 -2
  97. package/dist/round/subagent.js +22 -6
  98. package/dist/round/turn.d.ts +32 -14
  99. package/dist/round/turn.js +83 -17
  100. package/dist/round/workflow.d.ts +30 -9
  101. package/dist/round/workflow.js +146 -78
  102. package/dist/runtime/index.d.ts +4 -3
  103. package/dist/runtime/index.js +6 -1
  104. package/dist/runtime/tool-families.d.ts +0 -1
  105. package/dist/runtime/tool-families.js +0 -1
  106. package/dist/subagent/fingerprint.d.ts +2 -3
  107. package/dist/subagent/fingerprint.js +8 -18
  108. package/dist/subagent/index.d.ts +6 -5
  109. package/dist/subagent/index.js +8 -7
  110. package/dist/subagent/prompt.d.ts +4 -6
  111. package/dist/subagent/prompt.js +0 -9
  112. package/dist/subagent/run.d.ts +8 -2
  113. package/dist/subagent/run.js +59 -10
  114. package/dist/subagent/workspace.d.ts +0 -1
  115. package/dist/subagent/workspace.js +0 -1
  116. package/dist/subtasks/catalog.d.ts +1 -2
  117. package/dist/subtasks/catalog.js +1 -2
  118. package/dist/subtasks/decomposition.d.ts +16 -21
  119. package/dist/subtasks/decomposition.js +27 -76
  120. package/dist/subtasks/delegate.d.ts +20 -2
  121. package/dist/subtasks/delegate.js +21 -17
  122. package/dist/subtasks/index.d.ts +1 -3
  123. package/dist/subtasks/index.js +1 -3
  124. package/dist/subtasks/subtask-types.d.ts +0 -9
  125. package/dist/subtasks/subtask-types.js +0 -8
  126. package/dist/subtasks/types.d.ts +45 -71
  127. package/dist/subtasks/types.js +0 -1
  128. package/dist/testing/auth.d.ts +0 -1
  129. package/dist/testing/auth.js +0 -1
  130. package/dist/testing/do.d.ts +0 -1
  131. package/dist/testing/do.js +0 -1
  132. package/dist/testing/fake-session.d.ts +0 -1
  133. package/dist/testing/fake-session.js +0 -1
  134. package/dist/testing/fixtures.d.ts +0 -1
  135. package/dist/testing/fixtures.js +0 -1
  136. package/dist/testing/harness.d.ts +0 -1
  137. package/dist/testing/harness.js +0 -1
  138. package/dist/testing/index.d.ts +0 -1
  139. package/dist/testing/index.js +0 -1
  140. package/dist/testing/mock-model.d.ts +35 -1
  141. package/dist/testing/mock-model.js +75 -1
  142. package/dist/testing/node.d.ts +0 -1
  143. package/dist/testing/node.js +0 -1
  144. package/dist/testing/vcr-global-setup.d.ts +1 -4
  145. package/dist/testing/vcr-global-setup.js +1 -4
  146. package/dist/testing/vcr-shared.d.ts +0 -1
  147. package/dist/testing/vcr-shared.js +0 -1
  148. package/dist/testing/vcr-spec.d.ts +0 -1
  149. package/dist/testing/vcr-spec.js +0 -1
  150. package/dist/testing/vcr-store.d.ts +0 -1
  151. package/dist/testing/vcr-store.js +0 -1
  152. package/dist/testing/vcr.d.ts +0 -1
  153. package/dist/testing/vcr.js +0 -1
  154. package/dist/worker/define-agent.d.ts +0 -1
  155. package/dist/worker/define-agent.js +0 -1
  156. package/dist/worker/index.d.ts +5 -13
  157. package/dist/worker/index.js +5 -13
  158. package/package.json +20 -2
  159. package/dist/a2a/agent-stub.d.ts.map +0 -1
  160. package/dist/a2a/agent-stub.js.map +0 -1
  161. package/dist/a2a/caller.d.ts.map +0 -1
  162. package/dist/a2a/caller.js.map +0 -1
  163. package/dist/a2a/card.d.ts.map +0 -1
  164. package/dist/a2a/card.js.map +0 -1
  165. package/dist/a2a/context.d.ts.map +0 -1
  166. package/dist/a2a/context.js.map +0 -1
  167. package/dist/a2a/executor.d.ts.map +0 -1
  168. package/dist/a2a/executor.js.map +0 -1
  169. package/dist/a2a/index.d.ts.map +0 -1
  170. package/dist/a2a/index.js.map +0 -1
  171. package/dist/a2a/notify.d.ts.map +0 -1
  172. package/dist/a2a/notify.js.map +0 -1
  173. package/dist/a2a/parts.d.ts.map +0 -1
  174. package/dist/a2a/parts.js.map +0 -1
  175. package/dist/a2a/push.d.ts.map +0 -1
  176. package/dist/a2a/push.js.map +0 -1
  177. package/dist/a2a/task-store.d.ts.map +0 -1
  178. package/dist/a2a/task-store.js.map +0 -1
  179. package/dist/a2a/task.d.ts.map +0 -1
  180. package/dist/a2a/task.js.map +0 -1
  181. package/dist/a2a/verify.d.ts.map +0 -1
  182. package/dist/a2a/verify.js.map +0 -1
  183. package/dist/agent/budget.d.ts.map +0 -1
  184. package/dist/agent/budget.js.map +0 -1
  185. package/dist/agent/control.d.ts.map +0 -1
  186. package/dist/agent/control.js.map +0 -1
  187. package/dist/agent/final-reply.d.ts.map +0 -1
  188. package/dist/agent/final-reply.js.map +0 -1
  189. package/dist/agent/history.d.ts.map +0 -1
  190. package/dist/agent/history.js.map +0 -1
  191. package/dist/agent/index.d.ts.map +0 -1
  192. package/dist/agent/index.js.map +0 -1
  193. package/dist/agent/inference.d.ts.map +0 -1
  194. package/dist/agent/inference.js.map +0 -1
  195. package/dist/agent/model.d.ts.map +0 -1
  196. package/dist/agent/model.js.map +0 -1
  197. package/dist/agent/session.d.ts.map +0 -1
  198. package/dist/agent/session.js.map +0 -1
  199. package/dist/config.d.ts.map +0 -1
  200. package/dist/config.js.map +0 -1
  201. package/dist/contract/index.d.ts.map +0 -1
  202. package/dist/contract/index.js.map +0 -1
  203. package/dist/contract/plugin.d.ts.map +0 -1
  204. package/dist/contract/plugin.js.map +0 -1
  205. package/dist/contract/recipe.d.ts.map +0 -1
  206. package/dist/contract/recipe.js.map +0 -1
  207. package/dist/contract/validation.d.ts.map +0 -1
  208. package/dist/contract/validation.js.map +0 -1
  209. package/dist/db/db.d.ts.map +0 -1
  210. package/dist/db/db.js.map +0 -1
  211. package/dist/db/index.d.ts.map +0 -1
  212. package/dist/db/index.js.map +0 -1
  213. package/dist/db/migrations/index.d.ts.map +0 -1
  214. package/dist/db/migrations/index.js.map +0 -1
  215. package/dist/db/models/subtasks.d.ts.map +0 -1
  216. package/dist/db/models/subtasks.js.map +0 -1
  217. package/dist/db/models/tasks.d.ts.map +0 -1
  218. package/dist/db/models/tasks.js.map +0 -1
  219. package/dist/db/schema.d.ts.map +0 -1
  220. package/dist/db/schema.js.map +0 -1
  221. package/dist/env.d.ts.map +0 -1
  222. package/dist/env.js.map +0 -1
  223. package/dist/host/agent.d.ts.map +0 -1
  224. package/dist/host/agent.js.map +0 -1
  225. package/dist/host/index.d.ts.map +0 -1
  226. package/dist/host/index.js.map +0 -1
  227. package/dist/host/plugin-host.d.ts.map +0 -1
  228. package/dist/host/plugin-host.js.map +0 -1
  229. package/dist/index.d.ts.map +0 -1
  230. package/dist/index.js.map +0 -1
  231. package/dist/platform.d.ts.map +0 -1
  232. package/dist/platform.js.map +0 -1
  233. package/dist/round/agent.d.ts.map +0 -1
  234. package/dist/round/agent.js.map +0 -1
  235. package/dist/round/index.d.ts.map +0 -1
  236. package/dist/round/index.js.map +0 -1
  237. package/dist/round/policy.d.ts.map +0 -1
  238. package/dist/round/policy.js.map +0 -1
  239. package/dist/round/subagent.d.ts.map +0 -1
  240. package/dist/round/subagent.js.map +0 -1
  241. package/dist/round/turn.d.ts.map +0 -1
  242. package/dist/round/turn.js.map +0 -1
  243. package/dist/round/workflow.d.ts.map +0 -1
  244. package/dist/round/workflow.js.map +0 -1
  245. package/dist/runtime/index.d.ts.map +0 -1
  246. package/dist/runtime/index.js.map +0 -1
  247. package/dist/runtime/tool-families.d.ts.map +0 -1
  248. package/dist/runtime/tool-families.js.map +0 -1
  249. package/dist/subagent/fingerprint.d.ts.map +0 -1
  250. package/dist/subagent/fingerprint.js.map +0 -1
  251. package/dist/subagent/index.d.ts.map +0 -1
  252. package/dist/subagent/index.js.map +0 -1
  253. package/dist/subagent/prompt.d.ts.map +0 -1
  254. package/dist/subagent/prompt.js.map +0 -1
  255. package/dist/subagent/run.d.ts.map +0 -1
  256. package/dist/subagent/run.js.map +0 -1
  257. package/dist/subagent/workspace.d.ts.map +0 -1
  258. package/dist/subagent/workspace.js.map +0 -1
  259. package/dist/subtasks/catalog.d.ts.map +0 -1
  260. package/dist/subtasks/catalog.js.map +0 -1
  261. package/dist/subtasks/decomposition.d.ts.map +0 -1
  262. package/dist/subtasks/decomposition.js.map +0 -1
  263. package/dist/subtasks/delegate.d.ts.map +0 -1
  264. package/dist/subtasks/delegate.js.map +0 -1
  265. package/dist/subtasks/index.d.ts.map +0 -1
  266. package/dist/subtasks/index.js.map +0 -1
  267. package/dist/subtasks/scheduler.d.ts +0 -49
  268. package/dist/subtasks/scheduler.d.ts.map +0 -1
  269. package/dist/subtasks/scheduler.js +0 -48
  270. package/dist/subtasks/scheduler.js.map +0 -1
  271. package/dist/subtasks/subtask-types.d.ts.map +0 -1
  272. package/dist/subtasks/subtask-types.js.map +0 -1
  273. package/dist/subtasks/types.d.ts.map +0 -1
  274. package/dist/subtasks/types.js.map +0 -1
  275. package/dist/testing/auth.d.ts.map +0 -1
  276. package/dist/testing/auth.js.map +0 -1
  277. package/dist/testing/do.d.ts.map +0 -1
  278. package/dist/testing/do.js.map +0 -1
  279. package/dist/testing/fake-session.d.ts.map +0 -1
  280. package/dist/testing/fake-session.js.map +0 -1
  281. package/dist/testing/fixtures.d.ts.map +0 -1
  282. package/dist/testing/fixtures.js.map +0 -1
  283. package/dist/testing/harness.d.ts.map +0 -1
  284. package/dist/testing/harness.js.map +0 -1
  285. package/dist/testing/index.d.ts.map +0 -1
  286. package/dist/testing/index.js.map +0 -1
  287. package/dist/testing/mock-model.d.ts.map +0 -1
  288. package/dist/testing/mock-model.js.map +0 -1
  289. package/dist/testing/node.d.ts.map +0 -1
  290. package/dist/testing/node.js.map +0 -1
  291. package/dist/testing/vcr-global-setup.d.ts.map +0 -1
  292. package/dist/testing/vcr-global-setup.js.map +0 -1
  293. package/dist/testing/vcr-shared.d.ts.map +0 -1
  294. package/dist/testing/vcr-shared.js.map +0 -1
  295. package/dist/testing/vcr-spec.d.ts.map +0 -1
  296. package/dist/testing/vcr-spec.js.map +0 -1
  297. package/dist/testing/vcr-store.d.ts.map +0 -1
  298. package/dist/testing/vcr-store.js.map +0 -1
  299. package/dist/testing/vcr.d.ts.map +0 -1
  300. package/dist/testing/vcr.js.map +0 -1
  301. package/dist/worker/define-agent.d.ts.map +0 -1
  302. package/dist/worker/define-agent.js.map +0 -1
  303. package/dist/worker/index.d.ts.map +0 -1
  304. package/dist/worker/index.js.map +0 -1
@@ -0,0 +1,130 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import { createAnthropicLanguageModel } from "./language-model.js";
3
+ /**
4
+ * The beta Anthropic requires to accept a bearer credential rather than an
5
+ * `x-api-key`.
6
+ */
7
+ const OAUTH_BETA = "oauth-2025-04-20";
8
+ /**
9
+ * AI Gateway's per-request log metadata header.
10
+ *
11
+ * Core already stamps `{taskId, round}` on a turn and `{taskId, subtaskId}` on a
12
+ * subagent chunk so a model call can be tied back to the work that made it; the
13
+ * Workers AI provider carries that in its settings object. Anthropic has no such
14
+ * field, so it rides as a header instead — same correlation, different envelope.
15
+ * Capped at five entries by the gateway; extra keys are dropped there, so trim
16
+ * here rather than sending something that silently truncates.
17
+ */
18
+ const GATEWAY_METADATA_HEADER = "cf-aig-metadata";
19
+ const GATEWAY_METADATA_MAX_ENTRIES = 5;
20
+ /**
21
+ * AI Gateway's own authorization header — deliberately *not* `Authorization`,
22
+ * which already carries the model provider's credential on the same request.
23
+ * Two independent authorities, two headers.
24
+ *
25
+ * A client header rather than a per-pair one: it authenticates the caller to the
26
+ * gateway, which does not vary by task or round, unlike
27
+ * {@link GATEWAY_METADATA_HEADER}.
28
+ */
29
+ const GATEWAY_AUTH_HEADER = "cf-aig-authorization";
30
+ function metadataHeaders(metadata) {
31
+ if (!metadata)
32
+ return {};
33
+ const entries = Object.entries(metadata).slice(0, GATEWAY_METADATA_MAX_ENTRIES);
34
+ if (entries.length === 0)
35
+ return {};
36
+ return {
37
+ [GATEWAY_METADATA_HEADER]: JSON.stringify(Object.fromEntries(entries))
38
+ };
39
+ }
40
+ export function createAnthropicModelRuntime(deps) {
41
+ const { config } = deps;
42
+ /**
43
+ * The resolved base URL, memoized — **not** the client.
44
+ *
45
+ * Resolving is what is expensive and what must not happen at module scope:
46
+ * `wrangler deploy` evaluates module scope to validate the new version and
47
+ * bindings are unpopulated at that point, so an eager `baseUrl()` would throw
48
+ * during deploy. That argument is about the *URL*, which is why it is the URL
49
+ * that is cached.
50
+ *
51
+ * Assigned only on success, so a failed gateway lookup is retried on the next
52
+ * round rather than cached as a rejected promise for the life of the isolate.
53
+ * Two concurrent first calls may each resolve one; they are identical, and
54
+ * the cost is a spare string.
55
+ */
56
+ let resolvedBaseUrl;
57
+ /**
58
+ * A client per call, deliberately.
59
+ *
60
+ * This used to memoize the `Anthropic` instance, which bakes the credential
61
+ * in at construction. That is correct only while the credential outlives the
62
+ * isolate. It does not when {@link AnthropicRuntimeDeps.authToken} mints a
63
+ * short-lived token per request: the first call succeeds, and every call
64
+ * after the token's lifetime gets a `401` — intermittently, only under
65
+ * sustained load, and pointing at the wrong secret.
66
+ *
67
+ * Rebuilding is close to free. `new Anthropic({...})` is pure config
68
+ * assembly — no network, no handshake — so the per-call cost is an object
69
+ * allocation, against a correctness bug that only appears in production.
70
+ * The per-pair headers ride on the request rather than the client, so nothing
71
+ * else depended on the instance being shared.
72
+ */
73
+ const clientFor = async () => {
74
+ if (deps.clientOverride)
75
+ return deps.clientOverride;
76
+ // Awaited, not cast. `env.AI.gateway(id).getUrl()` returns a PROMISE:
77
+ // handing it to `baseURL` unresolved type-checks only behind an `as
78
+ // string`, then fails deep inside the SDK on `baseURL.endsWith is not a
79
+ // function`, on every request, with nothing naming the gateway. The await
80
+ // is why this thunk is async and why `client` is awaited at the call site.
81
+ resolvedBaseUrl ??= await deps.baseUrl();
82
+ const gatewayToken = deps.gatewayToken?.();
83
+ return new Anthropic({
84
+ authToken: await deps.authToken(),
85
+ // Explicitly null, or the SDK falls back to resolving credentials from
86
+ // config files and env vars — which on Workers means a confusing failure
87
+ // far from the actual misconfiguration.
88
+ apiKey: null,
89
+ baseURL: resolvedBaseUrl,
90
+ defaultHeaders: {
91
+ "anthropic-beta": OAUTH_BETA,
92
+ ...(gatewayToken
93
+ ? { [GATEWAY_AUTH_HEADER]: `Bearer ${gatewayToken}` }
94
+ : {})
95
+ },
96
+ // Retry lives one layer up, in the AI SDK, which is the only layer that
97
+ // honours the provider's own `retry-after` — see `ModelConfig.maxRetries`
98
+ // and the `APICallError` mapping that feeds it. A second layer here would
99
+ // multiply that wait and defeat the fallback's timing.
100
+ maxRetries: 0
101
+ });
102
+ };
103
+ return {
104
+ createModelPair(overrides = {}) {
105
+ const primaryId = overrides.primaryModelId ?? config.chatModelId;
106
+ const fallbackId = overrides.fallbackModelId ?? config.fallbackChatModelId;
107
+ const headers = metadataHeaders(overrides.metadata);
108
+ const build = (modelId) => createAnthropicLanguageModel({
109
+ client: clientFor,
110
+ modelId,
111
+ defaultMaxTokens: config.maxOutputTokens,
112
+ ...(deps.effort ? { effort: deps.effort } : {}),
113
+ ...(deps.cache !== undefined ? { cache: deps.cache } : {}),
114
+ ...(deps.classifyAuthFailure
115
+ ? { classifyAuthFailure: deps.classifyAuthFailure }
116
+ : {}),
117
+ headers
118
+ });
119
+ let primary;
120
+ let fallback;
121
+ return {
122
+ primary: () => (primary ??= overrides.model ?? build(primaryId)),
123
+ fallback: () => (fallback ??=
124
+ overrides.fallbackModel ?? overrides.model ?? build(fallbackId)),
125
+ primaryId: () => primaryId,
126
+ fallbackId: () => fallbackId
127
+ };
128
+ }
129
+ };
130
+ }
@@ -44,4 +44,3 @@ export declare const newTurnBudget: (allowance: number) => TurnBudget;
44
44
  * attempt as the only one that can ever begin overdrawn.
45
45
  */
46
46
  export declare const stepAllowance: (maxTurns: number, spent: number) => number;
47
- //# sourceMappingURL=budget.d.ts.map
@@ -40,4 +40,3 @@ export const newTurnBudget = (allowance) => ({
40
40
  * attempt as the only one that can ever begin overdrawn.
41
41
  */
42
42
  export const stepAllowance = (maxTurns, spent) => Math.max(1, maxTurns - spent);
43
- //# sourceMappingURL=budget.js.map
@@ -107,4 +107,3 @@ export declare function controlTools(opts: {
107
107
  }): ControlTool[];
108
108
  /** The tools as the SDK takes them, in declaration order. */
109
109
  export declare function controlToolSet(tools: ControlTool[]): ToolSet;
110
- //# sourceMappingURL=control.d.ts.map
@@ -64,9 +64,8 @@ export function controlTools(opts) {
64
64
  if (!parsed.success) {
65
65
  throw new ControlCallError(`${DELEGATE_TOOL_NAME} input is invalid — ${issues(parsed.error)}`);
66
66
  }
67
- // Everything past the schema — unknown reference indexes, dependency
68
- // cycles, a type's required params — throws its own error, already worded
69
- // for the model.
67
+ // Everything past the schema — unknown reference indexes, a type's
68
+ // required params — throws its own error, already worded for the model.
70
69
  const { reply, drafts } = resolveDecomposition({
71
70
  ...parsed.data,
72
71
  subtasks: parsed.data.subtasks.map((s) => ({
@@ -84,11 +83,12 @@ export function controlTools(opts) {
84
83
  * Drop params the model sent as an explicit `undefined`.
85
84
  *
86
85
  * The delegate schema declares the union of every type's param keys, all optional,
87
- * so one tool schema can serve every type (see `subtaskParamProperties`). A model
88
- * that names a key and leaves it empty has sent no param, and forwarding the key
89
- * with an `undefined` value would only make a missing required param report itself
90
- * as a *present* one. Whether what survives satisfies the type is still
91
- * `validateSubtaskParams`'s call, downstream.
86
+ * so one tool schema can serve every type (see
87
+ * `SubtaskTypeRegistry.paramProperties`). A model that names a key and leaves it
88
+ * empty has sent no param, and forwarding the key with an `undefined` value would
89
+ * only make a missing required param report itself as a *present* one. Whether
90
+ * what survives satisfies the type is still
91
+ * `SubtaskTypeRegistry.validateParams`'s call, downstream.
92
92
  */
93
93
  function definedParams(params) {
94
94
  if (!params)
@@ -100,7 +100,8 @@ function definedParams(params) {
100
100
  }
101
101
  /**
102
102
  * A zod failure as one line the model can act on: which field, and what was wrong.
103
- * The same rendering {@link file://./subtasks/subtask-types.ts validateSubtaskParams}
103
+ * The same rendering
104
+ * {@link file://../subtasks/subtask-types.ts SubtaskTypeRegistry.validateParams}
104
105
  * uses, so every rejection a control call can produce reads the same way.
105
106
  */
106
107
  function issues(error) {
@@ -112,4 +113,3 @@ function issues(error) {
112
113
  export function controlToolSet(tools) {
113
114
  return Object.fromEntries(tools.map((c) => [c.name, c.tool]));
114
115
  }
115
- //# sourceMappingURL=control.js.map
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Failures the loops must treat specially, whichever provider raised them.
3
+ *
4
+ * A sibling of {@link file://./model.ts model.ts} and neutral for the same
5
+ * reason: a provider directory may throw these, and nothing here may know that
6
+ * any particular one exists. `nonRecoverableKind` in
7
+ * {@link file://./inference.ts inference.ts} keys on this file, so a provider
8
+ * written outside core — the thing `ModelRuntimeFactory` exists to make cheap —
9
+ * gets the same handling as `agent/anthropic` with no change to core.
10
+ *
11
+ * ## Why a third classification was needed at all
12
+ *
13
+ * Core's attempt ladder splits every failure two ways — transient conditions
14
+ * throw out so the Workflow step retries the whole round, everything else burns
15
+ * the model slot and hands over to the fallback (see
16
+ * {@link file://./inference.ts isTransientAiError}). An expired credential fits
17
+ * neither: retrying spends the Workflow's budget on a request that can never
18
+ * succeed, and falling back spends the second slot on the *same* rejected token.
19
+ * It has to stop the round and say what a human must do.
20
+ *
21
+ * Note that being non-transient is not enough on its own — "not transient" is
22
+ * precisely the signal that means "try the fallback".
23
+ */
24
+ /**
25
+ * Who refused the request, when a `401` came back.
26
+ *
27
+ * There can be up to three authorities on the path, each with its own
28
+ * credential: the AI Gateway (`cf-aig-authorization`), an optional intermediary
29
+ * a deployment puts between the gateway and the provider (`"proxy"`), and the
30
+ * model provider itself (`Authorization`). They fail with the same status code
31
+ * and completely different remedies, so a rejection that does not say which one
32
+ * it was sends an operator to rotate the wrong secret — which is exactly what
33
+ * happened before this existed.
34
+ *
35
+ * `"proxy"` is the odd one out: it is generally *not* a secret to rotate. An
36
+ * intermediary that mints its caller credential per request fails for reasons
37
+ * upstream of any stored secret — configuration drift, a rotated signing key,
38
+ * clock skew — so the remedy is to look, not to rotate. Core recognises no
39
+ * particular intermediary; a deployment that has one supplies its own classifier
40
+ * (see `AnthropicModelDeps.classifyAuthFailure`).
41
+ *
42
+ * `"unknown"` is a real answer and the default. Guessing `"provider"` for an
43
+ * unrecognised body is how the misdiagnosis happens; saying "one of these, here
44
+ * is how to check each" is worse copy and better information.
45
+ */
46
+ export type CredentialRejectedBy = "provider" | "gateway" | "proxy" | "unknown";
47
+ /**
48
+ * A credential on the path to the model was rejected (HTTP 401 / 403).
49
+ *
50
+ * Deliberately not an `APICallError`: the AI SDK's classifier treats those as
51
+ * potentially retryable, and this never is.
52
+ * {@link file://./inference.ts nonRecoverableKind} maps it to one of the
53
+ * credential kinds — which one depends on {@link source} — and that is what
54
+ * stops the round before the fallback slot; `isTransientAiError` additionally
55
+ * returns `false` so the message text can never be mistaken for a rate limit.
56
+ *
57
+ * The round then fails carrying that kind, and the host supplies the
58
+ * operator-facing copy through `HandleTaskDeps.failureCopy` — core owns the
59
+ * signal and the delivery, never the wording.
60
+ */
61
+ export declare class CredentialRejectedError extends Error {
62
+ readonly name = "CredentialRejectedError";
63
+ /** The upstream status, when one was available. */
64
+ readonly status: number | undefined;
65
+ /** Which authority rejected it. See {@link CredentialRejectedBy}. */
66
+ readonly source: CredentialRejectedBy;
67
+ constructor(message: string, options?: {
68
+ status?: number;
69
+ source?: CredentialRejectedBy;
70
+ cause?: unknown;
71
+ });
72
+ /**
73
+ * Structural check rather than `instanceof`.
74
+ *
75
+ * A Worker bundle can end up with two copies of this module (core linked as a
76
+ * tarball while a plugin resolves its own), and `instanceof` fails across
77
+ * them — the same realm hazard `AGENTS.md` calls out for `agents`. The name is
78
+ * a readonly literal, so this is as strong in practice and survives bundling.
79
+ *
80
+ * It is also what lets a provider outside core raise one: anything named
81
+ * `CredentialRejectedError` with a `source` is honoured, no shared class
82
+ * identity required.
83
+ */
84
+ static isInstance(err: unknown): err is CredentialRejectedError;
85
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Failures the loops must treat specially, whichever provider raised them.
3
+ *
4
+ * A sibling of {@link file://./model.ts model.ts} and neutral for the same
5
+ * reason: a provider directory may throw these, and nothing here may know that
6
+ * any particular one exists. `nonRecoverableKind` in
7
+ * {@link file://./inference.ts inference.ts} keys on this file, so a provider
8
+ * written outside core — the thing `ModelRuntimeFactory` exists to make cheap —
9
+ * gets the same handling as `agent/anthropic` with no change to core.
10
+ *
11
+ * ## Why a third classification was needed at all
12
+ *
13
+ * Core's attempt ladder splits every failure two ways — transient conditions
14
+ * throw out so the Workflow step retries the whole round, everything else burns
15
+ * the model slot and hands over to the fallback (see
16
+ * {@link file://./inference.ts isTransientAiError}). An expired credential fits
17
+ * neither: retrying spends the Workflow's budget on a request that can never
18
+ * succeed, and falling back spends the second slot on the *same* rejected token.
19
+ * It has to stop the round and say what a human must do.
20
+ *
21
+ * Note that being non-transient is not enough on its own — "not transient" is
22
+ * precisely the signal that means "try the fallback".
23
+ */
24
+ /**
25
+ * A credential on the path to the model was rejected (HTTP 401 / 403).
26
+ *
27
+ * Deliberately not an `APICallError`: the AI SDK's classifier treats those as
28
+ * potentially retryable, and this never is.
29
+ * {@link file://./inference.ts nonRecoverableKind} maps it to one of the
30
+ * credential kinds — which one depends on {@link source} — and that is what
31
+ * stops the round before the fallback slot; `isTransientAiError` additionally
32
+ * returns `false` so the message text can never be mistaken for a rate limit.
33
+ *
34
+ * The round then fails carrying that kind, and the host supplies the
35
+ * operator-facing copy through `HandleTaskDeps.failureCopy` — core owns the
36
+ * signal and the delivery, never the wording.
37
+ */
38
+ export class CredentialRejectedError extends Error {
39
+ name = "CredentialRejectedError";
40
+ /** The upstream status, when one was available. */
41
+ status;
42
+ /** Which authority rejected it. See {@link CredentialRejectedBy}. */
43
+ source;
44
+ constructor(message, options) {
45
+ super(message, { cause: options?.cause });
46
+ this.status = options?.status;
47
+ this.source = options?.source ?? "unknown";
48
+ }
49
+ /**
50
+ * Structural check rather than `instanceof`.
51
+ *
52
+ * A Worker bundle can end up with two copies of this module (core linked as a
53
+ * tarball while a plugin resolves its own), and `instanceof` fails across
54
+ * them — the same realm hazard `AGENTS.md` calls out for `agents`. The name is
55
+ * a readonly literal, so this is as strong in practice and survives bundling.
56
+ *
57
+ * It is also what lets a provider outside core raise one: anything named
58
+ * `CredentialRejectedError` with a `source` is honoured, no shared class
59
+ * identity required.
60
+ */
61
+ static isInstance(err) {
62
+ return err instanceof Error && err.name === "CredentialRejectedError";
63
+ }
64
+ }
@@ -1,3 +1,4 @@
1
+ import { type Tool } from "ai";
1
2
  import { z } from "zod";
2
3
  /**
3
4
  * The `final_reply` tool — the main agent answering the user itself, and the other
@@ -12,7 +13,7 @@ import { z } from "zod";
12
13
  * So prose is no longer an outcome. Both endings are now named tools, the round runs
13
14
  * with `toolChoice: "required"`, and a round that ends any other way has failed its
14
15
  * attempt. The *choice* is still entirely the model's — the point of the design (see
15
- * {@link file://./turn.ts turn.ts}) was never that the model be steered toward
16
+ * {@link file://../round/turn.ts turn.ts}) was never that the model be steered toward
16
17
  * delegating, only that it not be forced. Picking between two named tools is also a
17
18
  * far easier discrimination for a small model than picking between prose and a tool,
18
19
  * which is what the weaker fallback models kept getting wrong.
@@ -20,16 +21,6 @@ import { z } from "zod";
20
21
  * This lives outside `subtasks/` deliberately: replying is not a subtask concept.
21
22
  */
22
23
  export declare const FINAL_REPLY_TOOL_NAME = "final_reply";
23
- /**
24
- * The tool as the model sees it. **Without `execute`**, exactly like
25
- * {@link file://./subtasks/delegate.ts delegateTool}: the call *is* the round's
26
- * output, so there is nothing for the SDK to run and the loop halts on it.
27
- *
28
- * Unlike `delegate`, this call is never reconstructed in a later round's history —
29
- * a past reply is stored as, and replayed as, ordinary assistant text (history is
30
- * text-only by design). The tool exists to constrain *generation*, not to become a
31
- * new shape in the transcript.
32
- */
33
24
  /**
34
25
  * The call's input, exported as the zod schema rather than only as the tool's
35
26
  * `inputSchema`, because the round has to run it itself.
@@ -43,7 +34,16 @@ export declare const FINAL_REPLY_TOOL_NAME = "final_reply";
43
34
  export declare const finalReplyInputSchema: z.ZodObject<{
44
35
  text: z.ZodString;
45
36
  }, z.core.$strip>;
46
- export declare const finalReplyTool: import("ai").Tool<{
37
+ /**
38
+ * The tool as the model sees it. **Without `execute`**, exactly like
39
+ * {@link file://../subtasks/delegate.ts delegateTool}: the call *is* the round's
40
+ * output, so there is nothing for the SDK to run and the loop halts on it.
41
+ *
42
+ * Unlike `delegate`, this call is never reconstructed in a later round's history —
43
+ * a past reply is stored as, and replayed as, ordinary assistant text (history is
44
+ * text-only by design). The tool exists to constrain *generation*, not to become a
45
+ * new shape in the transcript.
46
+ */
47
+ export declare const finalReplyTool: Tool<{
47
48
  text: string;
48
- }, never, import("@ai-sdk/provider-utils").Context>;
49
- //# sourceMappingURL=final-reply.d.ts.map
49
+ }>;
@@ -14,7 +14,7 @@ import { nonBlank } from "../subtasks/decomposition.js";
14
14
  * So prose is no longer an outcome. Both endings are now named tools, the round runs
15
15
  * with `toolChoice: "required"`, and a round that ends any other way has failed its
16
16
  * attempt. The *choice* is still entirely the model's — the point of the design (see
17
- * {@link file://./turn.ts turn.ts}) was never that the model be steered toward
17
+ * {@link file://../round/turn.ts turn.ts}) was never that the model be steered toward
18
18
  * delegating, only that it not be forced. Picking between two named tools is also a
19
19
  * far easier discrimination for a small model than picking between prose and a tool,
20
20
  * which is what the weaker fallback models kept getting wrong.
@@ -22,16 +22,6 @@ import { nonBlank } from "../subtasks/decomposition.js";
22
22
  * This lives outside `subtasks/` deliberately: replying is not a subtask concept.
23
23
  */
24
24
  export const FINAL_REPLY_TOOL_NAME = "final_reply";
25
- /**
26
- * The tool as the model sees it. **Without `execute`**, exactly like
27
- * {@link file://./subtasks/delegate.ts delegateTool}: the call *is* the round's
28
- * output, so there is nothing for the SDK to run and the loop halts on it.
29
- *
30
- * Unlike `delegate`, this call is never reconstructed in a later round's history —
31
- * a past reply is stored as, and replayed as, ordinary assistant text (history is
32
- * text-only by design). The tool exists to constrain *generation*, not to become a
33
- * new shape in the transcript.
34
- */
35
25
  /**
36
26
  * The call's input, exported as the zod schema rather than only as the tool's
37
27
  * `inputSchema`, because the round has to run it itself.
@@ -45,8 +35,34 @@ export const FINAL_REPLY_TOOL_NAME = "final_reply";
45
35
  export const finalReplyInputSchema = z.object({
46
36
  text: nonBlank("text").describe("Your reply, in your own voice. This is shown to the user verbatim, so it must be the complete answer and must not be blank.")
47
37
  });
38
+ /**
39
+ * The tool as the model sees it. **Without `execute`**, exactly like
40
+ * {@link file://../subtasks/delegate.ts delegateTool}: the call *is* the round's
41
+ * output, so there is nothing for the SDK to run and the loop halts on it.
42
+ *
43
+ * Unlike `delegate`, this call is never reconstructed in a later round's history —
44
+ * a past reply is stored as, and replayed as, ordinary assistant text (history is
45
+ * text-only by design). The tool exists to constrain *generation*, not to become a
46
+ * new shape in the transcript.
47
+ */
48
+ /*
49
+ * Annotated, not inferred, and the annotation is a **packaging** constraint
50
+ * rather than a style choice.
51
+ *
52
+ * `tool()` returns `Tool<Input, Output, Context>`, and `Context` lives in
53
+ * `@ai-sdk/provider-utils` — an internal of `ai`, which resolves it as a nested
54
+ * copy. Left inferred, `tsc` emits `import("@ai-sdk/provider-utils").Context`
55
+ * into this module's `.d.ts`, so every consumer typechecking
56
+ * `@loopingai/core/agent` needs a package this one does not declare and cannot
57
+ * usefully declare: pinning it here installs a *second*, different major
58
+ * alongside `ai`'s own, and TypeScript then refuses the reference outright as
59
+ * unportable.
60
+ *
61
+ * Naming the type through `ai`'s own re-export keeps the emitted declaration
62
+ * pointing at a package that is already a required peer. `verify:exports` walks
63
+ * the declaration graph for exactly this.
64
+ */
48
65
  export const finalReplyTool = tool({
49
66
  description: "Answer the user and end this round. Use this whenever the request is yours to answer — anything about this conversation, your own history, memory, or tools, and anything you can settle with the tools available to you here, including work that has already come back to you.",
50
67
  inputSchema: finalReplyInputSchema
51
68
  });
52
- //# sourceMappingURL=final-reply.js.map
@@ -3,7 +3,7 @@ import type { SessionMessage } from "agents/experimental/memory/session";
3
3
  /**
4
4
  * Session-history glue for the agent runtime: parse the gateway-authored `<turn>`
5
5
  * provenance wrapper, and bridge between plain text and the Agents-SDK Sessions
6
- * store. No A2A types cross this boundary — the {@link file://../a2a/inbound.ts
6
+ * store. No A2A types cross this boundary — the {@link file://../a2a/parts.ts
7
7
  * A2A adapter} has already reduced the inbound message to a plain string.
8
8
  *
9
9
  * The gateway inlines a `<turn from="…" id="…" channel="…" at="…">…</turn>` tag
@@ -53,8 +53,8 @@ export declare function taskUserMessageId(taskId: string): string;
53
53
  * Id of the acknowledgment a **delegating** round publishes — the message the
54
54
  * user sees while that round's Subtasks run. Also the anchor a later round finds
55
55
  * to reattach the round's `delegate` call to (see
56
- * {@link file://./turn.ts renderTurnMessages}), which is why it is derived from
57
- * the round rather than stored.
56
+ * {@link file://../round/turn.ts renderTurnMessages}), which is why it is
57
+ * derived from the round rather than stored.
58
58
  */
59
59
  export declare function roundAckMessageId(taskId: string, round: number): string;
60
60
  /**
@@ -95,4 +95,3 @@ export declare function sessionMessage(role: "user" | "assistant", text: string)
95
95
  export declare function sessionText(m: SessionMessage): string;
96
96
  /** Convert stored history to AI-SDK model messages (user/assistant text only). */
97
97
  export declare function toModelMessages(history: SessionMessage[]): ModelMessage[];
98
- //# sourceMappingURL=history.d.ts.map
@@ -61,8 +61,8 @@ export function taskUserMessageId(taskId) {
61
61
  * Id of the acknowledgment a **delegating** round publishes — the message the
62
62
  * user sees while that round's Subtasks run. Also the anchor a later round finds
63
63
  * to reattach the round's `delegate` call to (see
64
- * {@link file://./turn.ts renderTurnMessages}), which is why it is derived from
65
- * the round rather than stored.
64
+ * {@link file://../round/turn.ts renderTurnMessages}), which is why it is
65
+ * derived from the round rather than stored.
66
66
  */
67
67
  export function roundAckMessageId(taskId, round) {
68
68
  return `task:${taskId}:round:${round}:ack`;
@@ -131,4 +131,3 @@ export function toModelMessages(history) {
131
131
  content: sessionText(m)
132
132
  }));
133
133
  }
134
- //# sourceMappingURL=history.js.map
@@ -19,10 +19,11 @@
19
19
  * exactly what is here.
20
20
  */
21
21
  export { newTurnBudget, stepAllowance, type TurnBudget } from "./budget.js";
22
- export { createModelRuntime, type GatewayMetadata, type ModelOverrides, type ModelPair, type ModelRuntime, type ModelRuntimeDeps } from "./model.js";
22
+ export { type GatewayMetadata, type ModelOverrides, type ModelPair, type ModelRuntime, type ModelRuntimeFactory } from "./model.js";
23
+ export { CredentialRejectedError, type CredentialRejectedBy } from "./errors.js";
24
+ export { createWorkersAIModelRuntime, workersAIModels, type WorkersAIRuntimeDeps } from "./workers-ai/index.js";
23
25
  export { appendOnce, buildAgentSession, notifyingCompaction, type AgentSessionOptions, type SessionHost, type SessionLike } from "./session.js";
24
26
  export { deterministicSessionMessage, finalReplyMessageId, parseRoundAckMessageId, parseTurn, roundAckMessageId, sessionMessage, sessionText, taskUserMessageId, toModelMessages, type ParsedTurn } from "./history.js";
25
- export { buildIntermediateContentHandler, isTransientAiError, type OnContent } from "./inference.js";
27
+ export { buildIntermediateContentHandler, isTransientAiError, nonRecoverableKind, type NonRecoverableKind, type OnContent, type RoundFailureKind } from "./inference.js";
26
28
  export { ControlCallError, controlTools, controlToolSet, type ControlTool, type TurnDecision } from "./control.js";
27
29
  export { FINAL_REPLY_TOOL_NAME, finalReplyInputSchema, finalReplyTool } from "./final-reply.js";
28
- //# sourceMappingURL=index.d.ts.map
@@ -19,10 +19,11 @@
19
19
  * exactly what is here.
20
20
  */
21
21
  export { newTurnBudget, stepAllowance } from "./budget.js";
22
- export { createModelRuntime } from "./model.js";
22
+ export {} from "./model.js";
23
+ export { CredentialRejectedError } from "./errors.js";
24
+ export { createWorkersAIModelRuntime, workersAIModels } from "./workers-ai/index.js";
23
25
  export { appendOnce, buildAgentSession, notifyingCompaction } from "./session.js";
24
26
  export { deterministicSessionMessage, finalReplyMessageId, parseRoundAckMessageId, parseTurn, roundAckMessageId, sessionMessage, sessionText, taskUserMessageId, toModelMessages } from "./history.js";
25
- export { buildIntermediateContentHandler, isTransientAiError } from "./inference.js";
27
+ export { buildIntermediateContentHandler, isTransientAiError, nonRecoverableKind } from "./inference.js";
26
28
  export { ControlCallError, controlTools, controlToolSet } from "./control.js";
27
29
  export { FINAL_REPLY_TOOL_NAME, finalReplyInputSchema, finalReplyTool } from "./final-reply.js";
28
- //# sourceMappingURL=index.js.map
@@ -5,7 +5,7 @@ import type { StepResult, ToolSet } from "ai";
5
5
  *
6
6
  * The two loops themselves are deliberately separate, not layered on a common
7
7
  * one: the main agent's Session-coupled round lives in
8
- * {@link file://./turn.ts turn.ts}, and the Session-less subagent loop in
8
+ * {@link file://../round/turn.ts turn.ts}, and the Session-less subagent loop in
9
9
  * {@link file://../subagent/run.ts run.ts}. They share error classification and
10
10
  * progress streaming; their control flow has nothing in common worth abstracting.
11
11
  */
@@ -34,6 +34,63 @@ export type OnContent = (text: string, stepIndex: number) => void | Promise<void
34
34
  * error codes, which arrive as prose on a plain `Error`.
35
35
  */
36
36
  export declare function isTransientAiError(err: unknown): boolean;
37
+ /**
38
+ * Why a round stopped without a second attempt being worth making.
39
+ *
40
+ * A stable string rather than the error itself, because this value crosses two
41
+ * serialization boundaries — the DO's RPC return and a Workflow step result —
42
+ * and an `Error` survives neither reliably. The host maps it to operator-facing
43
+ * copy; core never owns that wording.
44
+ *
45
+ * The credential kinds are separate strings rather than one, because they have
46
+ * different remedies and the host cannot tell them apart afterwards:
47
+ *
48
+ * - `credential` — the model provider rejected the token. Rotate that one.
49
+ * - `gateway-credential` — the gateway *in front of* the provider rejected the
50
+ * request, which the provider therefore never saw. Rotate the gateway's token
51
+ * instead; the model credential is very likely fine.
52
+ * - `proxy-credential` — an intermediary between the gateway and the provider
53
+ * rejected the caller. Notably **not** a token to rotate: the credential it
54
+ * refused is minted per request, so the fault is upstream of the secret —
55
+ * configuration drift, a rotated signing key, or clock skew.
56
+ * - `unknown-credential` — a `401`/`403` matching none of the shapes. Says so,
57
+ * rather than picking one and sending an operator to rotate a working secret.
58
+ */
59
+ export type NonRecoverableKind = "credential" | "gateway-credential" | "proxy-credential" | "unknown-credential";
60
+ /**
61
+ * Why a round ended with no answer — one terminal status, two situations.
62
+ *
63
+ * `exhausted` is the ladder run to the end: both slots tried, every repair
64
+ * spent, nothing usable produced. Every other member is the ladder stopping
65
+ * early, because nothing further could have cleared the fault — see
66
+ * {@link nonRecoverableKind}.
67
+ *
68
+ * The distinction is a *reason*, not an outcome: both deliver a failed Task with
69
+ * the same shape. What it decides is the words, and only the host has those (see
70
+ * `HandleTaskDeps.failureCopy`) — which is why this is a total union rather than
71
+ * an optional field. A consumer that maps kinds to copy is then a `Record` the
72
+ * compiler checks, and a new kind cannot be silently ignored by any of them.
73
+ */
74
+ export type RoundFailureKind = "exhausted" | NonRecoverableKind;
75
+ /**
76
+ * Whether an error is one that **no** further attempt can clear, and the reason.
77
+ *
78
+ * This is the third classification, and the one the other two cannot express.
79
+ * {@link isTransientAiError} splits failures into "retry the step" (`true`) and
80
+ * "burn this slot, try the fallback" (`false`) — and for a rejected credential
81
+ * *both* are wrong. Retrying spends the Workflow's budget on a request that can
82
+ * never succeed; falling back spends the second slot presenting the *same* dead
83
+ * token. Returning `false` from the transient check only avoids the first.
84
+ *
85
+ * So the attempt ladders check this **before** entering the fallback slot and
86
+ * stop there, and `runHandleTask` ends the Task with copy the host supplies.
87
+ * Nothing is retried and nothing is spent proving the obvious twice.
88
+ *
89
+ * Keyed on {@link file://./errors.ts CredentialRejectedError}, which is neutral
90
+ * and structurally matched — so a provider outside core raises one and gets this
91
+ * handling with nothing here to change.
92
+ */
93
+ export declare function nonRecoverableKind(err: unknown): NonRecoverableKind | undefined;
37
94
  /**
38
95
  * Returns a fresh `onStepEnd` callback for one `generateText` attempt.
39
96
  * Fires `onContent` for each intermediate step (text that accompanies tool
@@ -49,4 +106,3 @@ export declare function isTransientAiError(err: unknown): boolean;
49
106
  * steps are skipped. Default `[]` (the subagent loop has no control tools).
50
107
  */
51
108
  export declare function buildIntermediateContentHandler(onContent: OnContent, terminalToolNames?: string[]): (step: StepResult<ToolSet>) => Promise<void>;
52
- //# sourceMappingURL=inference.d.ts.map