@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.
- package/README.md +6 -4
- package/dist/a2a/agent-stub.d.ts +0 -1
- package/dist/a2a/agent-stub.js +0 -1
- package/dist/a2a/caller.d.ts +0 -1
- package/dist/a2a/caller.js +0 -1
- package/dist/a2a/card.d.ts +0 -1
- package/dist/a2a/card.js +0 -1
- package/dist/a2a/context.d.ts +0 -1
- package/dist/a2a/context.js +0 -1
- package/dist/a2a/executor.d.ts +0 -1
- package/dist/a2a/executor.js +0 -1
- package/dist/a2a/index.d.ts +0 -1
- package/dist/a2a/index.js +0 -1
- package/dist/a2a/notify.d.ts +4 -4
- package/dist/a2a/notify.js +4 -4
- package/dist/a2a/parts.d.ts +0 -1
- package/dist/a2a/parts.js +0 -1
- package/dist/a2a/push.d.ts +0 -1
- package/dist/a2a/push.js +0 -1
- package/dist/a2a/task-store.d.ts +0 -1
- package/dist/a2a/task-store.js +0 -1
- package/dist/a2a/task.d.ts +0 -1
- package/dist/a2a/task.js +0 -1
- package/dist/a2a/verify.d.ts +0 -1
- package/dist/a2a/verify.js +0 -1
- package/dist/agent/anthropic/index.d.ts +15 -0
- package/dist/agent/anthropic/index.js +19 -0
- package/dist/agent/anthropic/language-model.d.ts +59 -0
- package/dist/agent/anthropic/language-model.js +442 -0
- package/dist/agent/anthropic/prompt.d.ts +84 -0
- package/dist/agent/anthropic/prompt.js +541 -0
- package/dist/agent/anthropic/runtime.d.ts +79 -0
- package/dist/agent/anthropic/runtime.js +130 -0
- package/dist/agent/budget.d.ts +0 -1
- package/dist/agent/budget.js +0 -1
- package/dist/agent/control.d.ts +0 -1
- package/dist/agent/control.js +10 -10
- package/dist/agent/errors.d.ts +85 -0
- package/dist/agent/errors.js +64 -0
- package/dist/agent/final-reply.d.ts +14 -14
- package/dist/agent/final-reply.js +28 -12
- package/dist/agent/history.d.ts +3 -4
- package/dist/agent/history.js +2 -3
- package/dist/agent/index.d.ts +4 -3
- package/dist/agent/index.js +4 -3
- package/dist/agent/inference.d.ts +58 -2
- package/dist/agent/inference.js +44 -1
- package/dist/agent/model.d.ts +42 -26
- package/dist/agent/model.js +1 -49
- package/dist/agent/session.d.ts +6 -8
- package/dist/agent/session.js +3 -4
- package/dist/agent/workers-ai/index.d.ts +23 -0
- package/dist/agent/workers-ai/index.js +23 -0
- package/dist/agent/workers-ai/runtime.d.ts +42 -0
- package/dist/agent/workers-ai/runtime.js +63 -0
- package/dist/config.d.ts +49 -16
- package/dist/config.js +30 -2
- package/dist/contract/index.d.ts +0 -1
- package/dist/contract/index.js +0 -1
- package/dist/contract/plugin.d.ts +63 -4
- package/dist/contract/plugin.js +76 -1
- package/dist/contract/recipe.d.ts +16 -18
- package/dist/contract/recipe.js +0 -1
- package/dist/contract/validation.d.ts +0 -1
- package/dist/contract/validation.js +0 -1
- package/dist/db/db.d.ts +0 -2
- package/dist/db/db.js +0 -1
- package/dist/db/index.d.ts +0 -1
- package/dist/db/index.js +0 -1
- package/dist/db/migrations/index.d.ts +0 -1
- package/dist/db/migrations/index.js +8 -2
- package/dist/db/models/subtasks.d.ts +24 -26
- package/dist/db/models/subtasks.js +33 -77
- package/dist/db/models/tasks.d.ts +0 -1
- package/dist/db/models/tasks.js +0 -1
- package/dist/db/schema.d.ts +2 -22
- package/dist/db/schema.js +2 -5
- package/dist/env.d.ts +0 -1
- package/dist/env.js +0 -1
- package/dist/host/agent.d.ts +58 -5
- package/dist/host/agent.js +63 -10
- package/dist/host/index.d.ts +0 -1
- package/dist/host/index.js +0 -1
- package/dist/host/plugin-host.d.ts +0 -1
- package/dist/host/plugin-host.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -3
- package/dist/platform.d.ts +74 -12
- package/dist/platform.js +76 -14
- package/dist/round/agent.d.ts +36 -32
- package/dist/round/agent.js +61 -90
- package/dist/round/index.d.ts +3 -3
- package/dist/round/index.js +2 -3
- package/dist/round/policy.d.ts +2 -3
- package/dist/round/policy.js +0 -1
- package/dist/round/subagent.d.ts +19 -2
- package/dist/round/subagent.js +22 -6
- package/dist/round/turn.d.ts +32 -14
- package/dist/round/turn.js +83 -17
- package/dist/round/workflow.d.ts +30 -9
- package/dist/round/workflow.js +146 -78
- package/dist/runtime/index.d.ts +4 -3
- package/dist/runtime/index.js +6 -1
- package/dist/runtime/tool-families.d.ts +0 -1
- package/dist/runtime/tool-families.js +0 -1
- package/dist/subagent/fingerprint.d.ts +2 -3
- package/dist/subagent/fingerprint.js +8 -18
- package/dist/subagent/index.d.ts +6 -5
- package/dist/subagent/index.js +8 -7
- package/dist/subagent/prompt.d.ts +4 -6
- package/dist/subagent/prompt.js +0 -9
- package/dist/subagent/run.d.ts +8 -2
- package/dist/subagent/run.js +59 -10
- package/dist/subagent/workspace.d.ts +0 -1
- package/dist/subagent/workspace.js +0 -1
- package/dist/subtasks/catalog.d.ts +1 -2
- package/dist/subtasks/catalog.js +1 -2
- package/dist/subtasks/decomposition.d.ts +16 -21
- package/dist/subtasks/decomposition.js +27 -76
- package/dist/subtasks/delegate.d.ts +20 -2
- package/dist/subtasks/delegate.js +21 -17
- package/dist/subtasks/index.d.ts +1 -3
- package/dist/subtasks/index.js +1 -3
- package/dist/subtasks/subtask-types.d.ts +0 -9
- package/dist/subtasks/subtask-types.js +0 -8
- package/dist/subtasks/types.d.ts +45 -71
- package/dist/subtasks/types.js +0 -1
- package/dist/testing/auth.d.ts +0 -1
- package/dist/testing/auth.js +0 -1
- package/dist/testing/do.d.ts +0 -1
- package/dist/testing/do.js +0 -1
- package/dist/testing/fake-session.d.ts +0 -1
- package/dist/testing/fake-session.js +0 -1
- package/dist/testing/fixtures.d.ts +0 -1
- package/dist/testing/fixtures.js +0 -1
- package/dist/testing/harness.d.ts +0 -1
- package/dist/testing/harness.js +0 -1
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -1
- package/dist/testing/mock-model.d.ts +35 -1
- package/dist/testing/mock-model.js +75 -1
- package/dist/testing/node.d.ts +0 -1
- package/dist/testing/node.js +0 -1
- package/dist/testing/vcr-global-setup.d.ts +1 -4
- package/dist/testing/vcr-global-setup.js +1 -4
- package/dist/testing/vcr-shared.d.ts +0 -1
- package/dist/testing/vcr-shared.js +0 -1
- package/dist/testing/vcr-spec.d.ts +0 -1
- package/dist/testing/vcr-spec.js +0 -1
- package/dist/testing/vcr-store.d.ts +0 -1
- package/dist/testing/vcr-store.js +0 -1
- package/dist/testing/vcr.d.ts +0 -1
- package/dist/testing/vcr.js +0 -1
- package/dist/worker/define-agent.d.ts +0 -1
- package/dist/worker/define-agent.js +0 -1
- package/dist/worker/index.d.ts +5 -13
- package/dist/worker/index.js +5 -13
- package/package.json +20 -2
- package/dist/a2a/agent-stub.d.ts.map +0 -1
- package/dist/a2a/agent-stub.js.map +0 -1
- package/dist/a2a/caller.d.ts.map +0 -1
- package/dist/a2a/caller.js.map +0 -1
- package/dist/a2a/card.d.ts.map +0 -1
- package/dist/a2a/card.js.map +0 -1
- package/dist/a2a/context.d.ts.map +0 -1
- package/dist/a2a/context.js.map +0 -1
- package/dist/a2a/executor.d.ts.map +0 -1
- package/dist/a2a/executor.js.map +0 -1
- package/dist/a2a/index.d.ts.map +0 -1
- package/dist/a2a/index.js.map +0 -1
- package/dist/a2a/notify.d.ts.map +0 -1
- package/dist/a2a/notify.js.map +0 -1
- package/dist/a2a/parts.d.ts.map +0 -1
- package/dist/a2a/parts.js.map +0 -1
- package/dist/a2a/push.d.ts.map +0 -1
- package/dist/a2a/push.js.map +0 -1
- package/dist/a2a/task-store.d.ts.map +0 -1
- package/dist/a2a/task-store.js.map +0 -1
- package/dist/a2a/task.d.ts.map +0 -1
- package/dist/a2a/task.js.map +0 -1
- package/dist/a2a/verify.d.ts.map +0 -1
- package/dist/a2a/verify.js.map +0 -1
- package/dist/agent/budget.d.ts.map +0 -1
- package/dist/agent/budget.js.map +0 -1
- package/dist/agent/control.d.ts.map +0 -1
- package/dist/agent/control.js.map +0 -1
- package/dist/agent/final-reply.d.ts.map +0 -1
- package/dist/agent/final-reply.js.map +0 -1
- package/dist/agent/history.d.ts.map +0 -1
- package/dist/agent/history.js.map +0 -1
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/inference.d.ts.map +0 -1
- package/dist/agent/inference.js.map +0 -1
- package/dist/agent/model.d.ts.map +0 -1
- package/dist/agent/model.js.map +0 -1
- package/dist/agent/session.d.ts.map +0 -1
- package/dist/agent/session.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/contract/index.d.ts.map +0 -1
- package/dist/contract/index.js.map +0 -1
- package/dist/contract/plugin.d.ts.map +0 -1
- package/dist/contract/plugin.js.map +0 -1
- package/dist/contract/recipe.d.ts.map +0 -1
- package/dist/contract/recipe.js.map +0 -1
- package/dist/contract/validation.d.ts.map +0 -1
- package/dist/contract/validation.js.map +0 -1
- package/dist/db/db.d.ts.map +0 -1
- package/dist/db/db.js.map +0 -1
- package/dist/db/index.d.ts.map +0 -1
- package/dist/db/index.js.map +0 -1
- package/dist/db/migrations/index.d.ts.map +0 -1
- package/dist/db/migrations/index.js.map +0 -1
- package/dist/db/models/subtasks.d.ts.map +0 -1
- package/dist/db/models/subtasks.js.map +0 -1
- package/dist/db/models/tasks.d.ts.map +0 -1
- package/dist/db/models/tasks.js.map +0 -1
- package/dist/db/schema.d.ts.map +0 -1
- package/dist/db/schema.js.map +0 -1
- package/dist/env.d.ts.map +0 -1
- package/dist/env.js.map +0 -1
- package/dist/host/agent.d.ts.map +0 -1
- package/dist/host/agent.js.map +0 -1
- package/dist/host/index.d.ts.map +0 -1
- package/dist/host/index.js.map +0 -1
- package/dist/host/plugin-host.d.ts.map +0 -1
- package/dist/host/plugin-host.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/platform.d.ts.map +0 -1
- package/dist/platform.js.map +0 -1
- package/dist/round/agent.d.ts.map +0 -1
- package/dist/round/agent.js.map +0 -1
- package/dist/round/index.d.ts.map +0 -1
- package/dist/round/index.js.map +0 -1
- package/dist/round/policy.d.ts.map +0 -1
- package/dist/round/policy.js.map +0 -1
- package/dist/round/subagent.d.ts.map +0 -1
- package/dist/round/subagent.js.map +0 -1
- package/dist/round/turn.d.ts.map +0 -1
- package/dist/round/turn.js.map +0 -1
- package/dist/round/workflow.d.ts.map +0 -1
- package/dist/round/workflow.js.map +0 -1
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/tool-families.d.ts.map +0 -1
- package/dist/runtime/tool-families.js.map +0 -1
- package/dist/subagent/fingerprint.d.ts.map +0 -1
- package/dist/subagent/fingerprint.js.map +0 -1
- package/dist/subagent/index.d.ts.map +0 -1
- package/dist/subagent/index.js.map +0 -1
- package/dist/subagent/prompt.d.ts.map +0 -1
- package/dist/subagent/prompt.js.map +0 -1
- package/dist/subagent/run.d.ts.map +0 -1
- package/dist/subagent/run.js.map +0 -1
- package/dist/subagent/workspace.d.ts.map +0 -1
- package/dist/subagent/workspace.js.map +0 -1
- package/dist/subtasks/catalog.d.ts.map +0 -1
- package/dist/subtasks/catalog.js.map +0 -1
- package/dist/subtasks/decomposition.d.ts.map +0 -1
- package/dist/subtasks/decomposition.js.map +0 -1
- package/dist/subtasks/delegate.d.ts.map +0 -1
- package/dist/subtasks/delegate.js.map +0 -1
- package/dist/subtasks/index.d.ts.map +0 -1
- package/dist/subtasks/index.js.map +0 -1
- package/dist/subtasks/scheduler.d.ts +0 -49
- package/dist/subtasks/scheduler.d.ts.map +0 -1
- package/dist/subtasks/scheduler.js +0 -48
- package/dist/subtasks/scheduler.js.map +0 -1
- package/dist/subtasks/subtask-types.d.ts.map +0 -1
- package/dist/subtasks/subtask-types.js.map +0 -1
- package/dist/subtasks/types.d.ts.map +0 -1
- package/dist/subtasks/types.js.map +0 -1
- package/dist/testing/auth.d.ts.map +0 -1
- package/dist/testing/auth.js.map +0 -1
- package/dist/testing/do.d.ts.map +0 -1
- package/dist/testing/do.js.map +0 -1
- package/dist/testing/fake-session.d.ts.map +0 -1
- package/dist/testing/fake-session.js.map +0 -1
- package/dist/testing/fixtures.d.ts.map +0 -1
- package/dist/testing/fixtures.js.map +0 -1
- package/dist/testing/harness.d.ts.map +0 -1
- package/dist/testing/harness.js.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/mock-model.d.ts.map +0 -1
- package/dist/testing/mock-model.js.map +0 -1
- package/dist/testing/node.d.ts.map +0 -1
- package/dist/testing/node.js.map +0 -1
- package/dist/testing/vcr-global-setup.d.ts.map +0 -1
- package/dist/testing/vcr-global-setup.js.map +0 -1
- package/dist/testing/vcr-shared.d.ts.map +0 -1
- package/dist/testing/vcr-shared.js.map +0 -1
- package/dist/testing/vcr-spec.d.ts.map +0 -1
- package/dist/testing/vcr-spec.js.map +0 -1
- package/dist/testing/vcr-store.d.ts.map +0 -1
- package/dist/testing/vcr-store.js.map +0 -1
- package/dist/testing/vcr.d.ts.map +0 -1
- package/dist/testing/vcr.js.map +0 -1
- package/dist/worker/define-agent.d.ts.map +0 -1
- package/dist/worker/define-agent.js.map +0 -1
- package/dist/worker/index.d.ts.map +0 -1
- package/dist/worker/index.js.map +0 -1
package/dist/agent/inference.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { APICallError, RetryError } from "ai";
|
|
2
|
+
// Type-only would not work: this is a runtime guard. `errors.ts` is the neutral
|
|
3
|
+
// sibling of `model.ts` and imports nothing, so this reaches no provider.
|
|
4
|
+
import { CredentialRejectedError } from "./errors.js";
|
|
2
5
|
/** Workers-AI error codes and message fragments that mean "try again later". */
|
|
3
6
|
const TRANSIENT_MESSAGE_FRAGMENTS = [
|
|
4
7
|
"3040",
|
|
@@ -32,6 +35,12 @@ function isRetryableStatus(status) {
|
|
|
32
35
|
* error codes, which arrive as prose on a plain `Error`.
|
|
33
36
|
*/
|
|
34
37
|
export function isTransientAiError(err) {
|
|
38
|
+
// Checked first because a rejected credential's message can carry "rate
|
|
39
|
+
// limit"-adjacent prose the fragment scan below would misread as transient.
|
|
40
|
+
// Note that `false` alone does not protect the fallback slot — see
|
|
41
|
+
// {@link nonRecoverableKind}, which is what actually stops the ladder.
|
|
42
|
+
if (nonRecoverableKind(err) !== undefined)
|
|
43
|
+
return false;
|
|
35
44
|
if (APICallError.isInstance(err)) {
|
|
36
45
|
if (err.isRetryable)
|
|
37
46
|
return true;
|
|
@@ -45,6 +54,41 @@ export function isTransientAiError(err) {
|
|
|
45
54
|
const message = err.message.toLowerCase();
|
|
46
55
|
return TRANSIENT_MESSAGE_FRAGMENTS.some((fragment) => message.includes(fragment));
|
|
47
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether an error is one that **no** further attempt can clear, and the reason.
|
|
59
|
+
*
|
|
60
|
+
* This is the third classification, and the one the other two cannot express.
|
|
61
|
+
* {@link isTransientAiError} splits failures into "retry the step" (`true`) and
|
|
62
|
+
* "burn this slot, try the fallback" (`false`) — and for a rejected credential
|
|
63
|
+
* *both* are wrong. Retrying spends the Workflow's budget on a request that can
|
|
64
|
+
* never succeed; falling back spends the second slot presenting the *same* dead
|
|
65
|
+
* token. Returning `false` from the transient check only avoids the first.
|
|
66
|
+
*
|
|
67
|
+
* So the attempt ladders check this **before** entering the fallback slot and
|
|
68
|
+
* stop there, and `runHandleTask` ends the Task with copy the host supplies.
|
|
69
|
+
* Nothing is retried and nothing is spent proving the obvious twice.
|
|
70
|
+
*
|
|
71
|
+
* Keyed on {@link file://./errors.ts CredentialRejectedError}, which is neutral
|
|
72
|
+
* and structurally matched — so a provider outside core raises one and gets this
|
|
73
|
+
* handling with nothing here to change.
|
|
74
|
+
*/
|
|
75
|
+
export function nonRecoverableKind(err) {
|
|
76
|
+
if (!CredentialRejectedError.isInstance(err))
|
|
77
|
+
return undefined;
|
|
78
|
+
switch (err.source) {
|
|
79
|
+
case "provider":
|
|
80
|
+
return "credential";
|
|
81
|
+
case "gateway":
|
|
82
|
+
return "gateway-credential";
|
|
83
|
+
case "proxy":
|
|
84
|
+
return "proxy-credential";
|
|
85
|
+
// Includes an error that crossed a realm boundary carrying no `source` at
|
|
86
|
+
// all: `isInstance` is structural, so that is reachable, and "unknown" is
|
|
87
|
+
// the honest reading of it.
|
|
88
|
+
default:
|
|
89
|
+
return "unknown-credential";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
48
92
|
/** A step is "intermediate" when it makes tool calls — more content follows. */
|
|
49
93
|
function isIntermediateStep(step) {
|
|
50
94
|
return step.finishReason === "tool-calls";
|
|
@@ -76,4 +120,3 @@ export function buildIntermediateContentHandler(onContent, terminalToolNames = [
|
|
|
76
120
|
await onContent(content, i);
|
|
77
121
|
};
|
|
78
122
|
}
|
|
79
|
-
//# sourceMappingURL=inference.js.map
|
package/dist/agent/model.d.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import type { LanguageModel } from "ai";
|
|
2
2
|
import type { ModelConfig } from "../config.js";
|
|
3
3
|
/**
|
|
4
|
-
* The
|
|
4
|
+
* The provider contract every loop runs against — and nothing that implements
|
|
5
|
+
* it.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* a
|
|
7
|
+
* {@link ModelRuntime} is the whole seam: an agent that returns one runs every
|
|
8
|
+
* loop in core unchanged, because nothing downstream — the round loop, the
|
|
9
|
+
* control-tool repair ladder, the Session's compaction, the Workflow — ever sees
|
|
10
|
+
* more than a `LanguageModel` from `ai`. It never learns which provider produced
|
|
11
|
+
* it.
|
|
12
|
+
*
|
|
13
|
+
* The implementations are siblings under `agent/`, one directory each:
|
|
14
|
+
* {@link file://./workers-ai/index.ts `./workers-ai`} is core's default, and
|
|
15
|
+
* {@link file://./anthropic/index.ts `./anthropic`} is Claude behind an optional
|
|
16
|
+
* peer dependency. A third provider is a third directory exporting one
|
|
17
|
+
* {@link ModelRuntimeFactory}; nothing here has to change to admit it.
|
|
18
|
+
*
|
|
19
|
+
* Which is why this file has no runtime imports at all. The Workers AI factory
|
|
20
|
+
* used to live in it, and a contract that ships one implementation inline reads
|
|
21
|
+
* as *the* runtime with an escape hatch, rather than as one of N.
|
|
10
22
|
*/
|
|
11
23
|
/**
|
|
12
24
|
* Custom metadata attached to the AI Gateway log for every call a pair makes.
|
|
@@ -22,15 +34,16 @@ export interface ModelOverrides {
|
|
|
22
34
|
/** Test override for the fallback slot. */
|
|
23
35
|
fallbackModel?: LanguageModel;
|
|
24
36
|
/**
|
|
25
|
-
*
|
|
26
|
-
* against the allowlist by `validateRecipe`). Defaults to the configured
|
|
37
|
+
* The provider's model id for the primary slot. Defaults to the configured
|
|
27
38
|
* `chatModelId`.
|
|
39
|
+
*
|
|
40
|
+
* The subagent path passes `ValidatedRecipe.primaryModelId`, which is the
|
|
41
|
+
* host's own configured id — `validateRecipe` copies the pair on, and a recipe
|
|
42
|
+
* has no field to name a model with. So this parameterizes the pair without
|
|
43
|
+
* ever widening which models are reachable.
|
|
28
44
|
*/
|
|
29
45
|
primaryModelId?: string;
|
|
30
|
-
/**
|
|
31
|
-
* Workers-AI id for the fallback slot (already code-validated). Defaults to
|
|
32
|
-
* the configured `fallbackChatModelId`.
|
|
33
|
-
*/
|
|
46
|
+
/** The provider's model id for the fallback slot. See {@link primaryModelId}. */
|
|
34
47
|
fallbackModelId?: string;
|
|
35
48
|
/** AI Gateway log metadata for correlation — see {@link GatewayMetadata}. */
|
|
36
49
|
metadata?: GatewayMetadata;
|
|
@@ -45,24 +58,27 @@ export interface ModelPair {
|
|
|
45
58
|
export interface ModelRuntime {
|
|
46
59
|
/**
|
|
47
60
|
* Lazily build + memoize a primary/fallback model pair (overridable in tests,
|
|
48
|
-
* id-parameterized
|
|
49
|
-
*
|
|
61
|
+
* id-parameterized so a subagent can run the pair its validated recipe
|
|
62
|
+
* carries). Nothing is checked here — the ids reaching this can only be the
|
|
63
|
+
* host's own, which `resolveConfig` has already proven non-empty and distinct.
|
|
50
64
|
*/
|
|
51
65
|
createModelPair(overrides?: ModelOverrides): ModelPair;
|
|
52
66
|
}
|
|
53
|
-
export interface ModelRuntimeDeps {
|
|
54
|
-
/** The `AI` binding. Read lazily — see {@link createModelRuntime}. */
|
|
55
|
-
ai: Ai;
|
|
56
|
-
config: ModelConfig;
|
|
57
|
-
}
|
|
58
67
|
/**
|
|
59
|
-
*
|
|
68
|
+
* How a provider is supplied to an agent: given the Worker env and the agent's
|
|
69
|
+
* *resolved* model config, return a runtime.
|
|
70
|
+
*
|
|
71
|
+
* Both base-class seams — `LoopingAgent.modelRuntime` and
|
|
72
|
+
* `RecipeSubagentHost.modelRuntime` — take this shape, which is the point of it.
|
|
73
|
+
* A provider written as one of these is defined once and referenced from the
|
|
74
|
+
* agent and its subagent facet, instead of being spelled out twice in two class
|
|
75
|
+
* bodies that nothing keeps in step. See
|
|
76
|
+
* {@link file://./workers-ai/runtime.ts workersAIModels} for core's own.
|
|
60
77
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
78
|
+
* Config arrives as an argument rather than being read off `this`: the facet
|
|
79
|
+
* resolves its config inside `buildRuntime` and calls the seam from there, so
|
|
80
|
+
* there is no `this.config` to read at that point — and a factory that cannot
|
|
81
|
+
* reach for one cannot disagree with its caller about which gateway the agent
|
|
82
|
+
* is on.
|
|
66
83
|
*/
|
|
67
|
-
export
|
|
68
|
-
//# sourceMappingURL=model.d.ts.map
|
|
84
|
+
export type ModelRuntimeFactory<TEnv> = (env: TEnv, config: ModelConfig) => ModelRuntime;
|
package/dist/agent/model.js
CHANGED
|
@@ -1,49 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Build the model runtime for one agent instance.
|
|
4
|
-
*
|
|
5
|
-
* The provider is constructed on first *use*, not here. During `wrangler deploy`
|
|
6
|
-
* Cloudflare evaluates module scope to validate the new version, and bindings
|
|
7
|
-
* are not populated at that point — constructing eagerly makes `createWorkersAI`
|
|
8
|
-
* throw "you must provide either a binding or credentials". The same laziness
|
|
9
|
-
* protects a consumer who builds their runtime early.
|
|
10
|
-
*/
|
|
11
|
-
export function createModelRuntime(deps) {
|
|
12
|
-
const { config } = deps;
|
|
13
|
-
let provider;
|
|
14
|
-
const workersai = () => (provider ??= createWorkersAI({
|
|
15
|
-
binding: deps.ai,
|
|
16
|
-
gateway: { id: config.aiGatewayId }
|
|
17
|
-
}));
|
|
18
|
-
/**
|
|
19
|
-
* Per-model Workers-AI settings: pin the gateway id (so per-call metadata does
|
|
20
|
-
* not drop the gateway route), attach correlation metadata when supplied, and
|
|
21
|
-
* set the reasoning budget.
|
|
22
|
-
*
|
|
23
|
-
* Always returns a settings object, even with no metadata: `reasoning_effort`
|
|
24
|
-
* has to reach the binding on every call, and an `undefined` return drops it.
|
|
25
|
-
*/
|
|
26
|
-
const chatSettings = (metadata) => ({
|
|
27
|
-
gateway: { id: config.aiGatewayId, ...(metadata ? { metadata } : {}) },
|
|
28
|
-
reasoning_effort: config.reasoningEffort
|
|
29
|
-
});
|
|
30
|
-
return {
|
|
31
|
-
createModelPair(overrides = {}) {
|
|
32
|
-
const primaryId = overrides.primaryModelId ?? config.chatModelId;
|
|
33
|
-
const fallbackId = overrides.fallbackModelId ?? config.fallbackChatModelId;
|
|
34
|
-
let primary;
|
|
35
|
-
let fallback;
|
|
36
|
-
const settings = chatSettings(overrides.metadata);
|
|
37
|
-
return {
|
|
38
|
-
primary: () => (primary ??= overrides.model ?? workersai()(primaryId, settings)),
|
|
39
|
-
fallback: () => (fallback ??=
|
|
40
|
-
overrides.fallbackModel ??
|
|
41
|
-
overrides.model ??
|
|
42
|
-
workersai()(fallbackId, settings)),
|
|
43
|
-
primaryId: () => primaryId,
|
|
44
|
-
fallbackId: () => fallbackId
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=model.js.map
|
|
1
|
+
export {};
|
package/dist/agent/session.d.ts
CHANGED
|
@@ -3,9 +3,8 @@ import { Session } from "agents/experimental/memory/session";
|
|
|
3
3
|
import type { SessionMessage } from "agents/experimental/memory/session";
|
|
4
4
|
import { createCompactFunction } from "agents/experimental/memory/utils";
|
|
5
5
|
/**
|
|
6
|
-
* The one continuous {@link Session} an agent Durable Object owns
|
|
7
|
-
*
|
|
8
|
-
* soul + memory + compaction).
|
|
6
|
+
* The one continuous {@link Session} an agent Durable Object owns: soul + memory
|
|
7
|
+
* + compaction, one Session per DO.
|
|
9
8
|
*
|
|
10
9
|
* Compaction is the one **lossy** thing this module does, so it is also the one
|
|
11
10
|
* thing it announces: `onMessagesDisplaced` hands over the raw messages a
|
|
@@ -27,7 +26,7 @@ export interface SessionLike {
|
|
|
27
26
|
* Read one message by id, or null. Reads the **raw stored row**, so it is
|
|
28
27
|
* unaffected by compaction overlays — a message folded into a summary is still
|
|
29
28
|
* readable here. That is what makes {@link appendOnce}'s read-back a reliable
|
|
30
|
-
* recovery path for a
|
|
29
|
+
* recovery path for a round whose Workflow step re-ran.
|
|
31
30
|
*/
|
|
32
31
|
getMessage(id: string): Promise<SessionMessage | null>;
|
|
33
32
|
refreshSystemPrompt(): Promise<string>;
|
|
@@ -40,13 +39,13 @@ export interface SessionLike {
|
|
|
40
39
|
* is **durably stored** under that id.
|
|
41
40
|
*
|
|
42
41
|
* `Session.appendMessage` is already idempotent by id: appending an id that
|
|
43
|
-
* exists is a no-op. The read-back is what matters for a re-run
|
|
44
|
-
*
|
|
42
|
+
* exists is a no-op. The read-back is what matters for a re-run step — if it
|
|
43
|
+
* crashed after appending and the retry re-inferred a *different* reply, the
|
|
45
44
|
* append no-ops and this returns the original, durable text. The Session and the
|
|
46
45
|
* value the caller goes on to deliver therefore never disagree.
|
|
47
46
|
*
|
|
48
47
|
* Falls back to the message's own text if the read-back returns null (it cannot,
|
|
49
|
-
* having just been appended) rather than failing a
|
|
48
|
+
* having just been appended) rather than failing a round over a missing echo.
|
|
50
49
|
*/
|
|
51
50
|
export declare function appendOnce(session: SessionLike, message: SessionMessage): Promise<string>;
|
|
52
51
|
export interface AgentSessionOptions {
|
|
@@ -99,4 +98,3 @@ export declare function notifyingCompaction(base: CompactFn, onMessagesDisplaced
|
|
|
99
98
|
*/
|
|
100
99
|
export declare function buildAgentSession(agent: SessionHost, model: LanguageModel, opts: AgentSessionOptions): Session;
|
|
101
100
|
export {};
|
|
102
|
-
//# sourceMappingURL=session.d.ts.map
|
package/dist/agent/session.js
CHANGED
|
@@ -7,13 +7,13 @@ import { sessionText } from "./history.js";
|
|
|
7
7
|
* is **durably stored** under that id.
|
|
8
8
|
*
|
|
9
9
|
* `Session.appendMessage` is already idempotent by id: appending an id that
|
|
10
|
-
* exists is a no-op. The read-back is what matters for a re-run
|
|
11
|
-
*
|
|
10
|
+
* exists is a no-op. The read-back is what matters for a re-run step — if it
|
|
11
|
+
* crashed after appending and the retry re-inferred a *different* reply, the
|
|
12
12
|
* append no-ops and this returns the original, durable text. The Session and the
|
|
13
13
|
* value the caller goes on to deliver therefore never disagree.
|
|
14
14
|
*
|
|
15
15
|
* Falls back to the message's own text if the read-back returns null (it cannot,
|
|
16
|
-
* having just been appended) rather than failing a
|
|
16
|
+
* having just been appended) rather than failing a round over a missing echo.
|
|
17
17
|
*/
|
|
18
18
|
export async function appendOnce(session, message) {
|
|
19
19
|
await session.appendMessage(message);
|
|
@@ -80,4 +80,3 @@ export function buildAgentSession(agent, model, opts) {
|
|
|
80
80
|
.onCompaction(compact)
|
|
81
81
|
.compactAfter(opts.compactAfterTokens);
|
|
82
82
|
}
|
|
83
|
-
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workers AI — core's default model provider.
|
|
3
|
+
*
|
|
4
|
+
* A sibling of {@link file://../anthropic/index.ts `./anthropic`}, and like it a
|
|
5
|
+
* provider rather than a capability: it ships no tools, no prompt copy and no
|
|
6
|
+
* policy; it satisfies {@link file://../model.ts ModelRuntime} and stops.
|
|
7
|
+
*
|
|
8
|
+
* It differs from that sibling in two ways, both deliberate:
|
|
9
|
+
*
|
|
10
|
+
* **No `LanguageModel` adapter.** `workers-ai-provider` ships one, so this
|
|
11
|
+
* directory is a factory and nothing else. The Anthropic side hand-builds the
|
|
12
|
+
* adapter — the prompt mapping, the cache control, the error taxonomy — which is
|
|
13
|
+
* why it is five files and this is one.
|
|
14
|
+
*
|
|
15
|
+
* **No package subpath.** `/anthropic` has one because `@anthropic-ai/sdk` is an
|
|
16
|
+
* *optional* peer and an agent on Workers AI must not pay for a provider it
|
|
17
|
+
* never calls. That argument does not apply here: `workers-ai-provider` is a
|
|
18
|
+
* required peer, and this is the default every un-overridden seam reaches
|
|
19
|
+
* through `LoopingAgent` itself, so it is in every consumer's module graph
|
|
20
|
+
* already. It is exported from `@loopingai/core/agent` — one symbol, one import
|
|
21
|
+
* path.
|
|
22
|
+
*/
|
|
23
|
+
export { createWorkersAIModelRuntime, workersAIModels, type WorkersAIRuntimeDeps } from "./runtime.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workers AI — core's default model provider.
|
|
3
|
+
*
|
|
4
|
+
* A sibling of {@link file://../anthropic/index.ts `./anthropic`}, and like it a
|
|
5
|
+
* provider rather than a capability: it ships no tools, no prompt copy and no
|
|
6
|
+
* policy; it satisfies {@link file://../model.ts ModelRuntime} and stops.
|
|
7
|
+
*
|
|
8
|
+
* It differs from that sibling in two ways, both deliberate:
|
|
9
|
+
*
|
|
10
|
+
* **No `LanguageModel` adapter.** `workers-ai-provider` ships one, so this
|
|
11
|
+
* directory is a factory and nothing else. The Anthropic side hand-builds the
|
|
12
|
+
* adapter — the prompt mapping, the cache control, the error taxonomy — which is
|
|
13
|
+
* why it is five files and this is one.
|
|
14
|
+
*
|
|
15
|
+
* **No package subpath.** `/anthropic` has one because `@anthropic-ai/sdk` is an
|
|
16
|
+
* *optional* peer and an agent on Workers AI must not pay for a provider it
|
|
17
|
+
* never calls. That argument does not apply here: `workers-ai-provider` is a
|
|
18
|
+
* required peer, and this is the default every un-overridden seam reaches
|
|
19
|
+
* through `LoopingAgent` itself, so it is in every consumer's module graph
|
|
20
|
+
* already. It is exported from `@loopingai/core/agent` — one symbol, one import
|
|
21
|
+
* path.
|
|
22
|
+
*/
|
|
23
|
+
export { createWorkersAIModelRuntime, workersAIModels } from "./runtime.js";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ModelConfig } from "../../config.js";
|
|
2
|
+
import type { AiEnv } from "../../env.js";
|
|
3
|
+
import type { ModelRuntime, ModelRuntimeFactory } from "../model.js";
|
|
4
|
+
/**
|
|
5
|
+
* The Workers-AI model pair every loop runs on by default, built per agent
|
|
6
|
+
* instance.
|
|
7
|
+
*
|
|
8
|
+
* The predecessor read `env.AI` and five config constants as module-level
|
|
9
|
+
* imports. Neither survives packaging: `env` does not exist at module scope on
|
|
10
|
+
* Workers, and a module constant cannot be overridden by a consumer. So this is
|
|
11
|
+
* a factory over an injected binding and an injected {@link ModelConfig}.
|
|
12
|
+
*/
|
|
13
|
+
export interface WorkersAIRuntimeDeps {
|
|
14
|
+
/** The `AI` binding. Read lazily — see {@link createWorkersAIModelRuntime}. */
|
|
15
|
+
ai: Ai;
|
|
16
|
+
config: ModelConfig;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build the Workers AI model runtime for one agent instance.
|
|
20
|
+
*
|
|
21
|
+
* The provider is constructed on first *use*, not here. During `wrangler deploy`
|
|
22
|
+
* Cloudflare evaluates module scope to validate the new version, and bindings
|
|
23
|
+
* are not populated at that point — constructing eagerly makes `createWorkersAI`
|
|
24
|
+
* throw "you must provide either a binding or credentials". The same laziness
|
|
25
|
+
* protects a consumer who builds their runtime early.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createWorkersAIModelRuntime(deps: WorkersAIRuntimeDeps): ModelRuntime;
|
|
28
|
+
/**
|
|
29
|
+
* Core's default provider — what every {@link ModelRuntimeFactory} seam lands on
|
|
30
|
+
* when an agent does not override it.
|
|
31
|
+
*
|
|
32
|
+
* One definition rather than one per base class. The body used to be written
|
|
33
|
+
* twice, once in {@link file://../../host/agent.ts LoopingAgent.modelRuntime}
|
|
34
|
+
* and once in
|
|
35
|
+
* {@link file://../../round/subagent.ts RecipeSubagentHost.modelRuntime}, which
|
|
36
|
+
* is the same duplication the seam exists to let a *consumer* avoid.
|
|
37
|
+
*
|
|
38
|
+
* Typed on {@link AiEnv} rather than a caller's full `Env`: a factory that
|
|
39
|
+
* accepts the narrow shape is callable with any env that satisfies it, so both
|
|
40
|
+
* base classes pass `this.env` straight through.
|
|
41
|
+
*/
|
|
42
|
+
export declare const workersAIModels: ModelRuntimeFactory<AiEnv>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createWorkersAI } from "workers-ai-provider";
|
|
2
|
+
/**
|
|
3
|
+
* Build the Workers AI model runtime for one agent instance.
|
|
4
|
+
*
|
|
5
|
+
* The provider is constructed on first *use*, not here. During `wrangler deploy`
|
|
6
|
+
* Cloudflare evaluates module scope to validate the new version, and bindings
|
|
7
|
+
* are not populated at that point — constructing eagerly makes `createWorkersAI`
|
|
8
|
+
* throw "you must provide either a binding or credentials". The same laziness
|
|
9
|
+
* protects a consumer who builds their runtime early.
|
|
10
|
+
*/
|
|
11
|
+
export function createWorkersAIModelRuntime(deps) {
|
|
12
|
+
const { config } = deps;
|
|
13
|
+
let provider;
|
|
14
|
+
const workersai = () => (provider ??= createWorkersAI({
|
|
15
|
+
binding: deps.ai,
|
|
16
|
+
gateway: { id: config.aiGatewayId }
|
|
17
|
+
}));
|
|
18
|
+
/**
|
|
19
|
+
* Per-model Workers-AI settings: pin the gateway id (so per-call metadata does
|
|
20
|
+
* not drop the gateway route), attach correlation metadata when supplied, and
|
|
21
|
+
* set the reasoning budget.
|
|
22
|
+
*
|
|
23
|
+
* Always returns a settings object, even with no metadata: `reasoning_effort`
|
|
24
|
+
* has to reach the binding on every call, and an `undefined` return drops it.
|
|
25
|
+
*/
|
|
26
|
+
const chatSettings = (metadata) => ({
|
|
27
|
+
gateway: { id: config.aiGatewayId, ...(metadata ? { metadata } : {}) },
|
|
28
|
+
reasoning_effort: config.reasoningEffort
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
createModelPair(overrides = {}) {
|
|
32
|
+
const primaryId = overrides.primaryModelId ?? config.chatModelId;
|
|
33
|
+
const fallbackId = overrides.fallbackModelId ?? config.fallbackChatModelId;
|
|
34
|
+
let primary;
|
|
35
|
+
let fallback;
|
|
36
|
+
const settings = chatSettings(overrides.metadata);
|
|
37
|
+
return {
|
|
38
|
+
primary: () => (primary ??= overrides.model ?? workersai()(primaryId, settings)),
|
|
39
|
+
fallback: () => (fallback ??=
|
|
40
|
+
overrides.fallbackModel ??
|
|
41
|
+
overrides.model ??
|
|
42
|
+
workersai()(fallbackId, settings)),
|
|
43
|
+
primaryId: () => primaryId,
|
|
44
|
+
fallbackId: () => fallbackId
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Core's default provider — what every {@link ModelRuntimeFactory} seam lands on
|
|
51
|
+
* when an agent does not override it.
|
|
52
|
+
*
|
|
53
|
+
* One definition rather than one per base class. The body used to be written
|
|
54
|
+
* twice, once in {@link file://../../host/agent.ts LoopingAgent.modelRuntime}
|
|
55
|
+
* and once in
|
|
56
|
+
* {@link file://../../round/subagent.ts RecipeSubagentHost.modelRuntime}, which
|
|
57
|
+
* is the same duplication the seam exists to let a *consumer* avoid.
|
|
58
|
+
*
|
|
59
|
+
* Typed on {@link AiEnv} rather than a caller's full `Env`: a factory that
|
|
60
|
+
* accepts the narrow shape is callable with any env that satisfies it, so both
|
|
61
|
+
* base classes pass `this.env` straight through.
|
|
62
|
+
*/
|
|
63
|
+
export const workersAIModels = (env, config) => createWorkersAIModelRuntime({ ai: env.AI, config });
|
package/dist/config.d.ts
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The shapes of everything an agent tunes, plus a working set of defaults.
|
|
3
|
-
*
|
|
4
|
-
* In the predecessor repos this file held bare `export const`s that ~12 modules
|
|
5
|
-
* imported directly. That is what this package cannot do: a module-level constant
|
|
6
|
-
* read at import time is not overridable by a consumer, and it freezes the value
|
|
7
|
-
* into the module graph before `env` exists. So core owns the *shapes* and a
|
|
8
|
-
* baseline; a consuming agent passes overrides to {@link resolveConfig} once, at
|
|
9
|
-
* DO start, and the resolved object is threaded through explicitly.
|
|
10
|
-
*
|
|
11
|
-
* The distinction against {@link file://./platform.ts} stays sharp: nothing here
|
|
12
|
-
* is a platform fact, and nothing there is tunable.
|
|
13
|
-
*/
|
|
14
1
|
/** Model ids and per-call generation settings. */
|
|
15
2
|
export interface ModelConfig {
|
|
16
3
|
/**
|
|
@@ -40,6 +27,21 @@ export interface ModelConfig {
|
|
|
40
27
|
fallbackChatModelId: string;
|
|
41
28
|
/** AI Gateway slug; `"default"` auto-provisions on first request. */
|
|
42
29
|
aiGatewayId: string;
|
|
30
|
+
/**
|
|
31
|
+
* The segment after the gateway slug in `.../{gateway}/{provider}` — either a
|
|
32
|
+
* provider-native path like `"anthropic"` or a
|
|
33
|
+
* [custom provider](https://developers.cloudflare.com/ai-gateway/configuration/custom-providers/)
|
|
34
|
+
* slug. Core never reads it; a `ModelRuntime` that builds its own base URL
|
|
35
|
+
* does.
|
|
36
|
+
*
|
|
37
|
+
* Config rather than a literal at that call site because the parent agent and
|
|
38
|
+
* its subagent facet resolve their config independently, and a value that
|
|
39
|
+
* drifts between them routes delegated subtasks through a different provider
|
|
40
|
+
* than the round that delegated them — silently, since both satisfy
|
|
41
|
+
* `ModelRuntime`. Which path to pick, and why, belongs with the agent that
|
|
42
|
+
* picks it.
|
|
43
|
+
*/
|
|
44
|
+
aiGatewayProvider: string;
|
|
43
45
|
/**
|
|
44
46
|
* Output-token ceiling for every chat call. Left unset, the binding applies a
|
|
45
47
|
* per-model default which a reasoning model spends on `reasoning_content`
|
|
@@ -49,6 +51,38 @@ export interface ModelConfig {
|
|
|
49
51
|
maxOutputTokens: number;
|
|
50
52
|
/** Reasoning budget forwarded on the binding's `inputs` by workers-ai-provider. */
|
|
51
53
|
reasoningEffort: "low" | "medium" | "high";
|
|
54
|
+
/**
|
|
55
|
+
* How many times a single model call is retried **on the same model** before
|
|
56
|
+
* the round gives up on that slot and moves to the fallback.
|
|
57
|
+
*
|
|
58
|
+
* This was hardcoded to `0` for a long time, with a reason that was right for
|
|
59
|
+
* one case and wrong for the other. The reason: primary→fallback recovery is
|
|
60
|
+
* ours, so provider-level backoff only adds latency and duplicates it. True
|
|
61
|
+
* when the two slots are different vendors, which is what
|
|
62
|
+
* {@link fallbackChatModelId} advises — a 429 on one says nothing about the
|
|
63
|
+
* other, so falling straight through is the fastest correct move.
|
|
64
|
+
*
|
|
65
|
+
* It is false for a rate limit on an agent whose slots share a credential. A
|
|
66
|
+
* coder running Opus with Sonnet as its step-down burns the fallback proving
|
|
67
|
+
* the same 429 twice, then throws, then the Workflow retries the whole round
|
|
68
|
+
* and does it again. Waiting the `retry-after` the provider actually sent is
|
|
69
|
+
* both cheaper and far more likely to work.
|
|
70
|
+
*
|
|
71
|
+
* The AI SDK does the waiting, and it does it properly:
|
|
72
|
+
* `retryWithExponentialBackoffRespectingRetryHeaders` honours `retry-after-ms`
|
|
73
|
+
* and `retry-after` and falls back to exponential backoff. It only fires for
|
|
74
|
+
* an `APICallError` carrying `isRetryable`, which is why
|
|
75
|
+
* {@link file://./agent/anthropic/language-model.ts} maps provider errors into
|
|
76
|
+
* that shape rather than rethrowing them raw.
|
|
77
|
+
*
|
|
78
|
+
* Bounded at 4 by `resolveConfig`. The retries happen *inside*
|
|
79
|
+
* `step.do("turn:<round>")`, and the SDK caps a single honoured `retry-after`
|
|
80
|
+
* at 60s, so the worst case is roughly `maxRetries` minutes of waiting before
|
|
81
|
+
* the round has spent a token of its own — against
|
|
82
|
+
* {@link file://./platform.ts STEP_TIMEOUT_MS}, which is where that ceiling is
|
|
83
|
+
* stated and the only place it should be read from.
|
|
84
|
+
*/
|
|
85
|
+
maxRetries: number;
|
|
52
86
|
}
|
|
53
87
|
/**
|
|
54
88
|
* An execution budget, in the only two currencies that mean anything: **turns**
|
|
@@ -126,8 +160,8 @@ export interface CoreConfig {
|
|
|
126
160
|
toolOutputWindow: number;
|
|
127
161
|
/**
|
|
128
162
|
* Upper bound on subtasks per **round** — a core invariant: a delegating round
|
|
129
|
-
* emits `1..maxSubtasks` subtasks, which is also what bounds its fan-out (
|
|
130
|
-
*
|
|
163
|
+
* emits `1..maxSubtasks` subtasks, which is also what bounds its fan-out (they
|
|
164
|
+
* all run concurrently, with no other concurrency cap).
|
|
131
165
|
*
|
|
132
166
|
* Not a budget but a shape: it is what the delegation schema offers the model,
|
|
133
167
|
* and the data layer re-checks it as the durable guard.
|
|
@@ -181,4 +215,3 @@ export declare class ConfigError extends Error {
|
|
|
181
215
|
* reads the same object.
|
|
182
216
|
*/
|
|
183
217
|
export declare function resolveConfig(overrides: CoreConfigOverrides): CoreConfig;
|
|
184
|
-
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -11,6 +11,15 @@
|
|
|
11
11
|
* The distinction against {@link file://./platform.ts} stays sharp: nothing here
|
|
12
12
|
* is a platform fact, and nothing there is tunable.
|
|
13
13
|
*/
|
|
14
|
+
import { STEP_TIMEOUT_MS } from "./platform.js";
|
|
15
|
+
/**
|
|
16
|
+
* Ceiling on {@link ModelConfig.maxRetries}.
|
|
17
|
+
*
|
|
18
|
+
* Derived, not chosen: each honoured `retry-after` can be up to 60s and they all
|
|
19
|
+
* run inside one `step.do`, so this holds the worst case to a small fraction of
|
|
20
|
+
* {@link STEP_TIMEOUT_MS} and leaves the round its own time to actually work.
|
|
21
|
+
*/
|
|
22
|
+
const MAX_MODEL_RETRIES = 4;
|
|
14
23
|
/**
|
|
15
24
|
* A working baseline. Every value is overridable; none is a ceiling. These are
|
|
16
25
|
* the values both predecessor agents converged on in production, so they are a
|
|
@@ -23,8 +32,16 @@ export const DEFAULT_CORE_CONFIG = {
|
|
|
23
32
|
// Not a model: an AI Gateway slug, and `"default"` is Cloudflare's own
|
|
24
33
|
// auto-provision behaviour rather than a choice core is making for anyone.
|
|
25
34
|
aiGatewayId: "default",
|
|
35
|
+
// The provider-native Anthropic endpoint, which is what a deployment with
|
|
36
|
+
// no custom provider registered has. Agents that must own the credential
|
|
37
|
+
// themselves override this with their `custom-*` slug.
|
|
38
|
+
aiGatewayProvider: "anthropic",
|
|
26
39
|
maxOutputTokens: 16_384,
|
|
27
|
-
reasoningEffort: "medium"
|
|
40
|
+
reasoningEffort: "medium",
|
|
41
|
+
// Two, which is the AI SDK's own default and enough to ride out the kind of
|
|
42
|
+
// rate limit that clears in seconds. Raising it trades round latency for
|
|
43
|
+
// resilience; see {@link ModelConfig.maxRetries} for the ceiling and why.
|
|
44
|
+
maxRetries: 2
|
|
28
45
|
},
|
|
29
46
|
mainAgentLimits: { maxTurns: 20, maxWallMs: 60 * 60_000 },
|
|
30
47
|
subagentLimits: { maxTurns: 20, maxWallMs: 30 * 60_000 },
|
|
@@ -99,6 +116,18 @@ export function resolveConfig(overrides) {
|
|
|
99
116
|
positive(config.toolOutputWindow, "toolOutputWindow");
|
|
100
117
|
positive(config.maxSubtasks, "maxSubtasks");
|
|
101
118
|
positive(config.model.maxOutputTokens, "model.maxOutputTokens");
|
|
119
|
+
// Zero is legal (it opts out), so this is not `positive`. The ceiling is the
|
|
120
|
+
// step timeout: retries happen inside `step.do("turn:<round>")`, and the AI
|
|
121
|
+
// SDK honours a `retry-after` of up to 60s per attempt — so `maxRetries`
|
|
122
|
+
// minutes of waiting inside one step, before the round has spent a single
|
|
123
|
+
// token of its own. The message below reads the real number off `platform.ts`.
|
|
124
|
+
if (!Number.isInteger(config.model.maxRetries) ||
|
|
125
|
+
config.model.maxRetries < 0 ||
|
|
126
|
+
config.model.maxRetries > MAX_MODEL_RETRIES) {
|
|
127
|
+
throw new ConfigError(`model.maxRetries must be an integer between 0 and ${MAX_MODEL_RETRIES}, got ` +
|
|
128
|
+
`${config.model.maxRetries} — retries run inside one Workflow step, and each ` +
|
|
129
|
+
`honoured retry-after can be up to 60s against a ${STEP_TIMEOUT_MS / 60_000}-minute step timeout`);
|
|
130
|
+
}
|
|
102
131
|
// See SessionConfig.compactTailTokens — below this gap the fixed floor eats
|
|
103
132
|
// the headroom and compaction fires on nearly every append.
|
|
104
133
|
const headroom = config.session.compactAfterTokens - config.session.compactTailTokens;
|
|
@@ -108,4 +137,3 @@ export function resolveConfig(overrides) {
|
|
|
108
137
|
}
|
|
109
138
|
return config;
|
|
110
139
|
}
|
|
111
|
-
//# sourceMappingURL=config.js.map
|
package/dist/contract/index.d.ts
CHANGED
|
@@ -7,4 +7,3 @@
|
|
|
7
7
|
export { PLUGIN_CONTRACT_VERSION, definePlugin, type AgentPlugin, type EmitProgress, type EnrichResultContext, type MainAgentToolContext, type PluginRequirements, type RecipeToolSet, type ResolveRuntimeContext, type ToolFamilyBuilder, type ToolFamilyContext, type TurnGateContext } from "./plugin.js";
|
|
8
8
|
export type { DelegationNames, RecipeLimits, ResolvedRecipe, SubtaskParams, SubtaskParamsSchema, SubtaskParamsShape, SubtaskTypeSpec, ValidatedRecipe } from "./recipe.js";
|
|
9
9
|
export { RecipeValidationError, resolveLimits, validateRecipe, type RecipePolicy } from "./validation.js";
|
|
10
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/contract/index.js
CHANGED