@stigmer/runner 3.38.2 → 3.38.3

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.
Files changed (27) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +12 -10
  3. package/dist/activities/execute-deep-agent/subagent-transformer.js +12 -52
  4. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  5. package/dist/activities/execute-deep-agent/turn-setup.d.ts +5 -4
  6. package/dist/activities/execute-deep-agent/turn-setup.js +68 -24
  7. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -1
  8. package/dist/shared/model-client.d.ts +24 -2
  9. package/dist/shared/model-client.js +8 -0
  10. package/dist/shared/model-client.js.map +1 -1
  11. package/dist/shared/model-registry.d.ts +42 -1
  12. package/dist/shared/model-registry.js +38 -1
  13. package/dist/shared/model-registry.js.map +1 -1
  14. package/dist/shared/thinking-mode.d.ts +51 -4
  15. package/dist/shared/thinking-mode.js +66 -4
  16. package/dist/shared/thinking-mode.js.map +1 -1
  17. package/package.json +6 -5
  18. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +63 -12
  19. package/src/activities/execute-deep-agent/subagent-transformer.ts +24 -63
  20. package/src/activities/execute-deep-agent/turn-setup.ts +70 -19
  21. package/src/shared/__tests__/model-client-sampling.test.ts +56 -2
  22. package/src/shared/__tests__/model-client.test.ts +72 -0
  23. package/src/shared/__tests__/model-registry.test.ts +96 -1
  24. package/src/shared/__tests__/thinking-mode.test.ts +69 -0
  25. package/src/shared/model-client.ts +35 -2
  26. package/src/shared/model-registry.ts +83 -1
  27. package/src/shared/thinking-mode.ts +77 -4
@@ -7,8 +7,39 @@
7
7
  * model-pricing-data.ts) and uses `costTier` + `harness` fields to
8
8
  * dynamically resolve economy-tier models for extraction/summarization,
9
9
  * plus `capabilities` catalog metadata for per-model capability lookups
10
- * (getModelVisionCapability).
10
+ * (getModelVisionCapability) and the request facts a native row states
11
+ * (getNativeRequestProfile).
11
12
  */
13
+ /**
14
+ * How a model reasons, as its registry row declares it (the proto's
15
+ * `ModelCapabilities`):
16
+ *
17
+ * - `shape` is `"adaptive"` when the row declares `adaptiveThinking` (depth
18
+ * adapts; Anthropic `{type: "adaptive"}`), `"budget"` when it declares only
19
+ * `thinking` (a fixed token budget; `{type: "enabled", budget_tokens}`),
20
+ * and `"none"` otherwise. Adaptive wins where a row declares both: it is
21
+ * the current form, and the budget form is deprecated on models that take
22
+ * both.
23
+ * - `required` is the row's `thinkingRequired`, tri-state: `true` for a
24
+ * model that always thinks and refuses to be told not to, `false` for one
25
+ * that accepts an explicit `{type: "disabled"}`, `undefined` for a row that
26
+ * was never assessed. The absence matters: a runner that read it as
27
+ * `false` would send `disabled` to a model that refuses it.
28
+ */
29
+ export interface NativeThinkingProfile {
30
+ readonly shape: "budget" | "adaptive" | "none";
31
+ readonly required: boolean | undefined;
32
+ }
33
+ /**
34
+ * The request facts a native-harness model's registry row states, read by
35
+ * the native execution turn when it builds its model client. One home for
36
+ * what the provider needs to be told about a model (the runner never names
37
+ * models in code); a field is `undefined` when the row does not state it.
38
+ */
39
+ export interface NativeRequestProfile {
40
+ readonly maxOutputTokens: number | undefined;
41
+ readonly thinking: NativeThinkingProfile;
42
+ }
12
43
  /**
13
44
  * Check whether a model identifier is known to the registry.
14
45
  *
@@ -68,5 +99,15 @@ export declare function resolveToApiModelId(registryId: string): Promise<string>
68
99
  * carries the registry id, so both forms arrive here.
69
100
  */
70
101
  export declare function getModelVisionCapability(modelName: string): Promise<boolean | undefined>;
102
+ /**
103
+ * The native-harness row's request facts for a model, matched by registry
104
+ * `id` or `apiModelId` (the execution config carries the former, the
105
+ * registry default the latter) and filtered to `harness: native`: ids such
106
+ * as `claude-sonnet-5` exist on both harnesses, and only the native row
107
+ * describes the native request. `undefined` when the registry is
108
+ * unreachable, the name is empty or Auto, or no native row matches — the
109
+ * caller then sends what it sent before.
110
+ */
111
+ export declare function getNativeRequestProfile(modelName: string): Promise<NativeRequestProfile | undefined>;
71
112
  /** Exposed for testing — resets the in-memory cache. */
72
113
  export declare function _resetRegistryCache(): void;
@@ -7,7 +7,8 @@
7
7
  * model-pricing-data.ts) and uses `costTier` + `harness` fields to
8
8
  * dynamically resolve economy-tier models for extraction/summarization,
9
9
  * plus `capabilities` catalog metadata for per-model capability lookups
10
- * (getModelVisionCapability).
10
+ * (getModelVisionCapability) and the request facts a native row states
11
+ * (getNativeRequestProfile).
11
12
  */
12
13
  import { resolveModelRegistryUrl, buildRegistryHeaders, REGISTRY_RETRY_POLICY, } from "./registry-endpoint.js";
13
14
  import { fetchWithRetry } from "./http-retry.js";
@@ -34,8 +35,26 @@ function parseRegistry(json) {
34
35
  harness: m.harness ?? "native",
35
36
  featured: !!m.featured,
36
37
  visionCapability: parseVisionCapability(m.capabilities),
38
+ maxOutputTokens: parsePositiveInteger(m.maxOutputTokens),
39
+ thinking: parseThinkingProfile(m.capabilities),
37
40
  }));
38
41
  }
42
+ function parsePositiveInteger(value) {
43
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
44
+ }
45
+ /**
46
+ * The row's thinking form. A missing or malformed `capabilities` block
47
+ * declares no shape and leaves `required` unknown, the same tri-state
48
+ * posture as {@link parseVisionCapability}.
49
+ */
50
+ function parseThinkingProfile(capabilities) {
51
+ if (!capabilities || typeof capabilities !== "object")
52
+ return { shape: "none", required: undefined };
53
+ const flags = capabilities;
54
+ const shape = flags.adaptiveThinking === true ? "adaptive" : flags.thinking === true ? "budget" : "none";
55
+ const required = typeof flags.thinkingRequired === "boolean" ? flags.thinkingRequired : undefined;
56
+ return { shape, required };
57
+ }
39
58
  /**
40
59
  * Extract `capabilities.vision` preserving the tri-state: a missing or
41
60
  * malformed `capabilities` block stays `undefined` (never coerced to false).
@@ -207,6 +226,24 @@ export async function getModelVisionCapability(modelName) {
207
226
  const entry = registry.find((m) => m.id === modelName || m.apiModelId === modelName);
208
227
  return entry?.visionCapability;
209
228
  }
229
+ /**
230
+ * The native-harness row's request facts for a model, matched by registry
231
+ * `id` or `apiModelId` (the execution config carries the former, the
232
+ * registry default the latter) and filtered to `harness: native`: ids such
233
+ * as `claude-sonnet-5` exist on both harnesses, and only the native row
234
+ * describes the native request. `undefined` when the registry is
235
+ * unreachable, the name is empty or Auto, or no native row matches — the
236
+ * caller then sends what it sent before.
237
+ */
238
+ export async function getNativeRequestProfile(modelName) {
239
+ if (!modelName || modelName === "default")
240
+ return undefined;
241
+ const registry = await getRegistry();
242
+ const entry = registry.find((m) => m.harness === "native" && (m.id === modelName || m.apiModelId === modelName));
243
+ if (!entry)
244
+ return undefined;
245
+ return { maxOutputTokens: entry.maxOutputTokens, thinking: entry.thinking };
246
+ }
210
247
  /** Exposed for testing — resets the in-memory cache. */
211
248
  export function _resetRegistryCache() {
212
249
  cache = null;
@@ -1 +1 @@
1
- {"version":3,"file":"model-registry.js","sourceRoot":"","sources":["../../src/shared/model-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model-registry.js","sourceRoot":"","sources":["../../src/shared/model-registry.ts"],"names":[],"mappings":"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"}
@@ -16,12 +16,23 @@
16
16
  * rather than pricing-gated, and the estimate/billing paths need no
17
17
  * thinking-specific rates.
18
18
  *
19
- * v1 translates thinking on the Cursor harness only (the explicit
20
- * `thinking` variant parameter, `execute-cursor/service-tier.ts`). No
21
- * native wire mapping exists yet — create-time validation refuses ENABLED
22
- * for native-harness models, mirroring the tier's #361 posture.
19
+ * Each harness translates the mode in its own dialect: the Cursor harness
20
+ * as the explicit `thinking` variant parameter
21
+ * (`execute-cursor/service-tier.ts`), the native harness as Anthropic's
22
+ * `thinking` request parameter in the form the model's native registry row
23
+ * declares ({@link toAnthropicThinking}). ENABLED means "the model reasons
24
+ * before it answers", whichever form the row takes.
25
+ *
26
+ * One model family breaks the "always explicit" rule on purpose: a row
27
+ * that states `thinkingRequired` names a model that always thinks and
28
+ * refuses `{type: "disabled"}` with a 400. Create-time validation refuses
29
+ * an explicit DISABLED there, and the runner sends the model's thinking
30
+ * form whatever the mode, so its reasoning streams as text rather than the
31
+ * empty blocks the model's own `display` default produces.
23
32
  */
33
+ import type { ThinkingConfigParam } from "@anthropic-ai/sdk/resources/messages";
24
34
  import { ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
35
+ import type { NativeThinkingProfile } from "./model-registry.js";
25
36
  /**
26
37
  * The effective mode after platform-default resolution: never UNSPECIFIED.
27
38
  */
@@ -33,3 +44,39 @@ export type EffectiveThinkingMode = ThinkingMode.DISABLED | ThinkingMode.ENABLED
33
44
  export declare function resolveEffectiveThinkingMode(configured: ThinkingMode | undefined): EffectiveThinkingMode;
34
45
  /** Human-readable mode label for logs and error messages. */
35
46
  export declare function thinkingModeLabel(mode: ThinkingMode): string;
47
+ /**
48
+ * The thinking budget sent to a model whose row declares the fixed-budget
49
+ * form. One platform constant, not a user choice (per-execution budgets are
50
+ * a later proto change): 16,000 tokens is room for a real plan while
51
+ * leaving every budget row's output ceiling (64,000 on the smallest) most
52
+ * of its length for the answer. The provider requires at least 1,024 and
53
+ * less than `max_tokens`. No interleaved-thinking beta rides with it: the
54
+ * hosted proxy forwards no `anthropic-beta` header, so these models think
55
+ * at the start of each model call, not between tool calls.
56
+ */
57
+ export declare const BUDGET_THINKING_TOKENS = 16000;
58
+ /**
59
+ * The native request's `thinking` parameter for an execution's effective
60
+ * mode on a model's native row, or `undefined` to send none.
61
+ *
62
+ * - A row that requires thinking gets its thinking form whatever the mode;
63
+ * the model thinks either way, and `display: "summarized"` is what makes
64
+ * its reasoning readable (the newest models default to `"omitted"`).
65
+ * - ENABLED gets the row's form: adaptive with `display: "summarized"`, or
66
+ * the fixed budget. A row that declares no form gets nothing; create-time
67
+ * validation refuses ENABLED there, so this is the fail-safe.
68
+ * - DISABLED gets an explicit `{type: "disabled"}` only where the row
69
+ * declares a thinking form and states `thinkingRequired: false`. Where the
70
+ * flag was never assessed nothing is sent (the request as it was before),
71
+ * because sending `disabled` to a model that requires thinking fails every
72
+ * turn; a row with no thinking form has no parameter to pin.
73
+ * - No row (an unreachable registry, an unknown model) sends nothing.
74
+ */
75
+ export declare function toAnthropicThinking(mode: EffectiveThinkingMode, profile: NativeThinkingProfile | undefined): ThinkingConfigParam | undefined;
76
+ /**
77
+ * Whether a graph built on this row reasons natively: true exactly when
78
+ * {@link toAnthropicThinking} asks for thinking. Derived from the same
79
+ * mapping, never decided separately, so the `think` tool and the structured
80
+ * output strategy can never disagree with the wire.
81
+ */
82
+ export declare function graphThinks(mode: EffectiveThinkingMode, profile: NativeThinkingProfile | undefined): boolean;
@@ -16,10 +16,19 @@
16
16
  * rather than pricing-gated, and the estimate/billing paths need no
17
17
  * thinking-specific rates.
18
18
  *
19
- * v1 translates thinking on the Cursor harness only (the explicit
20
- * `thinking` variant parameter, `execute-cursor/service-tier.ts`). No
21
- * native wire mapping exists yet — create-time validation refuses ENABLED
22
- * for native-harness models, mirroring the tier's #361 posture.
19
+ * Each harness translates the mode in its own dialect: the Cursor harness
20
+ * as the explicit `thinking` variant parameter
21
+ * (`execute-cursor/service-tier.ts`), the native harness as Anthropic's
22
+ * `thinking` request parameter in the form the model's native registry row
23
+ * declares ({@link toAnthropicThinking}). ENABLED means "the model reasons
24
+ * before it answers", whichever form the row takes.
25
+ *
26
+ * One model family breaks the "always explicit" rule on purpose: a row
27
+ * that states `thinkingRequired` names a model that always thinks and
28
+ * refuses `{type: "disabled"}` with a 400. Create-time validation refuses
29
+ * an explicit DISABLED there, and the runner sends the model's thinking
30
+ * form whatever the mode, so its reasoning streams as text rather than the
31
+ * empty blocks the model's own `display` default produces.
23
32
  */
24
33
  import { ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
25
34
  /**
@@ -40,4 +49,57 @@ export function thinkingModeLabel(mode) {
40
49
  return "unspecified";
41
50
  }
42
51
  }
52
+ /**
53
+ * The thinking budget sent to a model whose row declares the fixed-budget
54
+ * form. One platform constant, not a user choice (per-execution budgets are
55
+ * a later proto change): 16,000 tokens is room for a real plan while
56
+ * leaving every budget row's output ceiling (64,000 on the smallest) most
57
+ * of its length for the answer. The provider requires at least 1,024 and
58
+ * less than `max_tokens`. No interleaved-thinking beta rides with it: the
59
+ * hosted proxy forwards no `anthropic-beta` header, so these models think
60
+ * at the start of each model call, not between tool calls.
61
+ */
62
+ export const BUDGET_THINKING_TOKENS = 16_000;
63
+ /**
64
+ * The native request's `thinking` parameter for an execution's effective
65
+ * mode on a model's native row, or `undefined` to send none.
66
+ *
67
+ * - A row that requires thinking gets its thinking form whatever the mode;
68
+ * the model thinks either way, and `display: "summarized"` is what makes
69
+ * its reasoning readable (the newest models default to `"omitted"`).
70
+ * - ENABLED gets the row's form: adaptive with `display: "summarized"`, or
71
+ * the fixed budget. A row that declares no form gets nothing; create-time
72
+ * validation refuses ENABLED there, so this is the fail-safe.
73
+ * - DISABLED gets an explicit `{type: "disabled"}` only where the row
74
+ * declares a thinking form and states `thinkingRequired: false`. Where the
75
+ * flag was never assessed nothing is sent (the request as it was before),
76
+ * because sending `disabled` to a model that requires thinking fails every
77
+ * turn; a row with no thinking form has no parameter to pin.
78
+ * - No row (an unreachable registry, an unknown model) sends nothing.
79
+ */
80
+ export function toAnthropicThinking(mode, profile) {
81
+ if (profile === undefined)
82
+ return undefined;
83
+ if (profile.required === true || mode === ThinkingMode.ENABLED) {
84
+ switch (profile.shape) {
85
+ case "adaptive":
86
+ return { type: "adaptive", display: "summarized" };
87
+ case "budget":
88
+ return { type: "enabled", budget_tokens: BUDGET_THINKING_TOKENS };
89
+ case "none":
90
+ return undefined;
91
+ }
92
+ }
93
+ return profile.required === false && profile.shape !== "none" ? { type: "disabled" } : undefined;
94
+ }
95
+ /**
96
+ * Whether a graph built on this row reasons natively: true exactly when
97
+ * {@link toAnthropicThinking} asks for thinking. Derived from the same
98
+ * mapping, never decided separately, so the `think` tool and the structured
99
+ * output strategy can never disagree with the wire.
100
+ */
101
+ export function graphThinks(mode, profile) {
102
+ const thinking = toAnthropicThinking(mode, profile);
103
+ return thinking !== undefined && thinking.type !== "disabled";
104
+ }
43
105
  //# sourceMappingURL=thinking-mode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thinking-mode.js","sourceRoot":"","sources":["../../src/shared/thinking-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AAO5F;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAC1C,UAAoC;IAEpC,OAAO,UAAU,KAAK,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC5F,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IAClD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY,CAAC,OAAO;YACvB,OAAO,SAAS,CAAC;QACnB,KAAK,YAAY,CAAC,QAAQ;YACxB,OAAO,UAAU,CAAC;QACpB;YACE,OAAO,aAAa,CAAC;IACzB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"thinking-mode.js","sourceRoot":"","sources":["../../src/shared/thinking-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AAS5F;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAC1C,UAAoC;IAEpC,OAAO,UAAU,KAAK,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC5F,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IAClD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY,CAAC,OAAO;YACvB,OAAO,SAAS,CAAC;QACnB,KAAK,YAAY,CAAC,QAAQ;YACxB,OAAO,UAAU,CAAC;QACpB;YACE,OAAO,aAAa,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAA2B,EAC3B,OAA0C;IAE1C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;QAC/D,QAAQ,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,KAAK,UAAU;gBACb,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;YACrD,KAAK,QAAQ;gBACX,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,CAAC;YACpE,KAAK,MAAM;gBACT,OAAO,SAAS,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,KAAK,KAAK,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACnG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,IAA2B,EAC3B,OAA0C;IAE1C,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC;AAChE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/runner",
3
- "version": "3.38.2",
3
+ "version": "3.38.3",
4
4
  "description": "Embeddable Temporal worker for the Stigmer AI agent platform — handles agent execution, workflow orchestration, and MCP server management",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -87,6 +87,7 @@
87
87
  "dependencies": {
88
88
  "@anthropic-ai/bedrock-sdk": "^0.32.1",
89
89
  "@anthropic-ai/foundry-sdk": "^0.4.1",
90
+ "@anthropic-ai/sdk": "0.116.0",
90
91
  "@anthropic-ai/vertex-sdk": "^0.19.1",
91
92
  "@azure/identity": "^4.13.1",
92
93
  "@bufbuild/protobuf": "2.12.0",
@@ -108,10 +109,10 @@
108
109
  "@opentelemetry/sdk-metrics": "^2.0.0",
109
110
  "@opentelemetry/sdk-trace-base": "^2.0.0",
110
111
  "@opentelemetry/sdk-trace-node": "^2.0.0",
111
- "@stigmer/outbound": "3.38.2",
112
- "@stigmer/protos": "3.38.2",
113
- "@stigmer/temporal-codecs": "3.38.2",
114
- "@stigmer/zip-structure": "3.38.2",
112
+ "@stigmer/outbound": "3.38.3",
113
+ "@stigmer/protos": "3.38.3",
114
+ "@stigmer/temporal-codecs": "3.38.3",
115
+ "@stigmer/zip-structure": "3.38.3",
115
116
  "@temporalio/activity": "1.16.2",
116
117
  "@temporalio/common": "1.16.2",
117
118
  "@temporalio/interceptors-opentelemetry": "1.16.2",
@@ -1,6 +1,8 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
2
  import type { StructuredTool } from "@langchain/core/tools";
3
3
  import type { McpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
4
+ import { ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
+ import type { EffectiveThinkingMode } from "../../../shared/thinking-mode.js";
4
6
 
5
7
  import {
6
8
  BUILTIN_SUBAGENT_TYPES,
@@ -12,12 +14,15 @@ import {
12
14
  transformAndCompileSubagents,
13
15
  type TransformedSubagent,
14
16
  } from "../subagent-transformer.js";
17
+ import { _resetRegistryCache } from "../../../shared/model-registry.js";
15
18
  import { mockWorkspaceBackend } from "../../../__test-utils__/mock-workspace.js";
16
19
 
17
20
  // =========================================================================
18
21
  // Test helpers
19
22
  // =========================================================================
20
23
 
24
+ const NOT_THINKING: EffectiveThinkingMode = ThinkingMode.DISABLED;
25
+
21
26
  function mockTool(name: string): StructuredTool {
22
27
  return { name, description: `Mock tool: ${name}` } as unknown as StructuredTool;
23
28
  }
@@ -145,7 +150,8 @@ describe("transformSingleSubagent", () => {
145
150
  parentMcpTools: [] as StructuredTool[],
146
151
  parentMcpServerToolMap: new Map<string, StructuredTool[]>(),
147
152
  parentMcpUsages: [] as McpServerUsage[],
148
- parentHasNativeThinking: true,
153
+ parentThinks: true,
154
+ thinkingMode: NOT_THINKING,
149
155
  parentModelName: "claude-sonnet-4-6",
150
156
  webFetchPosture: "strict" as const,
151
157
  };
@@ -197,11 +203,11 @@ describe("transformSingleSubagent", () => {
197
203
  expect(result!.systemPrompt).toContain("## Response rules");
198
204
  });
199
205
 
200
- it("does not inject think tool when parent has native thinking", async () => {
206
+ it("does not inject think tool when it inherits a parent that thinks", async () => {
201
207
  const proto = mockSubAgentProto();
202
208
  const result = await transformSingleSubagent(proto, {
203
209
  ...baseOpts,
204
- parentHasNativeThinking: true,
210
+ parentThinks: true,
205
211
  });
206
212
 
207
213
  const hasThinkTool = result!.tools.some(
@@ -211,24 +217,65 @@ describe("transformSingleSubagent", () => {
211
217
  });
212
218
 
213
219
  it("always injects web_fetch, regardless of thinking support", async () => {
214
- for (const parentHasNativeThinking of [true, false]) {
220
+ for (const parentThinks of [true, false]) {
215
221
  const result = await transformSingleSubagent(mockSubAgentProto(), {
216
222
  ...baseOpts,
217
- parentHasNativeThinking,
223
+ parentThinks,
218
224
  });
219
225
  const hasWebFetch = result!.tools.some((t) => t.name === "web_fetch");
220
226
  expect(hasWebFetch).toBe(true);
221
227
  }
222
228
  });
223
229
 
224
- it("injects think tool when parent lacks native thinking", async () => {
230
+ it("injects think tool when it inherits a parent that does not think", async () => {
225
231
  const proto = mockSubAgentProto();
226
232
  const result = await transformSingleSubagent(proto, {
227
233
  ...baseOpts,
228
- parentHasNativeThinking: false,
234
+ parentThinks: false,
235
+ });
236
+
237
+ expect(result!.tools.map((t) => t.name)).toContain("think");
238
+ });
239
+
240
+ describe("a sub-agent with its own model answers from its own native row", () => {
241
+ beforeEach(() => {
242
+ _resetRegistryCache();
243
+ vi.restoreAllMocks();
244
+ vi.spyOn(global, "fetch").mockResolvedValue({
245
+ ok: true,
246
+ json: () => Promise.resolve({
247
+ models: [
248
+ { id: "claude-sonnet-5", provider: "anthropic", harness: "native", capabilities: { adaptiveThinking: true, thinkingRequired: false } },
249
+ { id: "claude-haiku-4.5", provider: "anthropic", harness: "native", capabilities: { thinking: true, thinkingRequired: false } },
250
+ { id: "claude-fable-5", provider: "anthropic", harness: "native", capabilities: { adaptiveThinking: true, thinkingRequired: true } },
251
+ { id: "composer-2.5", provider: "cursor", harness: "cursor" },
252
+ ],
253
+ }),
254
+ } as Response);
229
255
  });
230
256
 
231
- expect(result!.tools.length).toBeGreaterThan(0);
257
+ afterEach(() => {
258
+ _resetRegistryCache();
259
+ });
260
+
261
+ const thinkBound = async (modelOverride: string, thinkingMode: ThinkingMode.DISABLED | ThinkingMode.ENABLED, parentThinks: boolean) => {
262
+ const result = await transformSingleSubagent(mockSubAgentProto({ modelOverride }), { ...baseOpts, thinkingMode, parentThinks });
263
+ return result!.tools.some((t) => t.name === "think");
264
+ };
265
+
266
+ it("a thinking execution drops think on a model that can think, whatever the parent does", async () => {
267
+ expect(await thinkBound("claude-sonnet-5", ThinkingMode.ENABLED, false)).toBe(false);
268
+ expect(await thinkBound("claude-haiku-4.5", ThinkingMode.ENABLED, false)).toBe(false);
269
+ });
270
+
271
+ it("a non-thinking execution binds think, unless the sub-agent's model always thinks", async () => {
272
+ expect(await thinkBound("claude-sonnet-5", ThinkingMode.DISABLED, true)).toBe(true);
273
+ expect(await thinkBound("claude-fable-5", ThinkingMode.DISABLED, false)).toBe(false);
274
+ });
275
+
276
+ it("a model with no native row binds think: its request carries no thinking", async () => {
277
+ expect(await thinkBound("composer-2.5", ThinkingMode.ENABLED, true)).toBe(true);
278
+ });
232
279
  });
233
280
 
234
281
  it("returns null for invalid model override", async () => {
@@ -451,7 +498,8 @@ describe("transformAndCompileSubagents", () => {
451
498
  workspaceBackend: mockWorkspaceBackend(),
452
499
  approvalGate: null,
453
500
  parentModelName: "claude-sonnet-4-6",
454
- parentHasNativeThinking: true,
501
+ parentThinks: true,
502
+ thinkingMode: NOT_THINKING,
455
503
  webFetchPosture: "strict" as const,
456
504
  costCap: undefined,
457
505
  };
@@ -622,7 +670,8 @@ describe("subagent-transformer edge cases", () => {
622
670
  parentMcpTools: [],
623
671
  parentMcpServerToolMap: new Map(),
624
672
  parentMcpUsages: [],
625
- parentHasNativeThinking: true,
673
+ parentThinks: true,
674
+ thinkingMode: NOT_THINKING,
626
675
  parentModelName: "claude-sonnet-4-6",
627
676
  webFetchPosture: "strict",
628
677
  });
@@ -649,7 +698,8 @@ describe("subagent-transformer edge cases", () => {
649
698
  workspaceBackend: mockWorkspaceBackend({ rootDir: "" }),
650
699
  approvalGate: null,
651
700
  parentModelName: "claude-sonnet-4-6",
652
- parentHasNativeThinking: true,
701
+ parentThinks: true,
702
+ thinkingMode: NOT_THINKING,
653
703
  webFetchPosture: "strict",
654
704
  costCap: undefined,
655
705
  } as Parameters<typeof transformAndCompileSubagents>[0]);
@@ -673,7 +723,8 @@ describe("subagent-transformer edge cases", () => {
673
723
  workspaceBackend: mockWorkspaceBackend(),
674
724
  approvalGate: null,
675
725
  parentModelName: "claude-sonnet-4-6",
676
- parentHasNativeThinking: true,
726
+ parentThinks: true,
727
+ thinkingMode: NOT_THINKING,
677
728
  webFetchPosture: "strict",
678
729
  costCap: undefined,
679
730
  } as Parameters<typeof transformAndCompileSubagents>[0]);
@@ -39,7 +39,8 @@ import type { CostAdvisoryMiddleware, StigmerMiddleware } from "../../middleware
39
39
  import { createThinkTool, createWebFetchTool, type GuardPosture } from "../../tools/index.js";
40
40
  import { buildSubAgentMiddleware } from "./subagent-wiring.js";
41
41
  import { SubAgentGate } from "../../shared/subagent-gate.js";
42
- import { isModelRegistered } from "../../shared/model-registry.js";
42
+ import { getNativeRequestProfile, isModelRegistered } from "../../shared/model-registry.js";
43
+ import { graphThinks, type EffectiveThinkingMode } from "../../shared/thinking-mode.js";
43
44
  import type { SkillMetadata } from "../../shared/skill-resolver.js";
44
45
  import { renderSkillsSection } from "./prompt-builder.js";
45
46
  import { ENGINE_TOOL } from "./engine-tools.js";
@@ -175,7 +176,15 @@ export interface SubagentTransformOptions {
175
176
  */
176
177
  readonly casObserver?: CasCaptureObserver;
177
178
  readonly parentModelName: string;
178
- readonly parentHasNativeThinking: boolean;
179
+ /**
180
+ * Whether the parent's graph reasons natively (thinking-mode.ts
181
+ * `graphThinks` on its row). A sub-agent that names no model of its own
182
+ * runs on the parent's, so it inherits this answer; a sub-agent with a
183
+ * `model_override` is answered from its own model's row.
184
+ */
185
+ readonly parentThinks: boolean;
186
+ /** The execution's effective thinking mode, read against a sub-agent's own row. */
187
+ readonly thinkingMode: EffectiveThinkingMode;
179
188
  /**
180
189
  * URL-guard posture for the native `web_fetch` tool, inherited from the
181
190
  * parent (resolveGuardPosture(config.mode) in turn-setup.ts) so a sub-agent
@@ -303,7 +312,8 @@ export async function transformSingleSubagent(
303
312
  readonly parentMcpTools: readonly StructuredTool[];
304
313
  readonly parentMcpServerToolMap: ReadonlyMap<string, readonly StructuredTool[]>;
305
314
  readonly parentMcpUsages: readonly McpServerUsage[];
306
- readonly parentHasNativeThinking: boolean;
315
+ readonly parentThinks: boolean;
316
+ readonly thinkingMode: EffectiveThinkingMode;
307
317
  readonly parentModelName: string;
308
318
  readonly webFetchPosture: GuardPosture;
309
319
  },
@@ -330,12 +340,14 @@ export async function transformSingleSubagent(
330
340
  // Build tools list — start with filtered MCP tools (populated by caller)
331
341
  const tools: StructuredTool[] = [];
332
342
 
333
- // Inject think tool when model lacks native extended thinking
334
- const saHasNativeThinking = model
335
- ? await _modelSupportsThinking(model)
336
- : opts.parentHasNativeThinking;
343
+ // `think` is a reasoning aid for a graph that does not reason natively.
344
+ // Whether this one does is the same answer its model's request carries
345
+ // (the model factory maps the same mode against the same row).
346
+ const saThinks = model
347
+ ? graphThinks(opts.thinkingMode, (await getNativeRequestProfile(model))?.thinking)
348
+ : opts.parentThinks;
337
349
 
338
- if (!saHasNativeThinking) {
350
+ if (!saThinks) {
339
351
  tools.push(createThinkTool() as unknown as StructuredTool);
340
352
  }
341
353
 
@@ -444,30 +456,6 @@ export function resolveSubagentSkillPrompt(
444
456
  return renderSkillsSection(skills.get(subAgent.name) ?? []);
445
457
  }
446
458
 
447
- /**
448
- * Heuristic check for native extended thinking support. Models with thinking
449
- * support don't need the explicit think tool. Read for the parent (does its
450
- * graph carry `think`?) and inherited by every sub-agent that names no model
451
- * of its own. Moved from `setup.ts` in #1096: the compile step is where it
452
- * is consumed, and the adapter's setup reads it from here too.
453
- */
454
- export function modelHasNativeThinking(modelId: string): boolean {
455
- const lower = modelId.toLowerCase();
456
-
457
- if (lower.includes("haiku")) return false;
458
- if (lower.includes("gpt-4o-mini")) return false;
459
-
460
- if (lower.includes("claude") && (
461
- lower.includes("sonnet") || lower.includes("opus")
462
- )) return true;
463
-
464
- if (lower.includes("o1") || lower.includes("o3") || lower.includes("o4")) {
465
- return true;
466
- }
467
-
468
- return false;
469
- }
470
-
471
459
  // =========================================================================
472
460
  // Compilation pipeline
473
461
  // =========================================================================
@@ -654,7 +642,8 @@ export async function transformAndCompileSubagents(
654
642
  approvalGate,
655
643
  casObserver,
656
644
  parentModelName,
657
- parentHasNativeThinking,
645
+ parentThinks,
646
+ thinkingMode,
658
647
  webFetchPosture,
659
648
  costAdvisory,
660
649
  modelFactory,
@@ -694,7 +683,8 @@ export async function transformAndCompileSubagents(
694
683
  parentMcpTools,
695
684
  parentMcpServerToolMap,
696
685
  parentMcpUsages,
697
- parentHasNativeThinking,
686
+ parentThinks,
687
+ thinkingMode,
698
688
  parentModelName,
699
689
  webFetchPosture,
700
690
  });
@@ -780,32 +770,3 @@ export async function transformAndCompileSubagents(
780
770
  );
781
771
  return compiled;
782
772
  }
783
-
784
- // =========================================================================
785
- // Private helpers
786
- // =========================================================================
787
-
788
- /**
789
- * Check if a model supports native extended thinking.
790
- *
791
- * Heuristic: models with "claude" in the name that are NOT haiku-class
792
- * support thinking. Models with "o1", "o3", "o4" support reasoning.
793
- * This is a conservative heuristic — err on the side of injecting the
794
- * think tool (it's harmless if the model already thinks natively).
795
- */
796
- async function _modelSupportsThinking(modelId: string): Promise<boolean> {
797
- const lower = modelId.toLowerCase();
798
-
799
- if (lower.includes("haiku")) return false;
800
- if (lower.includes("gpt-4o-mini")) return false;
801
-
802
- if (lower.includes("claude") && (
803
- lower.includes("sonnet") || lower.includes("opus")
804
- )) return true;
805
-
806
- if (lower.includes("o1") || lower.includes("o3") || lower.includes("o4")) {
807
- return true;
808
- }
809
-
810
- return false;
811
- }