@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,102 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import { makeDecompositionProposalSchema } from "./decomposition.js";
|
|
3
|
+
/**
|
|
4
|
+
* The `delegate` tool — the single act by which the main agent hands work to
|
|
5
|
+
* subagents, and the shape both ends of that act agree on.
|
|
6
|
+
*
|
|
7
|
+
* Delegation is a **durable tool call**: a round emits it for real (the model
|
|
8
|
+
* picks it and fills its input), the Workflow performs it over minutes or hours,
|
|
9
|
+
* and a later round reassembles the call with its result to keep working. The two
|
|
10
|
+
* halves are separated by a Workflow boundary, not by a fiction — nothing here is
|
|
11
|
+
* fabricated on the model's behalf.
|
|
12
|
+
*
|
|
13
|
+
* This module owns the tool's identity because every round depends on it
|
|
14
|
+
* agreeing: a later round pairs a synthesized `tool-result` to an earlier round's
|
|
15
|
+
* `tool-call` by name and id, and a mismatch would not throw — it would silently
|
|
16
|
+
* produce a malformed history that the model quietly misreads.
|
|
17
|
+
*/
|
|
18
|
+
export const DELEGATE_TOOL_NAME = "delegate";
|
|
19
|
+
/**
|
|
20
|
+
* The tool as the model sees it. Deliberately **without `execute`**: the Workflow
|
|
21
|
+
* performs this call, durably, outside the inference — so there is nothing for the
|
|
22
|
+
* SDK to run, and the tool loop halts on the call rather than trying to continue
|
|
23
|
+
* past it. That is what makes it a *control* tool: unlike the agent's work tools
|
|
24
|
+
* (`recall`, `browser_*`, `set_context`), calling it ends the round.
|
|
25
|
+
*
|
|
26
|
+
* Its `inputSchema` is the delegation contract itself, and it is the **only**
|
|
27
|
+
* declaration of this tool. One schema has to serve both directions — the calls
|
|
28
|
+
* the model emits now, and the calls reconstructed from durable rows in later
|
|
29
|
+
* rounds — because a provider cannot be shown two shapes for one tool name in a
|
|
30
|
+
* single request. See {@link delegateCallInput} for how a durable row is rendered
|
|
31
|
+
* back into it.
|
|
32
|
+
*
|
|
33
|
+
* Built per registry rather than declared as a module constant: both the type
|
|
34
|
+
* enum in its schema and the catalogue in its description are facts about which
|
|
35
|
+
* plugins are installed, and in the predecessor repo both were frozen at import
|
|
36
|
+
* time — which is exactly what made the type set unoverridable.
|
|
37
|
+
*/
|
|
38
|
+
export function makeDelegateTool(types, maxSubtasks) {
|
|
39
|
+
return tool({
|
|
40
|
+
description: "Delegate part of the user's request to isolated subagents and acknowledge it. Their results return to you, and you then decide what to do next — answer the user, or delegate again.\n\n" +
|
|
41
|
+
"Every subtask must name one of these types, and supply the params that type requires:\n" +
|
|
42
|
+
types.renderTypes(),
|
|
43
|
+
inputSchema: makeDecompositionProposalSchema(types, maxSubtasks)
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The call's id, derived from the parent Task and the round that emitted it —
|
|
48
|
+
* deterministic and replay-safe, the same discipline as the Session message ids
|
|
49
|
+
* it sits alongside (see {@link file://../history.ts}). Later rounds rebuild it
|
|
50
|
+
* rather than storing it.
|
|
51
|
+
*/
|
|
52
|
+
export function delegateToolCallId(taskId, round) {
|
|
53
|
+
return `task:${taskId}:round:${round}:delegate`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The draft-local key a reconstructed call uses for a durable Subtask.
|
|
57
|
+
*
|
|
58
|
+
* A row does not keep the `localKey` its round's model chose — the data layer
|
|
59
|
+
* resolved it to a SQLite id and dropped it. So reconstruction derives a stable
|
|
60
|
+
* key from that id instead: the *same* id the matching outcome carries in
|
|
61
|
+
* {@link DelegateSubtaskOutcome}, so the model can line each result up with the
|
|
62
|
+
* work that produced it.
|
|
63
|
+
*/
|
|
64
|
+
function localKeyForId(id) {
|
|
65
|
+
return `s${id}`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Rebuild one round's call input from its durable rows, in stable ordinal order.
|
|
69
|
+
* Typed as {@link DecompositionProposal} — the same type the model's own calls
|
|
70
|
+
* are validated into — so the reconstructed call and an emitted one cannot drift
|
|
71
|
+
* apart in shape.
|
|
72
|
+
*
|
|
73
|
+
* `referenceIndexes` is omitted rather than faked: this round's references were
|
|
74
|
+
* snapshotted verbatim onto the rows when it ran, and the catalog they were
|
|
75
|
+
* chosen from is long gone.
|
|
76
|
+
*/
|
|
77
|
+
export function delegateCallInput(reply, branches) {
|
|
78
|
+
return {
|
|
79
|
+
reply,
|
|
80
|
+
subtasks: branches.map((branch) => ({
|
|
81
|
+
localKey: localKeyForId(branch.subtaskId),
|
|
82
|
+
type: branch.type,
|
|
83
|
+
prompt: branch.prompt,
|
|
84
|
+
dependsOn: branch.dependsOn.map(localKeyForId),
|
|
85
|
+
// Reconstructed verbatim from the row: a later round must see the same
|
|
86
|
+
// params the call really carried, or it cannot reason about what ran.
|
|
87
|
+
params: branch.params
|
|
88
|
+
}))
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Rebuild one round's call result from its durable rows, in stable ordinal order. */
|
|
92
|
+
export function delegateCallOutput(branches) {
|
|
93
|
+
return branches.map((branch) => ({
|
|
94
|
+
subtaskId: branch.subtaskId,
|
|
95
|
+
type: branch.type,
|
|
96
|
+
status: branch.status,
|
|
97
|
+
output: branch.status === "completed"
|
|
98
|
+
? (branch.resultParts ?? []).map((part) => part.text).join("\n")
|
|
99
|
+
: null
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=delegate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../src/subtasks/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAa,MAAM,IAAI,CAAC;AACrC,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AASrE;;;;;;;;;;;;;;GAcG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAA0B,EAC1B,WAAmB;IAEnB,OAAO,IAAI,CAAC;QACV,WAAW,EACT,0LAA0L;YAC1L,yFAAyF;YACzF,KAAK,CAAC,WAAW,EAAE;QACrB,WAAW,EAAE,+BAA+B,CAAC,KAAK,EAAE,WAAW,CAAC;KACjE,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,KAAa;IAC9D,OAAO,QAAQ,MAAM,UAAU,KAAK,WAAW,CAAC;AAClD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,EAAa;IAClC,OAAO,IAAI,EAAE,EAAE,CAAC;AAClB,CAAC;AAoBD;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,QAA6B;IAE7B,OAAO;QACL,KAAK;QACL,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAClC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC;YACzC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC;YAC9C,uEAAuE;YACvE,sEAAsE;YACtE,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,kBAAkB,CAChC,QAA6B;IAE7B,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EACJ,MAAM,CAAC,MAAM,KAAK,WAAW;YAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAChE,CAAC,CAAC,IAAI;KACX,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@loopingai/core/subtasks` — the delegation layer: what a round may hand out,
|
|
3
|
+
* how a proposal becomes durable drafts, and which of them may run next.
|
|
4
|
+
*/
|
|
5
|
+
export { makeSubtaskTypes, SubtaskParamsError, type SubtaskTypeRegistry } from "./subtask-types.js";
|
|
6
|
+
export { DecompositionValidationError, makeDecompositionProposalSchema, nonBlank, resolveDecomposition } from "./decomposition.js";
|
|
7
|
+
export { DELEGATE_TOOL_NAME, makeDelegateTool, delegateToolCallId, delegateCallInput, delegateCallOutput, type DelegateSubtaskOutcome } from "./delegate.js";
|
|
8
|
+
export { selectWave, type WaveDecision } from "./scheduler.js";
|
|
9
|
+
export { isCatalogEligible, type ReferenceCatalogEntry } from "./catalog.js";
|
|
10
|
+
export * from "./types.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/subtasks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,QAAQ,EACR,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE7E,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@loopingai/core/subtasks` — the delegation layer: what a round may hand out,
|
|
3
|
+
* how a proposal becomes durable drafts, and which of them may run next.
|
|
4
|
+
*/
|
|
5
|
+
export { makeSubtaskTypes, SubtaskParamsError } from "./subtask-types.js";
|
|
6
|
+
export { DecompositionValidationError, makeDecompositionProposalSchema, nonBlank, resolveDecomposition } from "./decomposition.js";
|
|
7
|
+
export { DELEGATE_TOOL_NAME, makeDelegateTool, delegateToolCallId, delegateCallInput, delegateCallOutput } from "./delegate.js";
|
|
8
|
+
export { selectWave } from "./scheduler.js";
|
|
9
|
+
export { isCatalogEligible } from "./catalog.js";
|
|
10
|
+
export * from "./types.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/subtasks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,QAAQ,EACR,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAqB,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAA8B,MAAM,cAAc,CAAC;AAE7E,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { SubtaskId, SubtaskNode } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The Phase 2 wave scheduler: given the DAG's current state, decide what runs
|
|
4
|
+
* next.
|
|
5
|
+
*
|
|
6
|
+
* Pure and non-mutating. Skipping nodes blocked by a failed prerequisite is the
|
|
7
|
+
* parent's job (`skipBlockedSubtasks`, which runs to a fixpoint and owns the
|
|
8
|
+
* durable writes); this only reads statuses and picks a wave. The Workflow calls
|
|
9
|
+
* it between durable steps, so it must be a plain function of its input — no I/O,
|
|
10
|
+
* no clock, no randomness.
|
|
11
|
+
*/
|
|
12
|
+
/** What the Workflow should do with the DAG as it currently stands. */
|
|
13
|
+
export type WaveDecision =
|
|
14
|
+
/** These nodes' prerequisites all succeeded — run them concurrently, now. */
|
|
15
|
+
{
|
|
16
|
+
kind: "ready";
|
|
17
|
+
ids: SubtaskId[];
|
|
18
|
+
}
|
|
19
|
+
/** Every node reached a terminal status. Phase 2 is over. */
|
|
20
|
+
| {
|
|
21
|
+
kind: "done";
|
|
22
|
+
}
|
|
23
|
+
/** Non-terminal nodes remain but none can ever run. An invariant violation. */
|
|
24
|
+
| {
|
|
25
|
+
kind: "stuck";
|
|
26
|
+
active: SubtaskId[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Select the next wave of dependency-ready Subtasks.
|
|
30
|
+
*
|
|
31
|
+
* A node is ready when it is still active and **every** dependency completed
|
|
32
|
+
* successfully — `completed` specifically, not merely terminal: a dependent must
|
|
33
|
+
* never run on a failed prerequisite's absent output.
|
|
34
|
+
*
|
|
35
|
+
* Ready ids come back in `ordinal` order. The Workflow builds durable step names
|
|
36
|
+
* from them (`execute:<id>`), and step names are a cache key, so the traversal
|
|
37
|
+
* that produces them has to be deterministic.
|
|
38
|
+
*
|
|
39
|
+
* **On `stuck`:** one "active nodes, none ready" check is the whole safety net. A
|
|
40
|
+
* cycle, a self-dependency, and a dangling dependency id all manifest identically
|
|
41
|
+
* here — every node in a cycle waits on a non-completed peer, a self-dependency
|
|
42
|
+
* waits on its own non-completed self, and an unknown id resolves to `undefined`,
|
|
43
|
+
* which is not `completed`. None of them are reachable: `createDecomposition`
|
|
44
|
+
* validates the DAG before it persists a single row. So this is a loud assertion
|
|
45
|
+
* for a corrupted DAG, not a control path — which is exactly why it is one check
|
|
46
|
+
* and not three detectors that can never fire.
|
|
47
|
+
*/
|
|
48
|
+
export declare function selectWave(nodes: SubtaskNode[]): WaveDecision;
|
|
49
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/subtasks/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAExE;;;;;;;;;GASG;AAEH,uEAAuE;AACvE,MAAM,MAAM,YAAY;AACtB,6EAA6E;AAC3E;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,SAAS,EAAE,CAAA;CAAE;AACrC,6DAA6D;GAC3D;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,+EAA+E;GAC7E;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AAiB3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,YAAY,CAa7D"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-terminal statuses — nodes Phase 2 still owes an outcome for.
|
|
3
|
+
*
|
|
4
|
+
* `running` counts as active on purpose. `executeSubtask` accepts a row that is
|
|
5
|
+
* `pending` **or** `running`: the latter is its ambiguous-retry path, where a
|
|
6
|
+
* previous attempt crashed mid-execution and the managed child's fingerprint
|
|
7
|
+
* cache may still hold the terminal result that makes the retry free. So a row
|
|
8
|
+
* stranded `running` is re-runnable, and treating it as inert would deadlock its
|
|
9
|
+
* dependents instead of recovering them.
|
|
10
|
+
*/
|
|
11
|
+
const ACTIVE = new Set([
|
|
12
|
+
"pending",
|
|
13
|
+
"running"
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Select the next wave of dependency-ready Subtasks.
|
|
17
|
+
*
|
|
18
|
+
* A node is ready when it is still active and **every** dependency completed
|
|
19
|
+
* successfully — `completed` specifically, not merely terminal: a dependent must
|
|
20
|
+
* never run on a failed prerequisite's absent output.
|
|
21
|
+
*
|
|
22
|
+
* Ready ids come back in `ordinal` order. The Workflow builds durable step names
|
|
23
|
+
* from them (`execute:<id>`), and step names are a cache key, so the traversal
|
|
24
|
+
* that produces them has to be deterministic.
|
|
25
|
+
*
|
|
26
|
+
* **On `stuck`:** one "active nodes, none ready" check is the whole safety net. A
|
|
27
|
+
* cycle, a self-dependency, and a dangling dependency id all manifest identically
|
|
28
|
+
* here — every node in a cycle waits on a non-completed peer, a self-dependency
|
|
29
|
+
* waits on its own non-completed self, and an unknown id resolves to `undefined`,
|
|
30
|
+
* which is not `completed`. None of them are reachable: `createDecomposition`
|
|
31
|
+
* validates the DAG before it persists a single row. So this is a loud assertion
|
|
32
|
+
* for a corrupted DAG, not a control path — which is exactly why it is one check
|
|
33
|
+
* and not three detectors that can never fire.
|
|
34
|
+
*/
|
|
35
|
+
export function selectWave(nodes) {
|
|
36
|
+
const statusById = new Map(nodes.map((n) => [n.id, n.status]));
|
|
37
|
+
const active = nodes.filter((n) => ACTIVE.has(n.status));
|
|
38
|
+
if (active.length === 0)
|
|
39
|
+
return { kind: "done" };
|
|
40
|
+
const ready = active
|
|
41
|
+
.filter((n) => n.dependsOn.every((d) => statusById.get(d) === "completed"))
|
|
42
|
+
.sort((a, b) => a.ordinal - b.ordinal)
|
|
43
|
+
.map((n) => n.id);
|
|
44
|
+
if (ready.length === 0)
|
|
45
|
+
return { kind: "stuck", active: active.map((n) => n.id) };
|
|
46
|
+
return { kind: "ready", ids: ready };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/subtasks/scheduler.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;GASG;AACH,MAAM,MAAM,GAA+B,IAAI,GAAG,CAAgB;IAChE,SAAS;IACT,SAAS;CACV,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEjD,MAAM,KAAK,GAAG,MAAM;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC;SAC1E,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;SACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEpB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC5D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { DelegationNames, ResolvedRecipe, SubtaskParams, SubtaskTypeSpec } from "../contract/recipe.js";
|
|
3
|
+
/**
|
|
4
|
+
* The **closed set of subtask types** the main agent may delegate, as the
|
|
5
|
+
* runtime uses it: lookup, the delegate enum, param validation, and the
|
|
6
|
+
* catalogue the delegating model is shown.
|
|
7
|
+
*
|
|
8
|
+
* The set is not declared here, and — unlike the predecessor repo — it is not a
|
|
9
|
+
* module constant. There, `SUBTASK_TYPE_SPECS` was imported at module scope and
|
|
10
|
+
* every derived value (`SUBTASK_TYPES`, `SUBTASK_TYPE_KEYS`, the delegate tool's
|
|
11
|
+
* description, the round contract) was computed at *import time*. That made the
|
|
12
|
+
* registry unoverridable, froze it before `env` exists, and pulled every
|
|
13
|
+
* domain's module into the bundle whether or not the agent used it.
|
|
14
|
+
*
|
|
15
|
+
* So it is a factory. The host builds one registry per DO instance from its
|
|
16
|
+
* installed plugins, and everything downstream reads that object.
|
|
17
|
+
*/
|
|
18
|
+
export type { DelegationNames, SubtaskParams, SubtaskTypeSpec };
|
|
19
|
+
/** A subtask whose params do not satisfy its type's contract. */
|
|
20
|
+
export declare class SubtaskParamsError extends Error {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
export interface SubtaskTypeRegistry {
|
|
24
|
+
/** Every known spec, in declaration order. */
|
|
25
|
+
readonly specs: readonly SubtaskTypeSpec[];
|
|
26
|
+
/** Every known type, keyed by its `key`. */
|
|
27
|
+
readonly byKey: ReadonlyMap<string, SubtaskTypeSpec>;
|
|
28
|
+
/** The type keys in declaration order. Empty when the agent delegates nothing. */
|
|
29
|
+
readonly keys: readonly string[];
|
|
30
|
+
/**
|
|
31
|
+
* The keys as a non-empty tuple for `z.enum` in the delegate schema — the
|
|
32
|
+
* model cannot emit anything outside it, so an unknown type never reaches the
|
|
33
|
+
* data layer.
|
|
34
|
+
*
|
|
35
|
+
* Throws when no type is registered. Not a defensive check but the real
|
|
36
|
+
* contract: an agent with no subtask types has nothing to delegate to, and
|
|
37
|
+
* must not offer a delegate tool at all.
|
|
38
|
+
*/
|
|
39
|
+
enumKeys(): [string, ...string[]];
|
|
40
|
+
/** Look up a type, or null when it is not one we know. */
|
|
41
|
+
spec(type: string): SubtaskTypeSpec | null;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve a subtask type to the recipe it runs under. Throws
|
|
44
|
+
* {@link SubtaskParamsError} for an unknown or retired type — the delegate
|
|
45
|
+
* enum prevents the model from emitting one, so any unknown type reaching
|
|
46
|
+
* execution is a configuration bug and should fail terminally.
|
|
47
|
+
*/
|
|
48
|
+
resolveRecipe(type: string): ResolvedRecipe;
|
|
49
|
+
/**
|
|
50
|
+
* Validate a subtask's params against its type's contract, returning the
|
|
51
|
+
* params to persist. A type with no schema must carry no params — a stray
|
|
52
|
+
* param would otherwise ride along unread, looking meaningful.
|
|
53
|
+
*
|
|
54
|
+
* Shape only: whether an id names something the outside world actually offers
|
|
55
|
+
* is a question for that world, answered when the work starts. Unknown keys
|
|
56
|
+
* are stripped rather than refused — a model that invents one has produced a
|
|
57
|
+
* valid subtask with noise attached, and the noise provably cannot reach the
|
|
58
|
+
* execution.
|
|
59
|
+
*/
|
|
60
|
+
validateParams(type: string, params: SubtaskParams | undefined): SubtaskParams;
|
|
61
|
+
/**
|
|
62
|
+
* Every param key any type declares, as the optional properties of the single
|
|
63
|
+
* flat `params` object the delegate tool advertises.
|
|
64
|
+
*
|
|
65
|
+
* Optional is not a weakening: which keys a given type *requires* is
|
|
66
|
+
* {@link validateParams}'s call, and it still refuses a subtask whose type's
|
|
67
|
+
* params are missing. What this adds is **visibility**. One tool schema has to
|
|
68
|
+
* serve every type, so the only alternative to naming the union of keys here
|
|
69
|
+
* is naming none of them — and a key the schema does not name is a key the
|
|
70
|
+
* model has no legal way to send, whatever the description promises. That is
|
|
71
|
+
* exactly how a domain subtask once reached validation with none of its
|
|
72
|
+
* declared ids: the field was declared as a free-form record, which the
|
|
73
|
+
* provider's schema conversion flattens to an object permitting no keys at all.
|
|
74
|
+
*
|
|
75
|
+
* Descriptions are prefixed with the owning type, so a flat namespace still
|
|
76
|
+
* reads unambiguously to the model (and a key two types share names both).
|
|
77
|
+
*/
|
|
78
|
+
paramProperties(): Record<string, z.ZodType<string | undefined>>;
|
|
79
|
+
/** The type catalogue as the delegating model is shown it. */
|
|
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
|
+
/** Every type's {@link SubtaskTypeSpec.delegationGuidance}, for the round contract. */
|
|
90
|
+
renderDelegationGuidance(names: DelegationNames): string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Build the registry from the specs the installed plugins declared.
|
|
94
|
+
*
|
|
95
|
+
* Duplicate keys are refused rather than last-one-wins: two plugins claiming one
|
|
96
|
+
* type is a misconfiguration whose symptom would otherwise be work silently
|
|
97
|
+
* routed to the wrong domain.
|
|
98
|
+
*/
|
|
99
|
+
export declare function makeSubtaskTypes(specs: readonly SubtaskTypeSpec[]): SubtaskTypeRegistry;
|
|
100
|
+
//# sourceMappingURL=subtask-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subtask-types.d.ts","sourceRoot":"","sources":["../../src/subtasks/subtask-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,aAAa,EACb,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC;AAEhE,iEAAiE;AACjE,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,mBAAmB;IAClC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrD,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAClC,0DAA0D;IAC1D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC;IAC5C;;;;;;;;;;OAUG;IACH,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,GAAG,SAAS,GAChC,aAAa,CAAC;IACjB;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACjE,8DAA8D;IAC9D,WAAW,IAAI,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,kBAAkB,IAAI,MAAM,CAAC;IAC7B,uFAAuF;IACvF,wBAAwB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,eAAe,EAAE,GAChC,mBAAmB,CAmHrB"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** A subtask whose params do not satisfy its type's contract. */
|
|
3
|
+
export class SubtaskParamsError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "SubtaskParamsError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Build the registry from the specs the installed plugins declared.
|
|
11
|
+
*
|
|
12
|
+
* Duplicate keys are refused rather than last-one-wins: two plugins claiming one
|
|
13
|
+
* type is a misconfiguration whose symptom would otherwise be work silently
|
|
14
|
+
* routed to the wrong domain.
|
|
15
|
+
*/
|
|
16
|
+
export function makeSubtaskTypes(specs) {
|
|
17
|
+
const byKey = new Map();
|
|
18
|
+
for (const spec of specs) {
|
|
19
|
+
if (byKey.has(spec.key)) {
|
|
20
|
+
throw new Error(`duplicate subtask type "${spec.key}" — two plugins declare the same type`);
|
|
21
|
+
}
|
|
22
|
+
byKey.set(spec.key, spec);
|
|
23
|
+
}
|
|
24
|
+
const keys = specs.map((s) => s.key);
|
|
25
|
+
const lookup = (type) => byKey.get(type) ?? null;
|
|
26
|
+
return {
|
|
27
|
+
specs,
|
|
28
|
+
byKey,
|
|
29
|
+
keys,
|
|
30
|
+
enumKeys() {
|
|
31
|
+
if (keys.length === 0) {
|
|
32
|
+
throw new Error("no subtask types are registered — an agent with no types cannot delegate, " +
|
|
33
|
+
"so it must not build a delegate tool");
|
|
34
|
+
}
|
|
35
|
+
return keys;
|
|
36
|
+
},
|
|
37
|
+
spec: lookup,
|
|
38
|
+
resolveRecipe(type) {
|
|
39
|
+
const found = lookup(type);
|
|
40
|
+
if (!found)
|
|
41
|
+
throw new SubtaskParamsError(`unknown subtask type: ${type}`);
|
|
42
|
+
return found.recipe;
|
|
43
|
+
},
|
|
44
|
+
validateParams(type, params) {
|
|
45
|
+
const found = lookup(type);
|
|
46
|
+
if (!found)
|
|
47
|
+
throw new SubtaskParamsError(`unknown subtask type: ${type}`);
|
|
48
|
+
const supplied = params ?? {};
|
|
49
|
+
if (!found.params) {
|
|
50
|
+
const extra = Object.keys(supplied);
|
|
51
|
+
if (extra.length > 0) {
|
|
52
|
+
throw new SubtaskParamsError(`subtask type "${type}" takes no params, got: ${extra.join(", ")}`);
|
|
53
|
+
}
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
const parsed = found.params.safeParse(supplied);
|
|
57
|
+
if (!parsed.success) {
|
|
58
|
+
const detail = parsed.error.issues
|
|
59
|
+
.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`)
|
|
60
|
+
.join("; ");
|
|
61
|
+
throw new SubtaskParamsError(`subtask type "${type}" has invalid params — ${detail}`);
|
|
62
|
+
}
|
|
63
|
+
return parsed.data;
|
|
64
|
+
},
|
|
65
|
+
paramProperties() {
|
|
66
|
+
const owners = new Map();
|
|
67
|
+
const declared = new Map();
|
|
68
|
+
for (const s of specs) {
|
|
69
|
+
if (!s.params)
|
|
70
|
+
continue;
|
|
71
|
+
for (const [key, field] of Object.entries(s.params.shape)) {
|
|
72
|
+
owners.set(key, [...(owners.get(key) ?? []), s.key]);
|
|
73
|
+
declared.set(key, field);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return Object.fromEntries([...declared].map(([key, field]) => [
|
|
77
|
+
key,
|
|
78
|
+
// Described *after* `.optional()`, so the text sits on the schema this
|
|
79
|
+
// returns rather than on the type it wraps — readable by both the JSON
|
|
80
|
+
// Schema conversion and anything inspecting these properties directly.
|
|
81
|
+
field
|
|
82
|
+
.optional()
|
|
83
|
+
.describe(`${owners.get(key)?.join("/")}: ${field.description ?? key}`)
|
|
84
|
+
]));
|
|
85
|
+
},
|
|
86
|
+
renderTypes() {
|
|
87
|
+
return specs
|
|
88
|
+
.map((s) => {
|
|
89
|
+
const help = s.paramsHelp ? ` — ${s.paramsHelp}` : "";
|
|
90
|
+
return `- \`${s.key}\`: ${s.description}${help}`;
|
|
91
|
+
})
|
|
92
|
+
.join("\n");
|
|
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
|
+
renderDelegationGuidance(names) {
|
|
102
|
+
const sections = [];
|
|
103
|
+
for (const s of specs) {
|
|
104
|
+
if (s.delegationGuidance)
|
|
105
|
+
sections.push(s.delegationGuidance(names));
|
|
106
|
+
}
|
|
107
|
+
return sections.join("\n\n");
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=subtask-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subtask-types.js","sourceRoot":"","sources":["../../src/subtasks/subtask-types.ts"],"names":[],"mappings":"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"}
|