@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.
@@ -5,9 +5,69 @@
5
5
  * invoked by the LLM, creates a child agent and sends the input as a
6
6
  * message. EC-2: delegation depth tracked to prevent infinite recursion.
7
7
  *
8
+ * SE10 — the handler forwards the parent run's `AbortSignal` to the child.
9
+ * SE11 — optional `onDelegationStart` / `onDelegationComplete` lifecycle hooks
10
+ * let the caller reject, rewrite, observe, or annotate a delegation.
11
+ *
8
12
  * @public
9
13
  */
10
- import type { CustomTool } from "../types/agent.js";
14
+ import type { CustomTool, ToolContextMessage } from "../types/agent.js";
15
+ /** Arguments passed to {@link SubAgentSpec.messageFilter} (SE12). */
16
+ export interface MessageFilterArgs {
17
+ /** The supervisor transcript (read-only text projection) available to this delegation. */
18
+ messages: readonly ToolContextMessage[];
19
+ /** The prompt about to be delegated (after any `onDelegationStart` rewrite). */
20
+ input: string;
21
+ /** The subagent's name. */
22
+ name: string;
23
+ }
24
+ /** Context passed to {@link SubAgentSpec.onDelegationStart} before the child runs. */
25
+ export interface DelegationStartContext {
26
+ input: string;
27
+ name: string;
28
+ /**
29
+ * SE15 — 1-based count of times THIS subagent tool has been invoked (a
30
+ * per-`defineSubAgent`-instance counter). Incremented before this hook runs;
31
+ * a rejected delegation still counts. Enables reject-after-N patterns.
32
+ */
33
+ iteration: number;
34
+ }
35
+ /**
36
+ * Decision returned from {@link SubAgentSpec.onDelegationStart}. Discriminated on
37
+ * `proceed` so a rejection (`proceed: false` + `rejectionReason`) and an approval
38
+ * (`modifiedInput`) cannot be mixed into one nonsensical object.
39
+ */
40
+ export type DelegationStartDecision = {
41
+ proceed: false;
42
+ rejectionReason?: string;
43
+ } | {
44
+ proceed?: true;
45
+ modifiedInput?: string;
46
+ /** SE13 — cap the child's iteration count (forwarded as `SendOptions.maxIterations`). */
47
+ modifiedMaxSteps?: number;
48
+ };
49
+ /** Context passed to {@link SubAgentSpec.onDelegationComplete} after the child settles. */
50
+ export interface DelegationCompleteContext {
51
+ input: string;
52
+ name: string;
53
+ /** The child's text result (present on success). */
54
+ result?: string;
55
+ /** The error the child threw (present on failure); the error is still re-thrown. */
56
+ error?: unknown;
57
+ /** SE15 — the same 1-based iteration this delegation's `onDelegationStart` saw. */
58
+ iteration: number;
59
+ }
60
+ /**
61
+ * The return of a delegation hook: a decision, a promise of one, or nothing —
62
+ * `void` lets a side-effect-only callback (`(ctx) => { log(ctx) }`) type-check,
63
+ * which is the common case (mirrors Mastra's `async ctx => { ... }` hooks).
64
+ */
65
+ type DelegationHookResult<T> = T | void | Promise<T | void>;
66
+ /** Decision returned from {@link SubAgentSpec.onDelegationComplete}. */
67
+ export interface DelegationCompleteDecision {
68
+ /** Appended to the child's result string. */
69
+ feedback?: string;
70
+ }
11
71
  export interface SubAgentSpec {
12
72
  name: string;
13
73
  description: string;
@@ -15,6 +75,39 @@ export interface SubAgentSpec {
15
75
  model?: string;
16
76
  tools?: CustomTool[];
17
77
  maxDelegationDepth?: number;
78
+ /**
79
+ * SE11 — called before the supervisor delegates. Return `{ proceed: false }`
80
+ * to reject (the child never runs and `rejectionReason` becomes the tool
81
+ * result), or `{ modifiedInput }` to rewrite the delegated prompt. A throwing
82
+ * hook surfaces (never silently swallowed).
83
+ */
84
+ onDelegationStart?: (ctx: DelegationStartContext) => DelegationHookResult<DelegationStartDecision>;
85
+ /**
86
+ * SE11 — called after the delegation settles. On success `ctx.result` is set
87
+ * and an optional `{ feedback }` is appended to it. On failure `ctx.error` is
88
+ * set and the original error is ALWAYS re-thrown after this hook runs — a throw
89
+ * from this hook on the error path is suppressed so it cannot mask the
90
+ * delegation's real failure (on the success path a throw does propagate).
91
+ */
92
+ onDelegationComplete?: (ctx: DelegationCompleteContext) => DelegationHookResult<DelegationCompleteDecision>;
93
+ /**
94
+ * SE12 — opt-in parent-context forwarding. When set, the supervisor transcript
95
+ * (`ctx.messages`, a read-only text projection) is passed to this filter and the
96
+ * returned subset is forwarded to the child as a role-tagged context preamble
97
+ * prepended to the delegated input. When ABSENT the child runs input-only —
98
+ * memory isolation stays the default. A filter returning `[]` forwards nothing.
99
+ * A throwing filter propagates (fail-fast, never swallowed — same contract as
100
+ * `onDelegationStart`); the delegation surfaces as a tool error.
101
+ */
102
+ messageFilter?: (args: MessageFilterArgs) => readonly ToolContextMessage[];
103
+ /**
104
+ * SE14 — opt-in subagent result-context control. When `true`, the child's
105
+ * completed tool-call results (name + result) are appended to the delegation
106
+ * payload returned to the supervisor, inside a `<subagent-tool-results>` block.
107
+ * When absent/`false` the delegation returns the child's final text only —
108
+ * text-only stays the default (Mastra's scoped posture). See ADR 0006.
109
+ */
110
+ includeToolResults?: boolean;
18
111
  }
19
112
  export declare class MaxDelegationDepthError extends Error {
20
113
  readonly currentDepth: number;
@@ -23,3 +116,4 @@ export declare class MaxDelegationDepthError extends Error {
23
116
  constructor(currentDepth: number, maxDepth: number);
24
117
  }
25
118
  export declare function defineSubAgent(spec: SubAgentSpec, _parentDepth?: number): CustomTool;
119
+ export {};
@@ -5,9 +5,69 @@
5
5
  * invoked by the LLM, creates a child agent and sends the input as a
6
6
  * message. EC-2: delegation depth tracked to prevent infinite recursion.
7
7
  *
8
+ * SE10 — the handler forwards the parent run's `AbortSignal` to the child.
9
+ * SE11 — optional `onDelegationStart` / `onDelegationComplete` lifecycle hooks
10
+ * let the caller reject, rewrite, observe, or annotate a delegation.
11
+ *
8
12
  * @public
9
13
  */
10
- import type { CustomTool } from "../types/agent.js";
14
+ import type { CustomTool, ToolContextMessage } from "../types/agent.js";
15
+ /** Arguments passed to {@link SubAgentSpec.messageFilter} (SE12). */
16
+ export interface MessageFilterArgs {
17
+ /** The supervisor transcript (read-only text projection) available to this delegation. */
18
+ messages: readonly ToolContextMessage[];
19
+ /** The prompt about to be delegated (after any `onDelegationStart` rewrite). */
20
+ input: string;
21
+ /** The subagent's name. */
22
+ name: string;
23
+ }
24
+ /** Context passed to {@link SubAgentSpec.onDelegationStart} before the child runs. */
25
+ export interface DelegationStartContext {
26
+ input: string;
27
+ name: string;
28
+ /**
29
+ * SE15 — 1-based count of times THIS subagent tool has been invoked (a
30
+ * per-`defineSubAgent`-instance counter). Incremented before this hook runs;
31
+ * a rejected delegation still counts. Enables reject-after-N patterns.
32
+ */
33
+ iteration: number;
34
+ }
35
+ /**
36
+ * Decision returned from {@link SubAgentSpec.onDelegationStart}. Discriminated on
37
+ * `proceed` so a rejection (`proceed: false` + `rejectionReason`) and an approval
38
+ * (`modifiedInput`) cannot be mixed into one nonsensical object.
39
+ */
40
+ export type DelegationStartDecision = {
41
+ proceed: false;
42
+ rejectionReason?: string;
43
+ } | {
44
+ proceed?: true;
45
+ modifiedInput?: string;
46
+ /** SE13 — cap the child's iteration count (forwarded as `SendOptions.maxIterations`). */
47
+ modifiedMaxSteps?: number;
48
+ };
49
+ /** Context passed to {@link SubAgentSpec.onDelegationComplete} after the child settles. */
50
+ export interface DelegationCompleteContext {
51
+ input: string;
52
+ name: string;
53
+ /** The child's text result (present on success). */
54
+ result?: string;
55
+ /** The error the child threw (present on failure); the error is still re-thrown. */
56
+ error?: unknown;
57
+ /** SE15 — the same 1-based iteration this delegation's `onDelegationStart` saw. */
58
+ iteration: number;
59
+ }
60
+ /**
61
+ * The return of a delegation hook: a decision, a promise of one, or nothing —
62
+ * `void` lets a side-effect-only callback (`(ctx) => { log(ctx) }`) type-check,
63
+ * which is the common case (mirrors Mastra's `async ctx => { ... }` hooks).
64
+ */
65
+ type DelegationHookResult<T> = T | void | Promise<T | void>;
66
+ /** Decision returned from {@link SubAgentSpec.onDelegationComplete}. */
67
+ export interface DelegationCompleteDecision {
68
+ /** Appended to the child's result string. */
69
+ feedback?: string;
70
+ }
11
71
  export interface SubAgentSpec {
12
72
  name: string;
13
73
  description: string;
@@ -15,6 +75,39 @@ export interface SubAgentSpec {
15
75
  model?: string;
16
76
  tools?: CustomTool[];
17
77
  maxDelegationDepth?: number;
78
+ /**
79
+ * SE11 — called before the supervisor delegates. Return `{ proceed: false }`
80
+ * to reject (the child never runs and `rejectionReason` becomes the tool
81
+ * result), or `{ modifiedInput }` to rewrite the delegated prompt. A throwing
82
+ * hook surfaces (never silently swallowed).
83
+ */
84
+ onDelegationStart?: (ctx: DelegationStartContext) => DelegationHookResult<DelegationStartDecision>;
85
+ /**
86
+ * SE11 — called after the delegation settles. On success `ctx.result` is set
87
+ * and an optional `{ feedback }` is appended to it. On failure `ctx.error` is
88
+ * set and the original error is ALWAYS re-thrown after this hook runs — a throw
89
+ * from this hook on the error path is suppressed so it cannot mask the
90
+ * delegation's real failure (on the success path a throw does propagate).
91
+ */
92
+ onDelegationComplete?: (ctx: DelegationCompleteContext) => DelegationHookResult<DelegationCompleteDecision>;
93
+ /**
94
+ * SE12 — opt-in parent-context forwarding. When set, the supervisor transcript
95
+ * (`ctx.messages`, a read-only text projection) is passed to this filter and the
96
+ * returned subset is forwarded to the child as a role-tagged context preamble
97
+ * prepended to the delegated input. When ABSENT the child runs input-only —
98
+ * memory isolation stays the default. A filter returning `[]` forwards nothing.
99
+ * A throwing filter propagates (fail-fast, never swallowed — same contract as
100
+ * `onDelegationStart`); the delegation surfaces as a tool error.
101
+ */
102
+ messageFilter?: (args: MessageFilterArgs) => readonly ToolContextMessage[];
103
+ /**
104
+ * SE14 — opt-in subagent result-context control. When `true`, the child's
105
+ * completed tool-call results (name + result) are appended to the delegation
106
+ * payload returned to the supervisor, inside a `<subagent-tool-results>` block.
107
+ * When absent/`false` the delegation returns the child's final text only —
108
+ * text-only stays the default (Mastra's scoped posture). See ADR 0006.
109
+ */
110
+ includeToolResults?: boolean;
18
111
  }
19
112
  export declare class MaxDelegationDepthError extends Error {
20
113
  readonly currentDepth: number;
@@ -23,3 +116,4 @@ export declare class MaxDelegationDepthError extends Error {
23
116
  constructor(currentDepth: number, maxDepth: number);
24
117
  }
25
118
  export declare function defineSubAgent(spec: SubAgentSpec, _parentDepth?: number): CustomTool;
119
+ export {};
@@ -1,4 +1,4 @@
1
- import { C as CustomTool, M as ModelSelection, Z as SDKUserMessage, $ as SendOptions, b as Run, G as GenerateOptions, j as GenerateRunResult, F as RunToCompletionOptions, H as RunToCompletionResult, S as SDKMessage, a6 as StreamToCompletionResult, a as McpServerConfig } from './run-BMo8yRwK.js';
1
+ import { C as CustomTool, M as ModelSelection, Z as SDKUserMessage, $ as SendOptions, b as Run, G as GenerateOptions, j as GenerateRunResult, F as RunToCompletionOptions, H as RunToCompletionResult, S as SDKMessage, a6 as StreamToCompletionResult, a as McpServerConfig } from './run-CrIulPF7.js';
2
2
  import * as zod from 'zod';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as CustomTool, M as ModelSelection, Z as SDKUserMessage, $ as SendOptions, b as Run, G as GenerateOptions, j as GenerateRunResult, F as RunToCompletionOptions, H as RunToCompletionResult, S as SDKMessage, a6 as StreamToCompletionResult, a as McpServerConfig } from './run-BMo8yRwK.cjs';
1
+ import { C as CustomTool, M as ModelSelection, Z as SDKUserMessage, $ as SendOptions, b as Run, G as GenerateOptions, j as GenerateRunResult, F as RunToCompletionOptions, H as RunToCompletionResult, S as SDKMessage, a6 as StreamToCompletionResult, a as McpServerConfig } from './run-CrIulPF7.cjs';
2
2
  import * as zod from 'zod';
3
3
 
4
4
  /**
package/dist/cron.cjs CHANGED
@@ -9454,21 +9454,21 @@ async function executeTool(inputs, resolved, call) {
9454
9454
  if (resolved.origin === "shell") return runShellTool(inputs, call);
9455
9455
  if (resolved.origin === "memory") return runMemoryTool(resolved, call, inputs.context);
9456
9456
  if (resolved.origin === "custom")
9457
- return runCustomTool(resolved, call, inputs.signal, inputs.context);
9457
+ return runCustomTool(resolved, call, inputs.signal, inputs.context, inputs.messages);
9458
9458
  return runMcpTool(inputs, resolved, call);
9459
9459
  }
9460
9460
  async function runMemoryTool(resolved, call, context) {
9461
9461
  return runHandlerTool("memory", resolved.memoryHandler, call, void 0, context);
9462
9462
  }
9463
- async function runCustomTool(resolved, call, signal, context) {
9464
- return runHandlerTool("custom", resolved.customHandler, call, signal, context);
9463
+ async function runCustomTool(resolved, call, signal, context, messages) {
9464
+ return runHandlerTool("custom", resolved.customHandler, call, signal, context, messages);
9465
9465
  }
9466
- async function runHandlerTool(kind, handler, call, signal, context) {
9466
+ async function runHandlerTool(kind, handler, call, signal, context, messages) {
9467
9467
  if (handler === void 0) {
9468
9468
  return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
9469
9469
  }
9470
9470
  try {
9471
- const out = await handler(call.input, { signal, context });
9471
+ const out = await handler(call.input, { signal, context, messages });
9472
9472
  if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
9473
9473
  return { stdout: out, stderr: "", exitCode: 0 };
9474
9474
  } catch (cause) {
@@ -10228,6 +10228,14 @@ function computeUsageCost(inputs, usage) {
10228
10228
  }
10229
10229
 
10230
10230
  // src/internal/agent-loop/loop.ts
10231
+ function projectToolContextMessages(messages) {
10232
+ const projected = [];
10233
+ for (const m of messages) {
10234
+ const content = m.content.flatMap((p) => p.type === "text" ? [p.text] : []).join("");
10235
+ if (content !== "") projected.push({ role: m.role, content });
10236
+ }
10237
+ return projected;
10238
+ }
10231
10239
  var MAX_NUDGE_ATTEMPTS = 2;
10232
10240
  var MAX_STOP_FEEDBACK_ATTEMPTS = 2;
10233
10241
  async function runAgentLoop(inputs) {
@@ -10470,7 +10478,9 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
10470
10478
  const outText = await transformLlmOutputText(inputs, llmOutput.text, tCtx);
10471
10479
  ctx.messages.push(buildAssistantTurn(outText, llmOutput.toolCalls));
10472
10480
  const rawResults = await dispatchTools(
10473
- inputs,
10481
+ // SE12 — forward a read-only text projection of the transcript-so-far to tool
10482
+ // handlers via `ctx.messages` (consumed by defineSubAgent's messageFilter).
10483
+ { ...inputs, messages: projectToolContextMessages(ctx.messages) },
10474
10484
  ctx.tools,
10475
10485
  llmOutput.toolCalls,
10476
10486
  ctx.events,