@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
|
@@ -41,8 +41,22 @@ export declare function makeDelegateTool(types: SubtaskTypeRegistry, maxSubtasks
|
|
|
41
41
|
/**
|
|
42
42
|
* The call's id, derived from the parent Task and the round that emitted it —
|
|
43
43
|
* deterministic and replay-safe, the same discipline as the Session message ids
|
|
44
|
-
* it sits alongside (see {@link file://../history.ts}). Later rounds rebuild it
|
|
44
|
+
* it sits alongside (see {@link file://../agent/history.ts}). Later rounds rebuild it
|
|
45
45
|
* rather than storing it.
|
|
46
|
+
*
|
|
47
|
+
* **Underscores, not colons, and this is load-bearing.** Unlike a Session message
|
|
48
|
+
* id, this one is sent to a provider as a `tool_use.id`, and Anthropic validates
|
|
49
|
+
* that field against `^[a-zA-Z0-9_-]+$`. The colon-separated form this used to
|
|
50
|
+
* return failed every round from the first delegation onwards — round 0 was fine
|
|
51
|
+
* because the model authors its own ids, and round 1 reconstructs this one, so
|
|
52
|
+
* the request 400d deterministically on both the primary and the fallback until
|
|
53
|
+
* the deterministic join fired. Workers AI never validated the field, which is
|
|
54
|
+
* why it took a Claude-backed agent to surface it.
|
|
55
|
+
*
|
|
56
|
+
* Nothing persists this: both halves of the pair are rebuilt together on every
|
|
57
|
+
* request, so changing the shape needs no migration. See
|
|
58
|
+
* {@link file://../agent/anthropic/prompt.ts providerSafeToolCallId} for the
|
|
59
|
+
* backstop that catches the next one of these.
|
|
46
60
|
*/
|
|
47
61
|
export declare function delegateToolCallId(taskId: string, round: number): string;
|
|
48
62
|
/**
|
|
@@ -71,8 +85,12 @@ export type DelegateSubtaskOutcome = {
|
|
|
71
85
|
* `referenceIndexes` is omitted rather than faked: this round's references were
|
|
72
86
|
* snapshotted verbatim onto the rows when it ran, and the catalog they were
|
|
73
87
|
* chosen from is long gone.
|
|
88
|
+
*
|
|
89
|
+
* A subtask proposal carries no identifier of its own, so the model pairs each
|
|
90
|
+
* entry here with its outcome **by position**: both arrays are built from the
|
|
91
|
+
* same ordinal-ordered `branches`, and the outcome additionally repeats `type`
|
|
92
|
+
* and carries the durable `subtaskId`.
|
|
74
93
|
*/
|
|
75
94
|
export declare function delegateCallInput(reply: string, branches: CompositionBranch[]): DecompositionProposal;
|
|
76
95
|
/** Rebuild one round's call result from its durable rows, in stable ordinal order. */
|
|
77
96
|
export declare function delegateCallOutput(branches: CompositionBranch[]): DelegateSubtaskOutcome[];
|
|
78
|
-
//# sourceMappingURL=delegate.d.ts.map
|
|
@@ -47,23 +47,25 @@ export function makeDelegateTool(types, maxSubtasks) {
|
|
|
47
47
|
/**
|
|
48
48
|
* The call's id, derived from the parent Task and the round that emitted it —
|
|
49
49
|
* deterministic and replay-safe, the same discipline as the Session message ids
|
|
50
|
-
* it sits alongside (see {@link file://../history.ts}). Later rounds rebuild it
|
|
50
|
+
* it sits alongside (see {@link file://../agent/history.ts}). Later rounds rebuild it
|
|
51
51
|
* rather than storing it.
|
|
52
|
-
*/
|
|
53
|
-
export function delegateToolCallId(taskId, round) {
|
|
54
|
-
return `task:${taskId}:round:${round}:delegate`;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* The draft-local key a reconstructed call uses for a durable Subtask.
|
|
58
52
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
53
|
+
* **Underscores, not colons, and this is load-bearing.** Unlike a Session message
|
|
54
|
+
* id, this one is sent to a provider as a `tool_use.id`, and Anthropic validates
|
|
55
|
+
* that field against `^[a-zA-Z0-9_-]+$`. The colon-separated form this used to
|
|
56
|
+
* return failed every round from the first delegation onwards — round 0 was fine
|
|
57
|
+
* because the model authors its own ids, and round 1 reconstructs this one, so
|
|
58
|
+
* the request 400d deterministically on both the primary and the fallback until
|
|
59
|
+
* the deterministic join fired. Workers AI never validated the field, which is
|
|
60
|
+
* why it took a Claude-backed agent to surface it.
|
|
61
|
+
*
|
|
62
|
+
* Nothing persists this: both halves of the pair are rebuilt together on every
|
|
63
|
+
* request, so changing the shape needs no migration. See
|
|
64
|
+
* {@link file://../agent/anthropic/prompt.ts providerSafeToolCallId} for the
|
|
65
|
+
* backstop that catches the next one of these.
|
|
64
66
|
*/
|
|
65
|
-
function
|
|
66
|
-
return `
|
|
67
|
+
export function delegateToolCallId(taskId, round) {
|
|
68
|
+
return `task_${taskId}_round_${round}_delegate`;
|
|
67
69
|
}
|
|
68
70
|
/**
|
|
69
71
|
* Rebuild one round's call input from its durable rows, in stable ordinal order.
|
|
@@ -74,15 +76,18 @@ function localKeyForId(id) {
|
|
|
74
76
|
* `referenceIndexes` is omitted rather than faked: this round's references were
|
|
75
77
|
* snapshotted verbatim onto the rows when it ran, and the catalog they were
|
|
76
78
|
* chosen from is long gone.
|
|
79
|
+
*
|
|
80
|
+
* A subtask proposal carries no identifier of its own, so the model pairs each
|
|
81
|
+
* entry here with its outcome **by position**: both arrays are built from the
|
|
82
|
+
* same ordinal-ordered `branches`, and the outcome additionally repeats `type`
|
|
83
|
+
* and carries the durable `subtaskId`.
|
|
77
84
|
*/
|
|
78
85
|
export function delegateCallInput(reply, branches) {
|
|
79
86
|
return {
|
|
80
87
|
reply,
|
|
81
88
|
subtasks: branches.map((branch) => ({
|
|
82
|
-
localKey: localKeyForId(branch.subtaskId),
|
|
83
89
|
type: branch.type,
|
|
84
90
|
prompt: branch.prompt,
|
|
85
|
-
dependsOn: branch.dependsOn.map(localKeyForId),
|
|
86
91
|
// Reconstructed verbatim from the row: a later round must see the same
|
|
87
92
|
// params the call really carried, or it cannot reason about what ran.
|
|
88
93
|
params: branch.params
|
|
@@ -100,4 +105,3 @@ export function delegateCallOutput(branches) {
|
|
|
100
105
|
: null
|
|
101
106
|
}));
|
|
102
107
|
}
|
|
103
|
-
//# sourceMappingURL=delegate.js.map
|
package/dist/subtasks/index.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@loopingai/core/subtasks` — the delegation layer: what a round may hand out,
|
|
3
|
-
* how a proposal becomes durable drafts
|
|
3
|
+
* and how a proposal becomes durable drafts.
|
|
4
4
|
*/
|
|
5
5
|
export { makeSubtaskTypes, SubtaskParamsError, type SubtaskTypeRegistry } from "./subtask-types.js";
|
|
6
6
|
export { DecompositionValidationError, makeDecompositionProposalSchema, nonBlank, resolveDecomposition } from "./decomposition.js";
|
|
7
7
|
export { DELEGATE_TOOL_NAME, makeDelegateTool, delegateToolCallId, delegateCallInput, delegateCallOutput, type DelegateSubtaskOutcome } from "./delegate.js";
|
|
8
|
-
export { selectWave, type WaveDecision } from "./scheduler.js";
|
|
9
8
|
export { isCatalogEligible, type ReferenceCatalogEntry } from "./catalog.js";
|
|
10
9
|
export * from "./types.js";
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/subtasks/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@loopingai/core/subtasks` — the delegation layer: what a round may hand out,
|
|
3
|
-
* how a proposal becomes durable drafts
|
|
3
|
+
* and how a proposal becomes durable drafts.
|
|
4
4
|
*/
|
|
5
5
|
export { makeSubtaskTypes, SubtaskParamsError } from "./subtask-types.js";
|
|
6
6
|
export { DecompositionValidationError, makeDecompositionProposalSchema, nonBlank, resolveDecomposition } from "./decomposition.js";
|
|
7
7
|
export { DELEGATE_TOOL_NAME, makeDelegateTool, delegateToolCallId, delegateCallInput, delegateCallOutput } from "./delegate.js";
|
|
8
|
-
export { selectWave } from "./scheduler.js";
|
|
9
8
|
export { isCatalogEligible } from "./catalog.js";
|
|
10
9
|
export * from "./types.js";
|
|
11
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -78,14 +78,6 @@ export interface SubtaskTypeRegistry {
|
|
|
78
78
|
paramProperties(): Record<string, z.ZodType<string | undefined>>;
|
|
79
79
|
/** The type catalogue as the delegating model is shown it. */
|
|
80
80
|
renderTypes(): string;
|
|
81
|
-
/**
|
|
82
|
-
* Every type's {@link SubtaskTypeSpec.capability}, for the main agent's soul.
|
|
83
|
-
*
|
|
84
|
-
* Returns `""` when no type declares one, and that case is worth naming: it is
|
|
85
|
-
* what lets each call site append unconditionally instead of emitting a
|
|
86
|
-
* separator around nothing.
|
|
87
|
-
*/
|
|
88
|
-
renderCapabilities(): string;
|
|
89
81
|
/** Every type's {@link SubtaskTypeSpec.delegationGuidance}, for the round contract. */
|
|
90
82
|
renderDelegationGuidance(names: DelegationNames): string;
|
|
91
83
|
}
|
|
@@ -97,4 +89,3 @@ export interface SubtaskTypeRegistry {
|
|
|
97
89
|
* routed to the wrong domain.
|
|
98
90
|
*/
|
|
99
91
|
export declare function makeSubtaskTypes(specs: readonly SubtaskTypeSpec[]): SubtaskTypeRegistry;
|
|
100
|
-
//# sourceMappingURL=subtask-types.d.ts.map
|
|
@@ -91,13 +91,6 @@ export function makeSubtaskTypes(specs) {
|
|
|
91
91
|
})
|
|
92
92
|
.join("\n");
|
|
93
93
|
},
|
|
94
|
-
renderCapabilities() {
|
|
95
|
-
const blocks = [];
|
|
96
|
-
for (const s of specs)
|
|
97
|
-
if (s.capability)
|
|
98
|
-
blocks.push(s.capability);
|
|
99
|
-
return blocks.join("\n\n");
|
|
100
|
-
},
|
|
101
94
|
renderDelegationGuidance(names) {
|
|
102
95
|
const sections = [];
|
|
103
96
|
for (const s of specs) {
|
|
@@ -108,4 +101,3 @@ export function makeSubtaskTypes(specs) {
|
|
|
108
101
|
}
|
|
109
102
|
};
|
|
110
103
|
}
|
|
111
|
-
//# sourceMappingURL=subtask-types.js.map
|
package/dist/subtasks/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ResolvedRecipe, SubtaskParams } from "../contract/recipe.js";
|
|
2
|
-
|
|
2
|
+
import type { RoundFailureKind } from "../agent/inference.js";
|
|
3
|
+
export type SubtaskStatus = "pending" | "running" | "completed" | "failed" | "canceled";
|
|
3
4
|
/** A per-caller, SQLite-assigned, monotonically increasing Subtask identifier. */
|
|
4
5
|
export type SubtaskId = number;
|
|
5
6
|
/**
|
|
@@ -22,18 +23,15 @@ export interface SubtaskResultPart {
|
|
|
22
23
|
text: string;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
|
-
* Creation input for one Subtask, before it is persisted. `
|
|
26
|
-
* draft
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* Creation input for one Subtask, before it is persisted. `ordinal` is derived
|
|
27
|
+
* from the draft's position in the decomposition array, which is the only thing
|
|
28
|
+
* that distinguishes one draft of a decomposition from another — they carry no
|
|
29
|
+
* identity of their own until the data layer assigns a {@link SubtaskId}.
|
|
29
30
|
*/
|
|
30
31
|
export interface SubtaskDraft {
|
|
31
|
-
localKey: string;
|
|
32
32
|
type: string;
|
|
33
33
|
prompt: string;
|
|
34
34
|
references: SubtaskReference[];
|
|
35
|
-
/** Draft-local keys of prerequisite drafts. */
|
|
36
|
-
dependsOn: string[];
|
|
37
35
|
/** The type's required inputs, already validated for shape. */
|
|
38
36
|
params: SubtaskParams;
|
|
39
37
|
}
|
|
@@ -93,24 +91,11 @@ export interface SubtaskChunkOutcome {
|
|
|
93
91
|
status: SubtaskStatus;
|
|
94
92
|
progress: ProgressEvent[];
|
|
95
93
|
}
|
|
96
|
-
/**
|
|
97
|
-
* Generated output of one completed prerequisite Subtask, loaded by the parent
|
|
98
|
-
* from its durable row for a dependent's invocation. `type` is the
|
|
99
|
-
* prerequisite's semantic type — used only to label the rendered section;
|
|
100
|
-
* dependency output is always presented as generated, never as conversation
|
|
101
|
-
* evidence.
|
|
102
|
-
*/
|
|
103
|
-
export interface DependencyResult {
|
|
104
|
-
subtaskId: SubtaskId;
|
|
105
|
-
type: string;
|
|
106
|
-
resultParts: SubtaskResultPart[];
|
|
107
|
-
}
|
|
108
94
|
/**
|
|
109
95
|
* RPC-safe input for one isolated `RecipeSubagent` execution, assembled by the
|
|
110
96
|
* parent at execution start: the already-resolved (and code-validated) Recipe,
|
|
111
|
-
* the Subtask's non-session prompt, its verbatim reference snapshots
|
|
112
|
-
*
|
|
113
|
-
* Recipe defensively but never resolves one itself.
|
|
97
|
+
* the Subtask's non-session prompt, and its verbatim reference snapshots. The
|
|
98
|
+
* child re-validates the Recipe defensively but never resolves one itself.
|
|
114
99
|
*/
|
|
115
100
|
export interface RecipeExecutionRequest {
|
|
116
101
|
taskId: string;
|
|
@@ -124,7 +109,6 @@ export interface RecipeExecutionRequest {
|
|
|
124
109
|
recipe: ResolvedRecipe;
|
|
125
110
|
prompt: string;
|
|
126
111
|
references: SubtaskReference[];
|
|
127
|
-
dependencyResults: DependencyResult[];
|
|
128
112
|
/**
|
|
129
113
|
* The Subtask's validated params. Part of the execution's identity — two plays
|
|
130
114
|
* of different games are different work — so this IS fingerprinted, unlike
|
|
@@ -154,11 +138,9 @@ export type RecipeExecutionResult = {
|
|
|
154
138
|
* One Subtask as the delegating model emits it. The model selects references
|
|
155
139
|
* by **catalog index only** — it never emits reference text, and application code
|
|
156
140
|
* snapshots the catalog entry's exact role+text onto the Subtask (see
|
|
157
|
-
* `agent/subtasks/decomposition.ts`).
|
|
158
|
-
* to SQLite-assigned {@link SubtaskId}s by the data layer.
|
|
141
|
+
* `agent/subtasks/decomposition.ts`).
|
|
159
142
|
*/
|
|
160
143
|
export interface SubtaskProposal {
|
|
161
|
-
localKey: string;
|
|
162
144
|
type: string;
|
|
163
145
|
prompt: string;
|
|
164
146
|
/**
|
|
@@ -167,8 +149,6 @@ export interface SubtaskProposal {
|
|
|
167
149
|
* *reconstructed* historical call, whose references were resolved rounds ago.
|
|
168
150
|
*/
|
|
169
151
|
referenceIndexes?: number[];
|
|
170
|
-
/** Draft-local keys of prerequisite proposals. */
|
|
171
|
-
dependsOn: string[];
|
|
172
152
|
/** The type's required inputs; omitted for a type that takes none. */
|
|
173
153
|
params?: SubtaskParams;
|
|
174
154
|
}
|
|
@@ -188,18 +168,19 @@ export interface DecompositionProposal {
|
|
|
188
168
|
*
|
|
189
169
|
* `replied` is the terminal answer — the round chose to answer the user rather
|
|
190
170
|
* than delegate, and the Workflow delivers it. `delegated` means the round's
|
|
191
|
-
* Subtask rows are durable and
|
|
192
|
-
* begins. `failed` means
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
* (mirrors
|
|
171
|
+
* Subtask rows are durable and the Workflow should execute them, after which
|
|
172
|
+
* another round begins. `failed` means the round produced no answer, with
|
|
173
|
+
* {@link RoundFailureKind} carrying why; no Subtask is ever synthesized to cover
|
|
174
|
+
* for it. `canceled` means the caller cancelled during the round: nothing was
|
|
175
|
+
* persisted and nothing was published. Transient platform faults are not
|
|
176
|
+
* results: they throw so the enclosing Workflow step can retry (mirrors
|
|
177
|
+
* {@link RecipeExecutionResult}).
|
|
197
178
|
*
|
|
198
179
|
* `turns` is what this round cost, which the Workflow meters against the Task's
|
|
199
180
|
* budget. This is the **only** type that carries it, and it carries it because the
|
|
200
181
|
* count has to cross an RPC boundary to reach a Workflow in another isolate;
|
|
201
|
-
* everything inside the DO shares one mutable
|
|
202
|
-
* instead. The field is attached in a single place — see `runTaskTurn` — so no
|
|
182
|
+
* everything inside the DO shares one mutable
|
|
183
|
+
* {@link file://../agent/budget.ts TurnBudget} instead. The field is attached in a single place — see `runTaskTurn` — so no
|
|
203
184
|
* branch can drop it and no branch can invent it.
|
|
204
185
|
*
|
|
205
186
|
* The idempotent recovery paths — a round replayed from durable rows rather than
|
|
@@ -220,8 +201,17 @@ export type TurnTaskResult = {
|
|
|
220
201
|
reply: string;
|
|
221
202
|
subtasks: Subtask[];
|
|
222
203
|
turns: number;
|
|
223
|
-
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* `kind` distinguishes a round that spent both models and got nothing usable
|
|
207
|
+
* (`exhausted`) from one that stopped on a fault no attempt could clear —
|
|
208
|
+
* where the fallback was deliberately *not* tried, and the kind is what lets
|
|
209
|
+
* the host say why in words an operator can act on. Same terminal Task either
|
|
210
|
+
* way; only the words differ.
|
|
211
|
+
*/
|
|
212
|
+
| {
|
|
224
213
|
status: "failed";
|
|
214
|
+
kind: RoundFailureKind;
|
|
225
215
|
error: string;
|
|
226
216
|
turns: number;
|
|
227
217
|
} | {
|
|
@@ -243,15 +233,13 @@ export type TurnVerdict = WithoutTurns<TurnTaskResult>;
|
|
|
243
233
|
/**
|
|
244
234
|
* One branch's outcome as a later round sees it — a plain, RPC-safe subset of the
|
|
245
235
|
* durable {@link Subtask} row, loaded across **every** round in stable ordinal
|
|
246
|
-
* order. Completed
|
|
247
|
-
*
|
|
236
|
+
* order. Completed and failed branches are both included so the reply can use
|
|
237
|
+
* available successes and disclose relevant failures.
|
|
248
238
|
*
|
|
249
|
-
* Carries `round
|
|
250
|
-
*
|
|
251
|
-
* `agent/subtasks/delegate.ts`).
|
|
252
|
-
*
|
|
253
|
-
* that keeps the scheduler's view narrow does not apply. `references` still stays
|
|
254
|
-
* out: it is unbounded history text, and the call's shape does not need it.
|
|
239
|
+
* Carries `round` and `prompt` — not for composing, but for reconstructing the
|
|
240
|
+
* per-round `delegate` call that produced these branches (see
|
|
241
|
+
* `agent/subtasks/delegate.ts`). `references` stays out: it is unbounded history
|
|
242
|
+
* text, and the call's shape does not need it.
|
|
255
243
|
*/
|
|
256
244
|
export interface CompositionBranch {
|
|
257
245
|
subtaskId: SubtaskId;
|
|
@@ -259,41 +247,29 @@ export interface CompositionBranch {
|
|
|
259
247
|
ordinal: number;
|
|
260
248
|
type: string;
|
|
261
249
|
prompt: string;
|
|
262
|
-
dependsOn: SubtaskId[];
|
|
263
250
|
params: SubtaskParams;
|
|
264
251
|
status: SubtaskStatus;
|
|
265
252
|
resultParts: SubtaskResultPart[] | null;
|
|
266
253
|
error: string | null;
|
|
267
254
|
}
|
|
268
255
|
/**
|
|
269
|
-
* The `scan:<
|
|
270
|
-
*
|
|
271
|
-
* the
|
|
272
|
-
* round trip, and no gap between asking and acting.
|
|
256
|
+
* The `scan:<round>` projection (RPC-safe): either the caller cancelled, or the
|
|
257
|
+
* ids of the round's Subtasks that still owe an outcome, in ordinal order.
|
|
258
|
+
* Returning the verdict with the ids is what lets the Workflow drop its separate
|
|
259
|
+
* cancellation probe — one round trip, and no gap between asking and acting.
|
|
260
|
+
*
|
|
261
|
+
* Ids and nothing else, deliberately: a Workflow step return is capped at 1 MiB
|
|
262
|
+
* and a Subtask carries verbatim history snapshots bounded only by
|
|
263
|
+
* `MAX_INBOUND_TEXT_BYTES`, so a scan returning rows would overflow on a large
|
|
264
|
+
* task. The durable rows are the source of truth; the Workflow carries
|
|
265
|
+
* references to them and re-reads through the parent when it needs more.
|
|
273
266
|
*/
|
|
274
267
|
export type SubtaskScan = {
|
|
275
268
|
canceled: true;
|
|
276
269
|
} | {
|
|
277
270
|
canceled: false;
|
|
278
|
-
|
|
271
|
+
ids: SubtaskId[];
|
|
279
272
|
};
|
|
280
|
-
/**
|
|
281
|
-
* The scheduler's view of one Subtask (Phase 2) — everything needed to pick the
|
|
282
|
-
* next dependency-ready wave, and nothing else.
|
|
283
|
-
*
|
|
284
|
-
* Deliberately excludes `prompt`, `references`, and `resultParts`: a Workflow
|
|
285
|
-
* step return is capped at 1 MiB, and a reference is a verbatim history snapshot
|
|
286
|
-
* bounded only by `MAX_INBOUND_TEXT_BYTES`, so a wave scan returning full rows
|
|
287
|
-
* would overflow on a large task. The durable rows — not Workflow state — are the
|
|
288
|
-
* source of truth, so the Workflow carries ids and statuses and re-reads the rest
|
|
289
|
-
* through the parent when it actually needs it.
|
|
290
|
-
*/
|
|
291
|
-
export interface SubtaskNode {
|
|
292
|
-
id: SubtaskId;
|
|
293
|
-
ordinal: number;
|
|
294
|
-
status: SubtaskStatus;
|
|
295
|
-
dependsOn: SubtaskId[];
|
|
296
|
-
}
|
|
297
273
|
/** Durable state owned by the main agent for one delegated unit of work. */
|
|
298
274
|
export interface Subtask {
|
|
299
275
|
id: SubtaskId;
|
|
@@ -307,7 +283,6 @@ export interface Subtask {
|
|
|
307
283
|
recipeVersion: number | null;
|
|
308
284
|
prompt: string;
|
|
309
285
|
references: SubtaskReference[];
|
|
310
|
-
dependsOn: SubtaskId[];
|
|
311
286
|
/** The type's required inputs, validated at delegation time. */
|
|
312
287
|
params: SubtaskParams;
|
|
313
288
|
status: SubtaskStatus;
|
|
@@ -318,4 +293,3 @@ export interface Subtask {
|
|
|
318
293
|
completedAt: number | null;
|
|
319
294
|
}
|
|
320
295
|
export {};
|
|
321
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/subtasks/types.js
CHANGED
package/dist/testing/auth.d.ts
CHANGED
|
@@ -32,4 +32,3 @@ export interface GatewayTokenOptions {
|
|
|
32
32
|
export declare const TEST_TENANT = "main";
|
|
33
33
|
/** Sign a short-lived EdDSA gateway JWT using the test gateway key. */
|
|
34
34
|
export declare function makeGatewayToken(options?: GatewayTokenOptions): Promise<string>;
|
|
35
|
-
//# sourceMappingURL=auth.d.ts.map
|
package/dist/testing/auth.js
CHANGED
package/dist/testing/do.d.ts
CHANGED
package/dist/testing/do.js
CHANGED
|
@@ -62,4 +62,3 @@ export declare function testStatus(state: TaskState, message?: Message): NonNull
|
|
|
62
62
|
export declare function testAgentMessage(messageId: string, text: string, contextId?: string, taskId?: string): Message;
|
|
63
63
|
/** A complete v1.0 `Task` in the given state. */
|
|
64
64
|
export declare function testTask(id: string, contextId: string, state: TaskState, message?: Message): Task;
|
|
65
|
-
//# sourceMappingURL=fixtures.d.ts.map
|
package/dist/testing/fixtures.js
CHANGED
package/dist/testing/harness.js
CHANGED
package/dist/testing/index.d.ts
CHANGED
|
@@ -29,4 +29,3 @@ export { makeGatewayToken, type GatewayTokenOptions } from "./auth.js";
|
|
|
29
29
|
export { AGENT_ORIGIN, GATEWAY_ORIGIN, TEST_AGENT_PRIVATE_JWK, TEST_GATEWAY_PRIVATE_JWK, TEST_MODELS, gatewayPublicJwks, testAgentMessage, testStatus, testTask } from "./fixtures.js";
|
|
30
30
|
export { doStorage, makeDoHelpers, type DoTestHelpers } from "./do.js";
|
|
31
31
|
export { createAgentHarness, type AgentHarness, type AgentHarnessOptions, type CapturedCallback, type HarnessWorker } from "./harness.js";
|
|
32
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/testing/index.js
CHANGED
|
@@ -29,4 +29,3 @@ export { makeGatewayToken } from "./auth.js";
|
|
|
29
29
|
export { AGENT_ORIGIN, GATEWAY_ORIGIN, TEST_AGENT_PRIVATE_JWK, TEST_GATEWAY_PRIVATE_JWK, TEST_MODELS, gatewayPublicJwks, testAgentMessage, testStatus, testTask } from "./fixtures.js";
|
|
30
30
|
export { doStorage, makeDoHelpers } from "./do.js";
|
|
31
31
|
export { createAgentHarness } from "./harness.js";
|
|
32
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -40,4 +40,38 @@ export declare function finalReply(text: string, opts?: {
|
|
|
40
40
|
* last step.
|
|
41
41
|
*/
|
|
42
42
|
export declare function mockModel(...steps: MockStep[]): MockLanguageModelV3;
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* A model whose every call throws, and a count of how many times it was asked.
|
|
45
|
+
*
|
|
46
|
+
* The count is the point. Several of the attempt ladder's rules are about a call
|
|
47
|
+
* that must *not* happen — a fallback slot left unspent, a repair not attempted
|
|
48
|
+
* — and those are invisible to an assertion on the returned outcome alone, which
|
|
49
|
+
* can be right for the wrong reason.
|
|
50
|
+
*/
|
|
51
|
+
export declare function throwingModel(error: unknown): {
|
|
52
|
+
model: MockLanguageModelV3;
|
|
53
|
+
calls: () => number;
|
|
54
|
+
};
|
|
55
|
+
/** {@link mockModel}, plus the same call count {@link throwingModel} reports. */
|
|
56
|
+
export declare function countingModel(...steps: MockStep[]): {
|
|
57
|
+
model: MockLanguageModelV3;
|
|
58
|
+
calls: () => number;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* A model that fails the first `failures` calls with a retryable `APICallError`,
|
|
62
|
+
* then behaves like {@link mockModel}.
|
|
63
|
+
*
|
|
64
|
+
* Exists for the one behaviour a scripted-outcome assertion cannot see: whether
|
|
65
|
+
* a rate limit was *waited out on the same model* or fell straight through to
|
|
66
|
+
* the fallback. Only the call count distinguishes them — both produce a
|
|
67
|
+
* successful round.
|
|
68
|
+
*
|
|
69
|
+
* `retry-after: 0` is deliberate. The AI SDK honours the header and its own
|
|
70
|
+
* backoff opens at two seconds, which would spend real seconds asserting
|
|
71
|
+
* something that has nothing to do with duration. Zero exercises the identical
|
|
72
|
+
* path — header parsed, preferred over the exponential delay, waited — for free.
|
|
73
|
+
*/
|
|
74
|
+
export declare function rateLimitedModel(failures: number, ...steps: MockStep[]): {
|
|
75
|
+
model: MockLanguageModelV3;
|
|
76
|
+
calls: () => number;
|
|
77
|
+
};
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { MockLanguageModelV3 } from "ai/test";
|
|
2
|
+
// From `ai`, not `@ai-sdk/provider`. `ai` re-exports the class and is a declared
|
|
3
|
+
// peer; reaching for the provider package directly makes this module — which is
|
|
4
|
+
// on the published `/testing` subpath every consumer loads — depend on a package
|
|
5
|
+
// core does not declare and only resolves today by hoisting.
|
|
6
|
+
import { APICallError } from "ai";
|
|
2
7
|
/**
|
|
3
8
|
* Test doubles for the LLM. Lets the tool-loop / executor specs run the real
|
|
4
9
|
* `generateText` machinery (tool execution, multi-step, fallback) against a
|
|
@@ -59,4 +64,73 @@ export function mockModel(...steps) {
|
|
|
59
64
|
doGenerate: async () => stepResult(steps[Math.min(i++, steps.length - 1)])
|
|
60
65
|
});
|
|
61
66
|
}
|
|
62
|
-
|
|
67
|
+
/**
|
|
68
|
+
* A model whose every call throws, and a count of how many times it was asked.
|
|
69
|
+
*
|
|
70
|
+
* The count is the point. Several of the attempt ladder's rules are about a call
|
|
71
|
+
* that must *not* happen — a fallback slot left unspent, a repair not attempted
|
|
72
|
+
* — and those are invisible to an assertion on the returned outcome alone, which
|
|
73
|
+
* can be right for the wrong reason.
|
|
74
|
+
*/
|
|
75
|
+
export function throwingModel(error) {
|
|
76
|
+
let calls = 0;
|
|
77
|
+
return {
|
|
78
|
+
model: new MockLanguageModelV3({
|
|
79
|
+
doGenerate: async () => {
|
|
80
|
+
calls += 1;
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}),
|
|
84
|
+
calls: () => calls
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** {@link mockModel}, plus the same call count {@link throwingModel} reports. */
|
|
88
|
+
export function countingModel(...steps) {
|
|
89
|
+
let calls = 0;
|
|
90
|
+
let i = 0;
|
|
91
|
+
return {
|
|
92
|
+
model: new MockLanguageModelV3({
|
|
93
|
+
doGenerate: async () => {
|
|
94
|
+
calls += 1;
|
|
95
|
+
return stepResult(steps[Math.min(i++, steps.length - 1)]);
|
|
96
|
+
}
|
|
97
|
+
}),
|
|
98
|
+
calls: () => calls
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A model that fails the first `failures` calls with a retryable `APICallError`,
|
|
103
|
+
* then behaves like {@link mockModel}.
|
|
104
|
+
*
|
|
105
|
+
* Exists for the one behaviour a scripted-outcome assertion cannot see: whether
|
|
106
|
+
* a rate limit was *waited out on the same model* or fell straight through to
|
|
107
|
+
* the fallback. Only the call count distinguishes them — both produce a
|
|
108
|
+
* successful round.
|
|
109
|
+
*
|
|
110
|
+
* `retry-after: 0` is deliberate. The AI SDK honours the header and its own
|
|
111
|
+
* backoff opens at two seconds, which would spend real seconds asserting
|
|
112
|
+
* something that has nothing to do with duration. Zero exercises the identical
|
|
113
|
+
* path — header parsed, preferred over the exponential delay, waited — for free.
|
|
114
|
+
*/
|
|
115
|
+
export function rateLimitedModel(failures, ...steps) {
|
|
116
|
+
let calls = 0;
|
|
117
|
+
let i = 0;
|
|
118
|
+
return {
|
|
119
|
+
model: new MockLanguageModelV3({
|
|
120
|
+
doGenerate: async () => {
|
|
121
|
+
calls += 1;
|
|
122
|
+
if (calls <= failures) {
|
|
123
|
+
throw new APICallError({
|
|
124
|
+
message: "429 Wholesale Rate limited",
|
|
125
|
+
url: "anthropic:messages:test",
|
|
126
|
+
requestBodyValues: {},
|
|
127
|
+
statusCode: 429,
|
|
128
|
+
responseHeaders: { "retry-after": "0" }
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return stepResult(steps[Math.min(i++, steps.length - 1)]);
|
|
132
|
+
}
|
|
133
|
+
}),
|
|
134
|
+
calls: () => calls
|
|
135
|
+
};
|
|
136
|
+
}
|
package/dist/testing/node.d.ts
CHANGED
|
@@ -54,4 +54,3 @@
|
|
|
54
54
|
export { createVcr, recordFromEnv, closeVcr, type Vcr, type VcrOptions, type VcrRequest, type VcrRequestHeaders, type VcrOutboundService } from "./vcr.js";
|
|
55
55
|
export { Cassette, requestKey, replayable, type CassetteEntry, type CassetteOptions, type RecordedRequest, type RecordedResponse, type ReplayableResponse } from "./vcr-store.js";
|
|
56
56
|
export { VCR_CONTROL_ORIGIN, VCR_MARKER_HEADER, CASSETTE_NAME_RE, type VcrReleaseResult } from "./vcr-shared.js";
|
|
57
|
-
//# sourceMappingURL=node.d.ts.map
|
package/dist/testing/node.js
CHANGED
|
@@ -6,10 +6,7 @@
|
|
|
6
6
|
* Belt and braces rather than load-bearing — each cassette is already flushed
|
|
7
7
|
* when its test releases it, so a run that ends normally has nothing left to do
|
|
8
8
|
* here, and a run that dies mid-test keeps everything recorded up to that point.
|
|
9
|
-
*
|
|
10
|
-
* and a self-refreshing auto-flush timer open, and a `RECORD=1` run hung on
|
|
11
|
-
* "close timed out" without it. Neither exists now.)
|
|
9
|
+
* The recorder holds no sockets and no timers, so nothing here has to close.
|
|
12
10
|
*/
|
|
13
11
|
export declare function setup(): void;
|
|
14
12
|
export declare function teardown(): Promise<void>;
|
|
15
|
-
//# sourceMappingURL=vcr-global-setup.d.ts.map
|
|
@@ -7,12 +7,9 @@ import { closeVcr } from "./vcr.js";
|
|
|
7
7
|
* Belt and braces rather than load-bearing — each cassette is already flushed
|
|
8
8
|
* when its test releases it, so a run that ends normally has nothing left to do
|
|
9
9
|
* here, and a run that dies mid-test keeps everything recorded up to that point.
|
|
10
|
-
*
|
|
11
|
-
* and a self-refreshing auto-flush timer open, and a `RECORD=1` run hung on
|
|
12
|
-
* "close timed out" without it. Neither exists now.)
|
|
10
|
+
* The recorder holds no sockets and no timers, so nothing here has to close.
|
|
13
11
|
*/
|
|
14
12
|
export function setup() { }
|
|
15
13
|
export async function teardown() {
|
|
16
14
|
await closeVcr();
|
|
17
15
|
}
|
|
18
|
-
//# sourceMappingURL=vcr-global-setup.js.map
|