@loopingai/core 0.1.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/LICENSE +674 -0
- package/README.md +279 -0
- package/dist/a2a/agent-stub.d.ts +61 -0
- package/dist/a2a/agent-stub.d.ts.map +1 -0
- package/dist/a2a/agent-stub.js +2 -0
- package/dist/a2a/agent-stub.js.map +1 -0
- package/dist/a2a/card.d.ts +119 -0
- package/dist/a2a/card.d.ts.map +1 -0
- package/dist/a2a/card.js +115 -0
- package/dist/a2a/card.js.map +1 -0
- package/dist/a2a/context.d.ts +14 -0
- package/dist/a2a/context.d.ts.map +1 -0
- package/dist/a2a/context.js +55 -0
- package/dist/a2a/context.js.map +1 -0
- package/dist/a2a/executor.d.ts +85 -0
- package/dist/a2a/executor.d.ts.map +1 -0
- package/dist/a2a/executor.js +107 -0
- package/dist/a2a/executor.js.map +1 -0
- package/dist/a2a/index.d.ts +18 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +17 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/a2a/notify.d.ts +75 -0
- package/dist/a2a/notify.d.ts.map +1 -0
- package/dist/a2a/notify.js +161 -0
- package/dist/a2a/notify.js.map +1 -0
- package/dist/a2a/parts.d.ts +46 -0
- package/dist/a2a/parts.d.ts.map +1 -0
- package/dist/a2a/parts.js +95 -0
- package/dist/a2a/parts.js.map +1 -0
- package/dist/a2a/task-store.d.ts +45 -0
- package/dist/a2a/task-store.d.ts.map +1 -0
- package/dist/a2a/task-store.js +100 -0
- package/dist/a2a/task-store.js.map +1 -0
- package/dist/a2a/task.d.ts +86 -0
- package/dist/a2a/task.d.ts.map +1 -0
- package/dist/a2a/task.js +16 -0
- package/dist/a2a/task.js.map +1 -0
- package/dist/a2a/verify.d.ts +64 -0
- package/dist/a2a/verify.d.ts.map +1 -0
- package/dist/a2a/verify.js +122 -0
- package/dist/a2a/verify.js.map +1 -0
- package/dist/agent/budget.d.ts +47 -0
- package/dist/agent/budget.d.ts.map +1 -0
- package/dist/agent/budget.js +43 -0
- package/dist/agent/budget.js.map +1 -0
- package/dist/agent/control.d.ts +110 -0
- package/dist/agent/control.d.ts.map +1 -0
- package/dist/agent/control.js +115 -0
- package/dist/agent/control.js.map +1 -0
- package/dist/agent/final-reply.d.ts +49 -0
- package/dist/agent/final-reply.d.ts.map +1 -0
- package/dist/agent/final-reply.js +52 -0
- package/dist/agent/final-reply.js.map +1 -0
- package/dist/agent/history.d.ts +83 -0
- package/dist/agent/history.d.ts.map +1 -0
- package/dist/agent/history.js +117 -0
- package/dist/agent/history.js.map +1 -0
- package/dist/agent/index.d.ts +17 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +17 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/inference.d.ts +52 -0
- package/dist/agent/inference.d.ts.map +1 -0
- package/dist/agent/inference.js +79 -0
- package/dist/agent/inference.js.map +1 -0
- package/dist/agent/model.d.ts +75 -0
- package/dist/agent/model.d.ts.map +1 -0
- package/dist/agent/model.js +62 -0
- package/dist/agent/model.js.map +1 -0
- package/dist/agent/session.d.ts +92 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +80 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/config.d.ts +159 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +92 -0
- package/dist/config.js.map +1 -0
- package/dist/contract/index.d.ts +10 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +9 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/plugin.d.ts +163 -0
- package/dist/contract/plugin.d.ts.map +1 -0
- package/dist/contract/plugin.js +39 -0
- package/dist/contract/plugin.js.map +1 -0
- package/dist/contract/recipe.d.ts +170 -0
- package/dist/contract/recipe.d.ts.map +1 -0
- package/dist/contract/recipe.js +2 -0
- package/dist/contract/recipe.js.map +1 -0
- package/dist/contract/validation.d.ts +86 -0
- package/dist/contract/validation.d.ts.map +1 -0
- package/dist/contract/validation.js +76 -0
- package/dist/contract/validation.js.map +1 -0
- package/dist/db/db.d.ts +131 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +91 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +9 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations/index.d.ts +21 -0
- package/dist/db/migrations/index.d.ts.map +1 -0
- package/dist/db/migrations/index.js +54 -0
- package/dist/db/migrations/index.js.map +1 -0
- package/dist/db/models/subtasks.d.ts +102 -0
- package/dist/db/models/subtasks.d.ts.map +1 -0
- package/dist/db/models/subtasks.js +285 -0
- package/dist/db/models/subtasks.js.map +1 -0
- package/dist/db/models/tasks.d.ts +92 -0
- package/dist/db/models/tasks.d.ts.map +1 -0
- package/dist/db/models/tasks.js +212 -0
- package/dist/db/models/tasks.js.map +1 -0
- package/dist/db/schema.d.ts +488 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +91 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/env.d.ts +46 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +40 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/platform.d.ts +47 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +47 -0
- package/dist/platform.js.map +1 -0
- package/dist/runtime/index.d.ts +86 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +123 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/tool-families.d.ts +33 -0
- package/dist/runtime/tool-families.d.ts.map +1 -0
- package/dist/runtime/tool-families.js +62 -0
- package/dist/runtime/tool-families.js.map +1 -0
- package/dist/subagent/fingerprint.d.ts +38 -0
- package/dist/subagent/fingerprint.d.ts.map +1 -0
- package/dist/subagent/fingerprint.js +97 -0
- package/dist/subagent/fingerprint.js.map +1 -0
- package/dist/subagent/index.d.ts +147 -0
- package/dist/subagent/index.d.ts.map +1 -0
- package/dist/subagent/index.js +299 -0
- package/dist/subagent/index.js.map +1 -0
- package/dist/subagent/prompt.d.ts +34 -0
- package/dist/subagent/prompt.d.ts.map +1 -0
- package/dist/subagent/prompt.js +46 -0
- package/dist/subagent/prompt.js.map +1 -0
- package/dist/subagent/run.d.ts +151 -0
- package/dist/subagent/run.d.ts.map +1 -0
- package/dist/subagent/run.js +491 -0
- package/dist/subagent/run.js.map +1 -0
- package/dist/subagent/workspace.d.ts +65 -0
- package/dist/subagent/workspace.d.ts.map +1 -0
- package/dist/subagent/workspace.js +53 -0
- package/dist/subagent/workspace.js.map +1 -0
- package/dist/subtasks/catalog.d.ts +40 -0
- package/dist/subtasks/catalog.d.ts.map +1 -0
- package/dist/subtasks/catalog.js +36 -0
- package/dist/subtasks/catalog.js.map +1 -0
- package/dist/subtasks/decomposition.d.ts +90 -0
- package/dist/subtasks/decomposition.d.ts.map +1 -0
- package/dist/subtasks/decomposition.js +205 -0
- package/dist/subtasks/decomposition.js.map +1 -0
- package/dist/subtasks/delegate.d.ts +77 -0
- package/dist/subtasks/delegate.d.ts.map +1 -0
- package/dist/subtasks/delegate.js +102 -0
- package/dist/subtasks/delegate.js.map +1 -0
- package/dist/subtasks/index.d.ts +11 -0
- package/dist/subtasks/index.d.ts.map +1 -0
- package/dist/subtasks/index.js +11 -0
- package/dist/subtasks/index.js.map +1 -0
- package/dist/subtasks/scheduler.d.ts +49 -0
- package/dist/subtasks/scheduler.d.ts.map +1 -0
- package/dist/subtasks/scheduler.js +48 -0
- package/dist/subtasks/scheduler.js.map +1 -0
- package/dist/subtasks/subtask-types.d.ts +100 -0
- package/dist/subtasks/subtask-types.d.ts.map +1 -0
- package/dist/subtasks/subtask-types.js +111 -0
- package/dist/subtasks/subtask-types.js.map +1 -0
- package/dist/subtasks/types.d.ts +321 -0
- package/dist/subtasks/types.d.ts.map +1 -0
- package/dist/subtasks/types.js +16 -0
- package/dist/subtasks/types.js.map +1 -0
- package/dist/testing/auth.d.ts +12 -0
- package/dist/testing/auth.d.ts.map +1 -0
- package/dist/testing/auth.js +25 -0
- package/dist/testing/auth.js.map +1 -0
- package/dist/testing/do.d.ts +30 -0
- package/dist/testing/do.d.ts.map +1 -0
- package/dist/testing/do.js +26 -0
- package/dist/testing/do.js.map +1 -0
- package/dist/testing/fake-session.d.ts +27 -0
- package/dist/testing/fake-session.d.ts.map +1 -0
- package/dist/testing/fake-session.js +38 -0
- package/dist/testing/fake-session.js.map +1 -0
- package/dist/testing/fixtures.d.ts +27 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +67 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/index.d.ts +31 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +31 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-model.d.ts +43 -0
- package/dist/testing/mock-model.d.ts.map +1 -0
- package/dist/testing/mock-model.js +62 -0
- package/dist/testing/mock-model.js.map +1 -0
- package/dist/testing/node.d.ts +24 -0
- package/dist/testing/node.d.ts.map +1 -0
- package/dist/testing/node.js +24 -0
- package/dist/testing/node.js.map +1 -0
- package/dist/testing/vcr-global-setup.d.ts +3 -0
- package/dist/testing/vcr-global-setup.d.ts.map +1 -0
- package/dist/testing/vcr-global-setup.js +9 -0
- package/dist/testing/vcr-global-setup.js.map +1 -0
- package/dist/testing/vcr-shared.d.ts +21 -0
- package/dist/testing/vcr-shared.d.ts.map +1 -0
- package/dist/testing/vcr-shared.js +21 -0
- package/dist/testing/vcr-shared.js.map +1 -0
- package/dist/testing/vcr-spec.d.ts +17 -0
- package/dist/testing/vcr-spec.d.ts.map +1 -0
- package/dist/testing/vcr-spec.js +72 -0
- package/dist/testing/vcr-spec.js.map +1 -0
- package/dist/testing/vcr.d.ts +81 -0
- package/dist/testing/vcr.d.ts.map +1 -0
- package/dist/testing/vcr.js +211 -0
- package/dist/testing/vcr.js.map +1 -0
- package/dist/worker/index.d.ts +62 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +194 -0
- package/dist/worker/index.js.map +1 -0
- package/eslint-rules/index.js +31 -0
- package/eslint-rules/no-deprecated-object-properties.js +81 -0
- package/package.json +147 -0
- package/scripts/generate-keys.mjs +53 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import type { ResolvedRecipe, SubtaskParams } from "../contract/recipe.js";
|
|
2
|
+
export type SubtaskStatus = "pending" | "running" | "completed" | "failed" | "skipped" | "canceled";
|
|
3
|
+
/** A per-caller, SQLite-assigned, monotonically increasing Subtask identifier. */
|
|
4
|
+
export type SubtaskId = number;
|
|
5
|
+
/**
|
|
6
|
+
* An exact, verbatim snapshot of one selected Session history message, copied
|
|
7
|
+
* onto the Subtask at decomposition time. The decomposition model selects which
|
|
8
|
+
* messages to reference; it never rewrites their content. User-turn provenance
|
|
9
|
+
* (author/channel) is already inline in the message text's `<turn>` wrapper.
|
|
10
|
+
*/
|
|
11
|
+
export interface SubtaskReference {
|
|
12
|
+
role: "user" | "assistant";
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* One part of a Subtask's result. Text-only today; file/data kinds are additive
|
|
17
|
+
* later. Internal to the agent — the terminal A2A Task collapses these to a
|
|
18
|
+
* single text reply for the gateway/human.
|
|
19
|
+
*/
|
|
20
|
+
export interface SubtaskResultPart {
|
|
21
|
+
kind: "text";
|
|
22
|
+
text: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creation input for one Subtask, before it is persisted. `dependsOn` uses
|
|
26
|
+
* draft-local keys (not yet-unknown {@link SubtaskId}s); the data layer resolves
|
|
27
|
+
* them to SQLite-assigned ids when the decomposition is created. `ordinal` is
|
|
28
|
+
* derived from the draft's position in the decomposition array.
|
|
29
|
+
*/
|
|
30
|
+
export interface SubtaskDraft {
|
|
31
|
+
localKey: string;
|
|
32
|
+
type: string;
|
|
33
|
+
prompt: string;
|
|
34
|
+
references: SubtaskReference[];
|
|
35
|
+
/** Draft-local keys of prerequisite drafts. */
|
|
36
|
+
dependsOn: string[];
|
|
37
|
+
/** The type's required inputs, already validated for shape. */
|
|
38
|
+
params: SubtaskParams;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Session state the parent resolved *from* a Subtask's params at execution
|
|
42
|
+
* start — the part of an execution's context the model can never supply.
|
|
43
|
+
*
|
|
44
|
+
* Deliberately outside {@link RecipeExecutionRequest}: it is not part of an
|
|
45
|
+
* execution's identity and it can change under us, so fingerprinting it would
|
|
46
|
+
* make a retry look like a different request. It travels as a separate argument,
|
|
47
|
+
* the same discipline as the chunk number.
|
|
48
|
+
*/
|
|
49
|
+
export type SubtaskRuntime = Record<string, unknown>;
|
|
50
|
+
/**
|
|
51
|
+
* Narrow a {@link SubtaskRuntime} to the shape a plugin resolved for itself.
|
|
52
|
+
*
|
|
53
|
+
* Runtime is an open bag because core cannot know what a domain needs — the
|
|
54
|
+
* predecessor repo declared ARC's four fields (`cardId`, `cookies`, `guid`,
|
|
55
|
+
* `frame`) right here in the delegation types, which meant core imported a
|
|
56
|
+
* domain's types and every unrelated agent carried them. A plugin now writes and
|
|
57
|
+
* reads its own slice, and the only thing core does with the bag is carry it.
|
|
58
|
+
*
|
|
59
|
+
* The unchecked cast is the point: the plugin that wrote the slice is the plugin
|
|
60
|
+
* reading it, so the assertion is local and its blast radius is one module.
|
|
61
|
+
*/
|
|
62
|
+
export declare function runtimeAs<T>(runtime: SubtaskRuntime): T;
|
|
63
|
+
/**
|
|
64
|
+
* A user-facing progress note a tool emits mid-execution (e.g. a game level-up).
|
|
65
|
+
* The resumable runner collects these and ends the current chunk so the parent
|
|
66
|
+
* DO can post them promptly; `key` is a stable dedupe id the gateway keys on.
|
|
67
|
+
*/
|
|
68
|
+
export interface ProgressEvent {
|
|
69
|
+
key: string;
|
|
70
|
+
text: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* One durable chunk's outcome as the facet reports it to the parent DO. `done`
|
|
74
|
+
* false means the run yielded a chunk boundary and the Workflow must run another
|
|
75
|
+
* chunk; `done` true carries the terminal {@link RecipeExecutionResult}. Progress
|
|
76
|
+
* events accumulated during the chunk ride along either way.
|
|
77
|
+
*/
|
|
78
|
+
export type RecipeChunkResult = {
|
|
79
|
+
done: false;
|
|
80
|
+
progress: ProgressEvent[];
|
|
81
|
+
} | {
|
|
82
|
+
done: true;
|
|
83
|
+
result: RecipeExecutionResult;
|
|
84
|
+
progress: ProgressEvent[];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The parent DO's projection of a chunk outcome for the Workflow (RPC-safe, no
|
|
88
|
+
* result parts — those are persisted on the row). `status` is `running` until the
|
|
89
|
+
* run is `done`, then the terminal Subtask status.
|
|
90
|
+
*/
|
|
91
|
+
export interface SubtaskChunkOutcome {
|
|
92
|
+
done: boolean;
|
|
93
|
+
status: SubtaskStatus;
|
|
94
|
+
progress: ProgressEvent[];
|
|
95
|
+
}
|
|
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
|
+
/**
|
|
109
|
+
* RPC-safe input for one isolated `RecipeSubagent` execution, assembled by the
|
|
110
|
+
* parent at execution start: the already-resolved (and code-validated) Recipe,
|
|
111
|
+
* the Subtask's non-session prompt, its verbatim reference snapshots, and the
|
|
112
|
+
* generated results of its completed dependencies. The child re-validates the
|
|
113
|
+
* Recipe defensively but never resolves one itself.
|
|
114
|
+
*/
|
|
115
|
+
export interface RecipeExecutionRequest {
|
|
116
|
+
taskId: string;
|
|
117
|
+
subtaskId: SubtaskId;
|
|
118
|
+
/**
|
|
119
|
+
* The Subtask's semantic type — what the work *is*, and what owns the params
|
|
120
|
+
* contract. Distinct from `recipe.key`, which names the execution
|
|
121
|
+
* configuration it runs under: several types may share one Recipe.
|
|
122
|
+
*/
|
|
123
|
+
type: string;
|
|
124
|
+
recipe: ResolvedRecipe;
|
|
125
|
+
prompt: string;
|
|
126
|
+
references: SubtaskReference[];
|
|
127
|
+
dependencyResults: DependencyResult[];
|
|
128
|
+
/**
|
|
129
|
+
* The Subtask's validated params. Part of the execution's identity — two plays
|
|
130
|
+
* of different games are different work — so this IS fingerprinted, unlike
|
|
131
|
+
* {@link SubtaskRuntime}, which is deliberately excluded: the leased scorecard
|
|
132
|
+
* can legitimately differ between two chunks of one run, and must not make a
|
|
133
|
+
* retry look like a different execution.
|
|
134
|
+
*/
|
|
135
|
+
params: SubtaskParams;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Terminal outcome of one `RecipeSubagent` execution (RPC-safe). `modelId` is a
|
|
139
|
+
* diagnostic only — which model produced the outcome (null when validation
|
|
140
|
+
* failed before any model call); it is never persisted on the Subtask row.
|
|
141
|
+
* Transient platform faults are not results: they throw so the enclosing
|
|
142
|
+
* Workflow step can retry.
|
|
143
|
+
*/
|
|
144
|
+
export type RecipeExecutionResult = {
|
|
145
|
+
status: "completed";
|
|
146
|
+
resultParts: SubtaskResultPart[];
|
|
147
|
+
modelId: string;
|
|
148
|
+
} | {
|
|
149
|
+
status: "failed";
|
|
150
|
+
error: string;
|
|
151
|
+
modelId: string | null;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* One Subtask as the delegating model emits it. The model selects references
|
|
155
|
+
* by **catalog index only** — it never emits reference text, and application code
|
|
156
|
+
* snapshots the catalog entry's exact role+text onto the Subtask (see
|
|
157
|
+
* `agent/subtasks/decomposition.ts`). `dependsOn` uses draft-local keys, resolved
|
|
158
|
+
* to SQLite-assigned {@link SubtaskId}s by the data layer.
|
|
159
|
+
*/
|
|
160
|
+
export interface SubtaskProposal {
|
|
161
|
+
localKey: string;
|
|
162
|
+
type: string;
|
|
163
|
+
prompt: string;
|
|
164
|
+
/**
|
|
165
|
+
* 1-based indices into the ephemeral, per-round reference catalog. Optional:
|
|
166
|
+
* omitted when the subtask needs no verbatim history, and always absent from a
|
|
167
|
+
* *reconstructed* historical call, whose references were resolved rounds ago.
|
|
168
|
+
*/
|
|
169
|
+
referenceIndexes?: number[];
|
|
170
|
+
/** Draft-local keys of prerequisite proposals. */
|
|
171
|
+
dependsOn: string[];
|
|
172
|
+
/** The type's required inputs; omitted for a type that takes none. */
|
|
173
|
+
params?: SubtaskParams;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The model's complete `delegate` call: the acknowledgment the user sees while
|
|
177
|
+
* the work runs, plus one through eight Subtask proposals. Validated against the
|
|
178
|
+
* round's ephemeral catalog before anything is persisted; invalid output fails
|
|
179
|
+
* the attempt (and, with both models exhausted, the round) rather than being
|
|
180
|
+
* silently repaired.
|
|
181
|
+
*/
|
|
182
|
+
export interface DecompositionProposal {
|
|
183
|
+
reply: string;
|
|
184
|
+
subtasks: SubtaskProposal[];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Terminal outcome of one main-agent round (RPC-safe).
|
|
188
|
+
*
|
|
189
|
+
* `replied` is the terminal answer — the round chose to answer the user rather
|
|
190
|
+
* than delegate, and the Workflow delivers it. `delegated` means the round's
|
|
191
|
+
* Subtask rows are durable and Phase 2 should run them, after which another round
|
|
192
|
+
* begins. `failed` means both models produced unusable output; no Subtask is ever
|
|
193
|
+
* synthesized to cover for it. `canceled` means the caller cancelled during the
|
|
194
|
+
* round: nothing was persisted and nothing was published. Transient platform
|
|
195
|
+
* faults are not results: they throw so the enclosing Workflow step can retry
|
|
196
|
+
* (mirrors {@link RecipeExecutionResult}).
|
|
197
|
+
*
|
|
198
|
+
* `turns` is what this round cost, which the Workflow meters against the Task's
|
|
199
|
+
* budget. This is the **only** type that carries it, and it carries it because the
|
|
200
|
+
* count has to cross an RPC boundary to reach a Workflow in another isolate;
|
|
201
|
+
* everything inside the DO shares one mutable {@link file://../budget.ts TurnBudget}
|
|
202
|
+
* instead. The field is attached in a single place — see `runTaskTurn` — so no
|
|
203
|
+
* branch can drop it and no branch can invent it.
|
|
204
|
+
*
|
|
205
|
+
* The idempotent recovery paths — a round replayed from durable rows rather than
|
|
206
|
+
* re-inferred — therefore report **0** structurally: they return before any model
|
|
207
|
+
* runs, so the budget they hand back is untouched. That is exact on a clean
|
|
208
|
+
* replay, where the Workflow's own cached step return already carries the original
|
|
209
|
+
* number, and under-counts by one round when a step crashed mid-flight and re-ran.
|
|
210
|
+
* Accepted rather than fixed: a replying round writes no durable row at all, so
|
|
211
|
+
* nothing exists to hang a per-round count on, and the wall clock bounds the
|
|
212
|
+
* crash-loop case anyway.
|
|
213
|
+
*/
|
|
214
|
+
export type TurnTaskResult = {
|
|
215
|
+
status: "replied";
|
|
216
|
+
reply: string;
|
|
217
|
+
turns: number;
|
|
218
|
+
} | {
|
|
219
|
+
status: "delegated";
|
|
220
|
+
reply: string;
|
|
221
|
+
subtasks: Subtask[];
|
|
222
|
+
turns: number;
|
|
223
|
+
} | {
|
|
224
|
+
status: "failed";
|
|
225
|
+
error: string;
|
|
226
|
+
turns: number;
|
|
227
|
+
} | {
|
|
228
|
+
status: "canceled";
|
|
229
|
+
turns: number;
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Distributive `Omit` — applies per member, so the discriminated union survives.
|
|
233
|
+
* A plain `Omit<TurnTaskResult, "turns">` collapses all four into one loose shape
|
|
234
|
+
* whose `reply` and `subtasks` are independently optional.
|
|
235
|
+
*/
|
|
236
|
+
type WithoutTurns<T> = T extends unknown ? Omit<T, "turns"> : never;
|
|
237
|
+
/**
|
|
238
|
+
* What a round decided, before its cost is attached. The DO's round logic returns
|
|
239
|
+
* this and lets one wrapper bill the budget, rather than every branch remembering
|
|
240
|
+
* to report a number it did not compute.
|
|
241
|
+
*/
|
|
242
|
+
export type TurnVerdict = WithoutTurns<TurnTaskResult>;
|
|
243
|
+
/**
|
|
244
|
+
* One branch's outcome as a later round sees it — a plain, RPC-safe subset of the
|
|
245
|
+
* durable {@link Subtask} row, loaded across **every** round in stable ordinal
|
|
246
|
+
* order. Completed, failed, and skipped branches are all included so the reply
|
|
247
|
+
* can use available successes and disclose relevant failures.
|
|
248
|
+
*
|
|
249
|
+
* Carries `round`, `prompt` and `dependsOn` — not for composing, but for
|
|
250
|
+
* reconstructing the per-round `delegate` call that produced these branches (see
|
|
251
|
+
* `agent/subtasks/delegate.ts`). Unlike {@link SubtaskNode}, this projection is
|
|
252
|
+
* built inside the DO and returns only a reply, so the 1 MiB Workflow-step cap
|
|
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.
|
|
255
|
+
*/
|
|
256
|
+
export interface CompositionBranch {
|
|
257
|
+
subtaskId: SubtaskId;
|
|
258
|
+
round: number;
|
|
259
|
+
ordinal: number;
|
|
260
|
+
type: string;
|
|
261
|
+
prompt: string;
|
|
262
|
+
dependsOn: SubtaskId[];
|
|
263
|
+
params: SubtaskParams;
|
|
264
|
+
status: SubtaskStatus;
|
|
265
|
+
resultParts: SubtaskResultPart[] | null;
|
|
266
|
+
error: string | null;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* The `scan:<n>` wave projection (RPC-safe): either the caller cancelled, or the
|
|
270
|
+
* refreshed DAG after blocked branches were skipped. Returning the verdict with
|
|
271
|
+
* the nodes is what lets the Workflow drop its separate cancellation probe — one
|
|
272
|
+
* round trip, and no gap between asking and acting.
|
|
273
|
+
*/
|
|
274
|
+
export type SubtaskScan = {
|
|
275
|
+
canceled: true;
|
|
276
|
+
} | {
|
|
277
|
+
canceled: false;
|
|
278
|
+
nodes: SubtaskNode[];
|
|
279
|
+
};
|
|
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
|
+
/** Durable state owned by the main agent for one delegated unit of work. */
|
|
298
|
+
export interface Subtask {
|
|
299
|
+
id: SubtaskId;
|
|
300
|
+
taskId: string;
|
|
301
|
+
/** The main-agent round that delegated this Subtask (0-based). */
|
|
302
|
+
round: number;
|
|
303
|
+
/** Position within the parent Task, increasing across every round. */
|
|
304
|
+
ordinal: number;
|
|
305
|
+
type: string;
|
|
306
|
+
recipeId: string | null;
|
|
307
|
+
recipeVersion: number | null;
|
|
308
|
+
prompt: string;
|
|
309
|
+
references: SubtaskReference[];
|
|
310
|
+
dependsOn: SubtaskId[];
|
|
311
|
+
/** The type's required inputs, validated at delegation time. */
|
|
312
|
+
params: SubtaskParams;
|
|
313
|
+
status: SubtaskStatus;
|
|
314
|
+
resultParts: SubtaskResultPart[] | null;
|
|
315
|
+
error: string | null;
|
|
316
|
+
createdAt: number;
|
|
317
|
+
updatedAt: number;
|
|
318
|
+
completedAt: number | null;
|
|
319
|
+
}
|
|
320
|
+
export {};
|
|
321
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/subtasks/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrow a {@link SubtaskRuntime} to the shape a plugin resolved for itself.
|
|
3
|
+
*
|
|
4
|
+
* Runtime is an open bag because core cannot know what a domain needs — the
|
|
5
|
+
* predecessor repo declared ARC's four fields (`cardId`, `cookies`, `guid`,
|
|
6
|
+
* `frame`) right here in the delegation types, which meant core imported a
|
|
7
|
+
* domain's types and every unrelated agent carried them. A plugin now writes and
|
|
8
|
+
* reads its own slice, and the only thing core does with the bag is carry it.
|
|
9
|
+
*
|
|
10
|
+
* The unchecked cast is the point: the plugin that wrote the slice is the plugin
|
|
11
|
+
* reading it, so the assertion is local and its blast radius is one module.
|
|
12
|
+
*/
|
|
13
|
+
export function runtimeAs(runtime) {
|
|
14
|
+
return runtime;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/subtasks/types.ts"],"names":[],"mappings":"AAyDA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAI,OAAuB;IAClD,OAAO,OAAY,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface GatewayTokenOptions {
|
|
2
|
+
audience?: string;
|
|
3
|
+
issuer?: string;
|
|
4
|
+
/** Relative string ("5m"), absolute epoch seconds, or Date. Past values expire the token. */
|
|
5
|
+
expiresIn?: string | number | Date;
|
|
6
|
+
identity?: Record<string, unknown>;
|
|
7
|
+
/** Claim the identity is carried in. Defaults to core's `IDENTITY_CLAIM`. */
|
|
8
|
+
identityClaim?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Sign a short-lived EdDSA gateway JWT using the test gateway key. */
|
|
11
|
+
export declare function makeGatewayToken(options?: GatewayTokenOptions): Promise<string>;
|
|
12
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/testing/auth.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,uEAAuE;AACvE,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { importJWK, SignJWT } from "jose";
|
|
2
|
+
import { IDENTITY_CLAIM } from "../a2a/verify.js";
|
|
3
|
+
import { TEST_GATEWAY_PRIVATE_JWK, GATEWAY_ORIGIN, AGENT_ORIGIN } from "./fixtures.js";
|
|
4
|
+
/** Sign a short-lived EdDSA gateway JWT using the test gateway key. */
|
|
5
|
+
export async function makeGatewayToken(options = {}) {
|
|
6
|
+
const privateKey = await importJWK(TEST_GATEWAY_PRIVATE_JWK, "EdDSA");
|
|
7
|
+
return new SignJWT({
|
|
8
|
+
[options.identityClaim ?? IDENTITY_CLAIM]: options.identity ?? {
|
|
9
|
+
key: "custom:1:test-agent",
|
|
10
|
+
name: "Test Agent",
|
|
11
|
+
kind: "custom",
|
|
12
|
+
workspaceId: 1
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
.setProtectedHeader({
|
|
16
|
+
alg: "EdDSA",
|
|
17
|
+
kid: TEST_GATEWAY_PRIVATE_JWK.kid,
|
|
18
|
+
jku: `${GATEWAY_ORIGIN}/.well-known/jwks.json`
|
|
19
|
+
})
|
|
20
|
+
.setIssuer(options.issuer ?? GATEWAY_ORIGIN)
|
|
21
|
+
.setAudience(options.audience ?? AGENT_ORIGIN)
|
|
22
|
+
.setExpirationTime(options.expiresIn ?? "5m")
|
|
23
|
+
.sign(privateKey);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/testing/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,YAAY,EACb,MAAM,eAAe,CAAC;AAYvB,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;IACtE,OAAO,IAAI,OAAO,CAAC;QACjB,CAAC,OAAO,CAAC,aAAa,IAAI,cAAc,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI;YAC7D,GAAG,EAAE,qBAAqB;YAC1B,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,CAAC;SACf;KACF,CAAC;SACC,kBAAkB,CAAC;QAClB,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,wBAAwB,CAAC,GAAG;QACjC,GAAG,EAAE,GAAG,cAAc,wBAAwB;KAC/C,CAAC;SACD,SAAS,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC;SAC3C,WAAW,CAAC,OAAO,CAAC,QAAQ,IAAI,YAAY,CAAC;SAC7C,iBAAiB,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;SAC5C,IAAI,CAAC,UAAU,CAAC,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AgentDB, type AgentDBOptions } from "../db/db.js";
|
|
2
|
+
/**
|
|
3
|
+
* Durable Object test helpers.
|
|
4
|
+
*
|
|
5
|
+
* The predecessor hardcoded its own DO binding and exposed one `with*` wrapper
|
|
6
|
+
* per named `AgentDB` domain — including one for a domain that belonged to a
|
|
7
|
+
* plugin. Both are parameterized here: a consumer binds their namespace once,
|
|
8
|
+
* and {@link DoTestHelpers.withDb} hands over the whole `AgentDB` rather than
|
|
9
|
+
* pre-selecting a table.
|
|
10
|
+
*/
|
|
11
|
+
export interface DoTestHelpers {
|
|
12
|
+
/** Fresh, unique DO stub per test — state never leaks between tests. */
|
|
13
|
+
freshStub(label: string): DurableObjectStub;
|
|
14
|
+
/** Run `fn` inside a fresh DO instance with a migrated {@link AgentDB}. */
|
|
15
|
+
withDb<T>(label: string, fn: (db: AgentDB) => T): Promise<T>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `ctx` is protected in the DO type system but public at runtime. Cast once so
|
|
19
|
+
* callers don't repeat the assertion.
|
|
20
|
+
*/
|
|
21
|
+
export declare function doStorage(instance: unknown): DurableObjectStorage;
|
|
22
|
+
/**
|
|
23
|
+
* Bind the helpers to a consumer's DO namespace.
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* const { freshStub, withDb } = makeDoHelpers(env.MyAgent);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function makeDoHelpers(ns: DurableObjectNamespace, defaults?: AgentDBOptions): DoTestHelpers;
|
|
30
|
+
//# sourceMappingURL=do.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"do.d.ts","sourceRoot":"","sources":["../../src/testing/do.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE3D;;;;;;;;GAQG;AAEH,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAC5C,2EAA2E;IAC3E,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC9D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,OAAO,GAAG,oBAAoB,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,sBAAsB,EAC1B,QAAQ,GAAE,cAAmC,GAC5C,aAAa,CAYf"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { runInDurableObject } from "cloudflare:test";
|
|
2
|
+
import { AgentDB } from "../db/db.js";
|
|
3
|
+
/**
|
|
4
|
+
* `ctx` is protected in the DO type system but public at runtime. Cast once so
|
|
5
|
+
* callers don't repeat the assertion.
|
|
6
|
+
*/
|
|
7
|
+
export function doStorage(instance) {
|
|
8
|
+
return instance.ctx.storage;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Bind the helpers to a consumer's DO namespace.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const { freshStub, withDb } = makeDoHelpers(env.MyAgent);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function makeDoHelpers(ns, defaults = { maxSubtasks: 8 }) {
|
|
18
|
+
const freshStub = (label) => ns.get(ns.idFromName(`test:${label}:${crypto.randomUUID()}`));
|
|
19
|
+
return {
|
|
20
|
+
freshStub,
|
|
21
|
+
withDb(label, fn) {
|
|
22
|
+
return runInDurableObject(freshStub(label), (instance) => fn(new AgentDB(doStorage(instance), defaults)));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=do.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"do.js","sourceRoot":"","sources":["../../src/testing/do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAuB,MAAM,aAAa,CAAC;AAmB3D;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,QAAiB;IACzC,OAAQ,QAAuD,CAAC,GAAG,CAAC,OAAO,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,EAA0B,EAC1B,WAA2B,EAAE,WAAW,EAAE,CAAC,EAAE;IAE7C,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,EAAE,CAClC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAEhE,OAAO;QACL,SAAS;QACT,MAAM,CAAI,KAAa,EAAE,EAAsB;YAC7C,OAAO,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CACvD,EAAE,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAC/C,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ToolSet } from "ai";
|
|
2
|
+
import type { SessionMessage } from "agents/experimental/memory/session";
|
|
3
|
+
import type { SessionLike } from "../agent/session.js";
|
|
4
|
+
/**
|
|
5
|
+
* An in-memory {@link SessionLike} standing in for the DO's real continuous
|
|
6
|
+
* Session. Shared by the turn, decomposition, and composition specs so a change
|
|
7
|
+
* to the Session contract breaks in one place.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the two real behaviors the phased pipeline depends on:
|
|
10
|
+
*
|
|
11
|
+
* - `appendMessage` **dedupes by id** — appending an existing id is a no-op, the
|
|
12
|
+
* property that makes deterministic-id appends exactly-once on a step re-run.
|
|
13
|
+
* - `getMessage` reads the raw stored message back.
|
|
14
|
+
*/
|
|
15
|
+
export declare class FakeSession implements SessionLike {
|
|
16
|
+
messages: SessionMessage[];
|
|
17
|
+
system: string;
|
|
18
|
+
/** Compaction overlays to report — non-empty gates the `recall` tool on. */
|
|
19
|
+
compactions: unknown[];
|
|
20
|
+
appendMessage(m: SessionMessage): void;
|
|
21
|
+
getHistory(): Promise<SessionMessage[]>;
|
|
22
|
+
getMessage(id: string): Promise<SessionMessage | null>;
|
|
23
|
+
refreshSystemPrompt(): Promise<string>;
|
|
24
|
+
tools(): Promise<ToolSet>;
|
|
25
|
+
getCompactions(): Promise<unknown[]>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=fake-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-session.d.ts","sourceRoot":"","sources":["../../src/testing/fake-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC7C,QAAQ,EAAE,cAAc,EAAE,CAAM;IAChC,MAAM,SAAsC;IAC5C,4EAA4E;IAC5E,WAAW,EAAE,OAAO,EAAE,CAAM;IAE5B,aAAa,CAAC,CAAC,EAAE,cAAc;IAIzB,UAAU;IAGV,UAAU,CAAC,EAAE,EAAE,MAAM;IAGrB,mBAAmB;IAGnB,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAGzB,cAAc;CAGrB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An in-memory {@link SessionLike} standing in for the DO's real continuous
|
|
3
|
+
* Session. Shared by the turn, decomposition, and composition specs so a change
|
|
4
|
+
* to the Session contract breaks in one place.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors the two real behaviors the phased pipeline depends on:
|
|
7
|
+
*
|
|
8
|
+
* - `appendMessage` **dedupes by id** — appending an existing id is a no-op, the
|
|
9
|
+
* property that makes deterministic-id appends exactly-once on a step re-run.
|
|
10
|
+
* - `getMessage` reads the raw stored message back.
|
|
11
|
+
*/
|
|
12
|
+
export class FakeSession {
|
|
13
|
+
messages = [];
|
|
14
|
+
system = "SOUL BLOCK\n\n## memory\n(empty)";
|
|
15
|
+
/** Compaction overlays to report — non-empty gates the `recall` tool on. */
|
|
16
|
+
compactions = [];
|
|
17
|
+
appendMessage(m) {
|
|
18
|
+
if (this.messages.some((existing) => existing.id === m.id))
|
|
19
|
+
return;
|
|
20
|
+
this.messages.push(m);
|
|
21
|
+
}
|
|
22
|
+
async getHistory() {
|
|
23
|
+
return this.messages;
|
|
24
|
+
}
|
|
25
|
+
async getMessage(id) {
|
|
26
|
+
return this.messages.find((m) => m.id === id) ?? null;
|
|
27
|
+
}
|
|
28
|
+
async refreshSystemPrompt() {
|
|
29
|
+
return this.system;
|
|
30
|
+
}
|
|
31
|
+
async tools() {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
async getCompactions() {
|
|
35
|
+
return this.compactions;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=fake-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-session.js","sourceRoot":"","sources":["../../src/testing/fake-session.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,WAAW;IACtB,QAAQ,GAAqB,EAAE,CAAC;IAChC,MAAM,GAAG,kCAAkC,CAAC;IAC5C,4EAA4E;IAC5E,WAAW,GAAc,EAAE,CAAC;IAE5B,aAAa,CAAC,CAAiB;QAC7B,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;YAAE,OAAO;QACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;IACxD,CAAC;IACD,KAAK,CAAC,mBAAmB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,KAAK;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type JWK } from "jose";
|
|
2
|
+
import { type Message, type Task, type TaskState } from "@a2a-js/sdk";
|
|
3
|
+
/** The gateway origin used in all tests. Must match vitest.config.ts and the MockAgent setup. */
|
|
4
|
+
export declare const GATEWAY_ORIGIN = "https://gateway.test";
|
|
5
|
+
/** Agent origin matching `url.origin` for requests to `http://localhost`. */
|
|
6
|
+
export declare const AGENT_ORIGIN = "http://localhost";
|
|
7
|
+
/** Fixed Ed25519 private JWK used as A2A_SIGNING_KEY in tests. */
|
|
8
|
+
export declare const TEST_AGENT_PRIVATE_JWK: JWK & {
|
|
9
|
+
kid: string;
|
|
10
|
+
};
|
|
11
|
+
/** Fixed Ed25519 private JWK for signing gateway JWTs in tests. */
|
|
12
|
+
export declare const TEST_GATEWAY_PRIVATE_JWK: JWK & {
|
|
13
|
+
kid: string;
|
|
14
|
+
};
|
|
15
|
+
/** Public JWKS the gateway would serve at its `jku` (the private key minus `d`). */
|
|
16
|
+
export declare function gatewayPublicJwks(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Build an A2A v1.0 `TaskStatus` for tests. The generated protobuf types require
|
|
19
|
+
* every field to be present (`message` included, holding `undefined` when there
|
|
20
|
+
* is none), so this keeps the specs from spelling that out each time.
|
|
21
|
+
*/
|
|
22
|
+
export declare function testStatus(state: TaskState, message?: Message): NonNullable<Task["status"]>;
|
|
23
|
+
/** An agent-role `Message` carrying a single v1.0 text part. */
|
|
24
|
+
export declare function testAgentMessage(messageId: string, text: string, contextId?: string, taskId?: string): Message;
|
|
25
|
+
/** A complete v1.0 `Task` in the given state. */
|
|
26
|
+
export declare function testTask(id: string, contextId: string, state: TaskState, message?: Message): Task;
|
|
27
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAQ,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5E,iGAAiG;AACjG,eAAO,MAAM,cAAc,yBAAyB,CAAC;AAErD,6EAA6E;AAC7E,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAMvD,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,wBAAwB,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAMzD,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAE7B;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,SAAK,EACd,MAAM,SAAK,GACV,OAAO,CAkBT;AAED,iDAAiD;AACjD,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI,CASN"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {} from "jose";
|
|
2
|
+
import { Role } from "@a2a-js/sdk";
|
|
3
|
+
/** The gateway origin used in all tests. Must match vitest.config.ts and the MockAgent setup. */
|
|
4
|
+
export const GATEWAY_ORIGIN = "https://gateway.test";
|
|
5
|
+
/** Agent origin matching `url.origin` for requests to `http://localhost`. */
|
|
6
|
+
export const AGENT_ORIGIN = "http://localhost";
|
|
7
|
+
/** Fixed Ed25519 private JWK used as A2A_SIGNING_KEY in tests. */
|
|
8
|
+
export const TEST_AGENT_PRIVATE_JWK = {
|
|
9
|
+
crv: "Ed25519",
|
|
10
|
+
d: "sbR9EgZV1zUY-K6ENkvSLY8c8Q9kJ9NnxsXc4GVx_1g",
|
|
11
|
+
x: "1dXrUHeE89GBnZbd7MjzJK-3Xvu7khZCK9ZrQauZQ6s",
|
|
12
|
+
kty: "OKP",
|
|
13
|
+
kid: "test-agent-key-1"
|
|
14
|
+
};
|
|
15
|
+
/** Fixed Ed25519 private JWK for signing gateway JWTs in tests. */
|
|
16
|
+
export const TEST_GATEWAY_PRIVATE_JWK = {
|
|
17
|
+
crv: "Ed25519",
|
|
18
|
+
d: "OVKcn3LDH-qybNIdUbr7T9wbmlxNk2maU4_nILbaLKY",
|
|
19
|
+
x: "jYiAbquXL6db7RihLvp2nsp1ShAolDI0tGOjuwsZVnI",
|
|
20
|
+
kty: "OKP",
|
|
21
|
+
kid: "test-gw-key-1"
|
|
22
|
+
};
|
|
23
|
+
/** Public JWKS the gateway would serve at its `jku` (the private key minus `d`). */
|
|
24
|
+
export function gatewayPublicJwks() {
|
|
25
|
+
const { d: _d, ...pub } = TEST_GATEWAY_PRIVATE_JWK;
|
|
26
|
+
return JSON.stringify({ keys: [{ ...pub, use: "sig", alg: "EdDSA" }] });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build an A2A v1.0 `TaskStatus` for tests. The generated protobuf types require
|
|
30
|
+
* every field to be present (`message` included, holding `undefined` when there
|
|
31
|
+
* is none), so this keeps the specs from spelling that out each time.
|
|
32
|
+
*/
|
|
33
|
+
export function testStatus(state, message) {
|
|
34
|
+
return { state, message, timestamp: new Date().toISOString() };
|
|
35
|
+
}
|
|
36
|
+
/** An agent-role `Message` carrying a single v1.0 text part. */
|
|
37
|
+
export function testAgentMessage(messageId, text, contextId = "", taskId = "") {
|
|
38
|
+
return {
|
|
39
|
+
messageId,
|
|
40
|
+
contextId,
|
|
41
|
+
taskId,
|
|
42
|
+
role: Role.ROLE_AGENT,
|
|
43
|
+
parts: [
|
|
44
|
+
{
|
|
45
|
+
content: { $case: "text", value: text },
|
|
46
|
+
metadata: undefined,
|
|
47
|
+
filename: "",
|
|
48
|
+
mediaType: "text/plain"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
metadata: undefined,
|
|
52
|
+
extensions: [],
|
|
53
|
+
referenceTaskIds: []
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** A complete v1.0 `Task` in the given state. */
|
|
57
|
+
export function testTask(id, contextId, state, message) {
|
|
58
|
+
return {
|
|
59
|
+
id,
|
|
60
|
+
contextId,
|
|
61
|
+
status: testStatus(state, message),
|
|
62
|
+
artifacts: [],
|
|
63
|
+
history: [],
|
|
64
|
+
metadata: undefined
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,IAAI,EAA2C,MAAM,aAAa,CAAC;AAE5E,iGAAiG;AACjG,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,kEAAkE;AAClE,MAAM,CAAC,MAAM,sBAAsB,GAA0B;IAC3D,GAAG,EAAE,SAAS;IACd,CAAC,EAAE,6CAA6C;IAChD,CAAC,EAAE,6CAA6C;IAChD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,kBAAkB;CACxB,CAAC;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,wBAAwB,GAA0B;IAC7D,GAAG,EAAE,SAAS;IACd,CAAC,EAAE,6CAA6C;IAChD,CAAC,EAAE,6CAA6C;IAChD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,eAAe;CACrB,CAAC;AAEF,oFAAoF;AACpF,MAAM,UAAU,iBAAiB;IAC/B,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,GAAG,wBAAwB,CAAC;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAgB,EAChB,OAAiB;IAEjB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AACjE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAC9B,SAAiB,EACjB,IAAY,EACZ,SAAS,GAAG,EAAE,EACd,MAAM,GAAG,EAAE;IAEX,OAAO;QACL,SAAS;QACT,SAAS;QACT,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,UAAU;QACrB,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;gBACvC,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,EAAE;gBACZ,SAAS,EAAE,YAAY;aACxB;SACF;QACD,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,EAAE;QACd,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,QAAQ,CACtB,EAAU,EACV,SAAiB,EACjB,KAAgB,EAChB,OAAiB;IAEjB,OAAO;QACL,EAAE;QACF,SAAS;QACT,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC;QAClC,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC"}
|