@theokit/sdk 2.21.0 → 2.23.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/CHANGELOG.md +57 -0
- package/dist/a2a/index.cjs +99 -19
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.d.cts +2 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.js +99 -19
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/subagent.d.cts +95 -1
- package/dist/a2a/subagent.d.ts +95 -1
- package/dist/{cron-dpvtRoro.d.ts → cron-7CruUd_0.d.ts} +1 -1
- package/dist/{cron-YrmsszEN.d.cts → cron-Bpt_1khA.d.cts} +1 -1
- package/dist/cron.cjs +16 -6
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +2 -2
- package/dist/cron.d.ts +2 -2
- package/dist/cron.js +16 -6
- package/dist/cron.js.map +1 -1
- package/dist/{errors-C4vZPqXf.d.ts → errors-BuwwkrAk.d.ts} +1 -1
- package/dist/{errors-DrcpYVfZ.d.cts → errors-CkCaIqVP.d.cts} +1 -1
- package/dist/errors.d.cts +2 -2
- package/dist/eval.cjs +16 -6
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +16 -6
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +16 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +16 -6
- package/dist/index.js.map +1 -1
- package/dist/{run-BMo8yRwK.d.cts → run-CrIulPF7.d.cts} +22 -2
- package/dist/{run-BMo8yRwK.d.ts → run-CrIulPF7.d.ts} +22 -2
- package/dist/types/agent-prims.d.ts +21 -1
- package/dist/types/agent.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 271f6e4: **SE13 — `modifiedMaxSteps` on `onDelegationStart` (cap the subagent's iterations).**
|
|
8
|
+
|
|
9
|
+
`DelegationStartDecision` (from `@theokit/sdk/a2a`) gains `modifiedMaxSteps?: number`. When an `onDelegationStart` hook returns it (and does not reject), `defineSubAgent` forwards it as `SendOptions.maxIterations` to the child `agent.send`, capping how many tool-loop rounds the subagent may run. Composes with SE10 (`signal`) and SE12 (`messageFilter` preamble) onto a single child `send`. Absent ⇒ the child uses its default iteration ceiling (unchanged).
|
|
10
|
+
|
|
11
|
+
Completes the SE11 `onDelegationStart` decision contract (the deferred `modifiedMaxSteps` — the `SendOptions.maxIterations` plumbing already existed). Additive + backward-compatible. From the Mastra supervisor-agents comparison (SDK Evolution roadmap SE13).
|
|
12
|
+
|
|
13
|
+
- b51dc6a: **SE14 — subagent result-context control (`SubAgentSpec.includeToolResults`).**
|
|
14
|
+
|
|
15
|
+
`defineSubAgent()` (from `@theokit/sdk/a2a`) gains an opt-in `includeToolResults`. When `true`, the child's completed tool-call results (name + result) are appended to the delegation payload returned to the supervisor, inside a delimited `<subagent-tool-results>` block; when absent/`false` the delegation returns the child's final text only — **text-only stays the default** (Mastra's scoped posture).
|
|
16
|
+
|
|
17
|
+
Implemented as a `run.stream()` replay after `run.wait()` (a proven, safe idiom — the run buffers events and `stream()` replays them) collecting `tool_call` events with `status: "completed"`. **No `RunResult` change** — reads the existing public stream surface; tool _args_ are never surfaced (only completed results). Rationale + the `RunResult`-field alternative are recorded in ADR 0006.
|
|
18
|
+
|
|
19
|
+
Additive + backward-compatible (default `false` never touches the stream). From the Mastra supervisor-agents comparison (SDK Evolution roadmap SE14).
|
|
20
|
+
|
|
21
|
+
- 30e02d9: **SE15 — `iteration` count on the delegation-hook context (reject-after-N).**
|
|
22
|
+
|
|
23
|
+
`DelegationStartContext` and `DelegationCompleteContext` (from `@theokit/sdk/a2a`) gain `iteration: number` — a 1-based per-`defineSubAgent`-instance invocation counter, incremented before `onDelegationStart` runs (a rejected delegation still counts). This enables the Mastra reject-after-N-iterations pattern: `onDelegationStart: (ctx) => ctx.iteration > 8 ? { proceed: false, rejectionReason } : { proceed: true }`. `onDelegationComplete` sees the same iteration its `onDelegationStart` did.
|
|
24
|
+
|
|
25
|
+
Also fixes a delegation-hook DX regression: `onDelegationStart` / `onDelegationComplete` now accept a **side-effect-only (void-returning) callback** (e.g. `(ctx) => { log(ctx) }`) — the common case, mirroring Mastra's `async ctx => { … }` hooks — via a shared `DelegationHookResult<T>` return type. Additive + backward-compatible. From the Mastra supervisor-agents comparison (SDK Evolution roadmap SE15).
|
|
26
|
+
|
|
27
|
+
## 2.22.0
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- 12cb30d: **SE10 — subagent delegation forwards the parent's `AbortSignal` (cancellation propagation).**
|
|
32
|
+
|
|
33
|
+
`defineSubAgent()` (from `@theokit/sdk/a2a`) now threads the run's cancellation into the child agent. When the agent loop dispatches the subagent tool it already passes the run's `AbortSignal` as the handler's `ctx.signal`; the subagent handler now forwards that signal to the child `agent.send(input, { signal })`. Aborting the parent run cancels the in-flight subagent at its next step instead of letting it run to completion (and burn tokens).
|
|
34
|
+
|
|
35
|
+
- Additive + backward-compatible: a handler invoked with no `ctx` (single-arg call sites) behaves exactly as before — no signal, no cancellation.
|
|
36
|
+
- The child agent is still disposed in `finally`, including on cancel.
|
|
37
|
+
|
|
38
|
+
Matches the Mastra supervisor-agents "abortSignal forwarded to delegated subagents" behavior (SDK Evolution roadmap SE10).
|
|
39
|
+
|
|
40
|
+
- 8e3249d: **SE11 — delegation lifecycle hooks on `defineSubAgent` (`onDelegationStart` / `onDelegationComplete`).**
|
|
41
|
+
|
|
42
|
+
`SubAgentSpec` (from `@theokit/sdk/a2a`) gains two optional hooks that let the caller intercept a delegation as it happens:
|
|
43
|
+
|
|
44
|
+
- `onDelegationStart({ input, name })` — return `{ proceed: false, rejectionReason }` to reject the delegation (the child never runs; `rejectionReason` becomes the tool result), or `{ modifiedInput }` to rewrite the prompt sent to the child.
|
|
45
|
+
- `onDelegationComplete({ input, name, result?, error? })` — runs after the delegation settles; on success an optional `{ feedback }` is appended to the child's result, and on failure `ctx.error` is set (the error is still re-thrown — never swallowed, Unbreakable Rule 8).
|
|
46
|
+
|
|
47
|
+
Additive + backward-compatible: specs without hooks behave exactly as before. New exported types: `DelegationStartContext`, `DelegationStartDecision`, `DelegationCompleteContext`, `DelegationCompleteDecision`.
|
|
48
|
+
|
|
49
|
+
Matches the Mastra supervisor `onDelegationStart` / `onDelegationComplete` control points (SDK Evolution roadmap SE11).
|
|
50
|
+
|
|
51
|
+
- d2d0d16: **SE12 — opt-in parent-context forwarding for subagents (`messageFilter`).**
|
|
52
|
+
|
|
53
|
+
`SubAgentSpec` (from `@theokit/sdk/a2a`) gains an optional `messageFilter`. When set, `defineSubAgent` forwards a filtered view of the supervisor's conversation to the child; when absent, the child runs input-only — **memory isolation stays the default**.
|
|
54
|
+
|
|
55
|
+
- New `ctx.messages` on the custom-tool handler `ToolContext`: a **read-only, text-only** projection of the current turn's transcript (`ToolContextMessage[]`), threaded by the agent loop the same way `ctx.signal` (#65) and `ctx.context` (M7) are. Non-text parts (tool calls / results) are dropped — a tool never sees raw wire parts or nested tool args.
|
|
56
|
+
- `messageFilter({ messages, input, name })` returns the subset to forward; `defineSubAgent` prepends it to the delegated input as a role-tagged context preamble. A filter returning `[]` forwards nothing. A filter that drops sensitive turns (e.g. anything `confidential`) provably keeps them out of the child context.
|
|
57
|
+
|
|
58
|
+
New exported types: `ToolContextMessage`, `MessageFilterArgs`. Additive + backward-compatible. Rationale + the transcript-exposure trade-off are recorded in ADR 0005. From the Mastra supervisor-agents comparison (SDK Evolution roadmap SE12).
|
|
59
|
+
|
|
3
60
|
## 2.21.0
|
|
4
61
|
|
|
5
62
|
### Minor Changes
|
package/dist/a2a/index.cjs
CHANGED
|
@@ -8326,21 +8326,21 @@ async function executeTool(inputs, resolved, call) {
|
|
|
8326
8326
|
if (resolved.origin === "shell") return runShellTool(inputs, call);
|
|
8327
8327
|
if (resolved.origin === "memory") return runMemoryTool(resolved, call, inputs.context);
|
|
8328
8328
|
if (resolved.origin === "custom")
|
|
8329
|
-
return runCustomTool(resolved, call, inputs.signal, inputs.context);
|
|
8329
|
+
return runCustomTool(resolved, call, inputs.signal, inputs.context, inputs.messages);
|
|
8330
8330
|
return runMcpTool(inputs, resolved, call);
|
|
8331
8331
|
}
|
|
8332
8332
|
async function runMemoryTool(resolved, call, context) {
|
|
8333
8333
|
return runHandlerTool("memory", resolved.memoryHandler, call, void 0, context);
|
|
8334
8334
|
}
|
|
8335
|
-
async function runCustomTool(resolved, call, signal, context) {
|
|
8336
|
-
return runHandlerTool("custom", resolved.customHandler, call, signal, context);
|
|
8335
|
+
async function runCustomTool(resolved, call, signal, context, messages) {
|
|
8336
|
+
return runHandlerTool("custom", resolved.customHandler, call, signal, context, messages);
|
|
8337
8337
|
}
|
|
8338
|
-
async function runHandlerTool(kind, handler, call, signal, context) {
|
|
8338
|
+
async function runHandlerTool(kind, handler, call, signal, context, messages) {
|
|
8339
8339
|
if (handler === void 0) {
|
|
8340
8340
|
return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
|
|
8341
8341
|
}
|
|
8342
8342
|
try {
|
|
8343
|
-
const out = await handler(call.input, { signal, context });
|
|
8343
|
+
const out = await handler(call.input, { signal, context, messages });
|
|
8344
8344
|
if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
|
|
8345
8345
|
return { stdout: out, stderr: "", exitCode: 0 };
|
|
8346
8346
|
} catch (cause) {
|
|
@@ -9165,6 +9165,14 @@ var init_usage_and_cost = __esm({
|
|
|
9165
9165
|
});
|
|
9166
9166
|
|
|
9167
9167
|
// src/internal/agent-loop/loop.ts
|
|
9168
|
+
function projectToolContextMessages(messages) {
|
|
9169
|
+
const projected = [];
|
|
9170
|
+
for (const m of messages) {
|
|
9171
|
+
const content = m.content.flatMap((p) => p.type === "text" ? [p.text] : []).join("");
|
|
9172
|
+
if (content !== "") projected.push({ role: m.role, content });
|
|
9173
|
+
}
|
|
9174
|
+
return projected;
|
|
9175
|
+
}
|
|
9168
9176
|
async function runAgentLoop(inputs) {
|
|
9169
9177
|
const sendSpan = inputs.telemetry?.startSpan("agent.send", {
|
|
9170
9178
|
agentId: inputs.agentId,
|
|
@@ -9405,7 +9413,9 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
|
|
|
9405
9413
|
const outText = await transformLlmOutputText(inputs, llmOutput.text, tCtx);
|
|
9406
9414
|
ctx.messages.push(buildAssistantTurn(outText, llmOutput.toolCalls));
|
|
9407
9415
|
const rawResults = await dispatchTools(
|
|
9408
|
-
|
|
9416
|
+
// SE12 — forward a read-only text projection of the transcript-so-far to tool
|
|
9417
|
+
// handlers via `ctx.messages` (consumed by defineSubAgent's messageFilter).
|
|
9418
|
+
{ ...inputs, messages: projectToolContextMessages(ctx.messages) },
|
|
9409
9419
|
ctx.tools,
|
|
9410
9420
|
llmOutput.toolCalls,
|
|
9411
9421
|
ctx.events,
|
|
@@ -18416,6 +18426,75 @@ var MaxDelegationDepthError = class extends Error {
|
|
|
18416
18426
|
maxDepth;
|
|
18417
18427
|
code = "max_delegation_depth";
|
|
18418
18428
|
};
|
|
18429
|
+
async function applyDelegationStart(spec, input, iteration) {
|
|
18430
|
+
if (spec.onDelegationStart === void 0) return { input };
|
|
18431
|
+
const decision = await spec.onDelegationStart({ input, name: spec.name, iteration });
|
|
18432
|
+
if (decision === void 0) return { input };
|
|
18433
|
+
if (decision.proceed === false)
|
|
18434
|
+
return { reject: decision.rejectionReason ?? "(delegation rejected)" };
|
|
18435
|
+
return {
|
|
18436
|
+
input: decision.modifiedInput ?? input,
|
|
18437
|
+
...decision.modifiedMaxSteps !== void 0 ? { maxSteps: decision.modifiedMaxSteps } : {}
|
|
18438
|
+
};
|
|
18439
|
+
}
|
|
18440
|
+
async function collectChildToolResults(run) {
|
|
18441
|
+
const lines = [];
|
|
18442
|
+
for await (const event of run.stream()) {
|
|
18443
|
+
if (event.type === "tool_call" && event.status === "completed") {
|
|
18444
|
+
const rendered = typeof event.result === "string" ? event.result : JSON.stringify(event.result ?? null);
|
|
18445
|
+
lines.push(`${event.name}: ${rendered}`);
|
|
18446
|
+
}
|
|
18447
|
+
}
|
|
18448
|
+
if (lines.length === 0) return "";
|
|
18449
|
+
return `
|
|
18450
|
+
|
|
18451
|
+
<subagent-tool-results>
|
|
18452
|
+
${lines.join("\n")}
|
|
18453
|
+
</subagent-tool-results>`;
|
|
18454
|
+
}
|
|
18455
|
+
async function runChildAgent(spec, input, signal, maxSteps) {
|
|
18456
|
+
const { Agent: Agent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
18457
|
+
const agent = await Agent2.create({
|
|
18458
|
+
...spec.model ? { model: { id: spec.model } } : {},
|
|
18459
|
+
systemPrompt: spec.instructions,
|
|
18460
|
+
tools: spec.tools ?? []
|
|
18461
|
+
});
|
|
18462
|
+
try {
|
|
18463
|
+
const sendOptions = {
|
|
18464
|
+
...signal !== void 0 ? { signal } : {},
|
|
18465
|
+
...maxSteps !== void 0 ? { maxIterations: maxSteps } : {}
|
|
18466
|
+
};
|
|
18467
|
+
const run = Object.keys(sendOptions).length > 0 ? await agent.send(input, sendOptions) : await agent.send(input);
|
|
18468
|
+
const result = await run.wait();
|
|
18469
|
+
const text = result.result ?? "(no response)";
|
|
18470
|
+
return spec.includeToolResults === true ? text + await collectChildToolResults(run) : text;
|
|
18471
|
+
} finally {
|
|
18472
|
+
agent.dispose();
|
|
18473
|
+
}
|
|
18474
|
+
}
|
|
18475
|
+
async function notifyDelegationError(spec, input, error, iteration) {
|
|
18476
|
+
if (spec.onDelegationComplete === void 0) return;
|
|
18477
|
+
try {
|
|
18478
|
+
await spec.onDelegationComplete({ input, name: spec.name, error, iteration });
|
|
18479
|
+
} catch {
|
|
18480
|
+
}
|
|
18481
|
+
}
|
|
18482
|
+
function applyMessageFilter(spec, input, messages) {
|
|
18483
|
+
if (spec.messageFilter === void 0 || messages === void 0) return input;
|
|
18484
|
+
const filtered = spec.messageFilter({ messages, input, name: spec.name });
|
|
18485
|
+
if (filtered.length === 0) return input;
|
|
18486
|
+
const preamble = filtered.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
18487
|
+
return `Prior conversation:
|
|
18488
|
+
${preamble}
|
|
18489
|
+
|
|
18490
|
+
Task:
|
|
18491
|
+
${input}`;
|
|
18492
|
+
}
|
|
18493
|
+
async function applyDelegationComplete(spec, input, result, iteration) {
|
|
18494
|
+
if (spec.onDelegationComplete === void 0) return result;
|
|
18495
|
+
const completion = await spec.onDelegationComplete({ input, name: spec.name, result, iteration });
|
|
18496
|
+
return completion?.feedback !== void 0 ? result + completion.feedback : result;
|
|
18497
|
+
}
|
|
18419
18498
|
function defineSubAgent(spec, _parentDepth = 0) {
|
|
18420
18499
|
const currentDepth = _parentDepth + 1;
|
|
18421
18500
|
const maxDepth = spec.maxDelegationDepth ?? 3;
|
|
@@ -18425,25 +18504,26 @@ function defineSubAgent(spec, _parentDepth = 0) {
|
|
|
18425
18504
|
const inputSchema = zod.z.object({
|
|
18426
18505
|
input: zod.z.string().describe("Task for the subagent")
|
|
18427
18506
|
});
|
|
18507
|
+
let iteration = 0;
|
|
18428
18508
|
return {
|
|
18429
18509
|
name: spec.name,
|
|
18430
18510
|
description: spec.description,
|
|
18431
18511
|
inputSchema,
|
|
18432
|
-
handler: async (rawInput) => {
|
|
18433
|
-
const { input } = inputSchema.parse(rawInput);
|
|
18434
|
-
|
|
18435
|
-
const
|
|
18436
|
-
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18512
|
+
handler: async (rawInput, ctx) => {
|
|
18513
|
+
const { input: parsed } = inputSchema.parse(rawInput);
|
|
18514
|
+
iteration += 1;
|
|
18515
|
+
const capturedIteration = iteration;
|
|
18516
|
+
const start = await applyDelegationStart(spec, parsed, capturedIteration);
|
|
18517
|
+
if ("reject" in start) return start.reject;
|
|
18518
|
+
const input = applyMessageFilter(spec, start.input, ctx?.messages);
|
|
18519
|
+
let result;
|
|
18440
18520
|
try {
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
agent.dispose();
|
|
18521
|
+
result = await runChildAgent(spec, input, ctx?.signal, start.maxSteps);
|
|
18522
|
+
} catch (error) {
|
|
18523
|
+
await notifyDelegationError(spec, input, error, capturedIteration);
|
|
18524
|
+
throw error;
|
|
18446
18525
|
}
|
|
18526
|
+
return applyDelegationComplete(spec, input, result, capturedIteration);
|
|
18447
18527
|
}
|
|
18448
18528
|
};
|
|
18449
18529
|
}
|