agentfootprint 10.2.0 → 10.3.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.
Files changed (160) hide show
  1. package/CAPABILITIES.md +1 -0
  2. package/dist/adapters/llm/AnthropicProvider.js +11 -2
  3. package/dist/adapters/llm/AnthropicProvider.js.map +1 -1
  4. package/dist/adapters/llm/BrowserAnthropicProvider.js +11 -2
  5. package/dist/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
  6. package/dist/adapters/llm/MockProvider.js +11 -1
  7. package/dist/adapters/llm/MockProvider.js.map +1 -1
  8. package/dist/adapters/llm/anthropicMessagesWire.js +19 -0
  9. package/dist/adapters/llm/anthropicMessagesWire.js.map +1 -1
  10. package/dist/adapters/llm/anthropicModels.js +48 -14
  11. package/dist/adapters/llm/anthropicModels.js.map +1 -1
  12. package/dist/adapters/llm/wireManifest.js +8 -2
  13. package/dist/adapters/llm/wireManifest.js.map +1 -1
  14. package/dist/adapters/nativeOutputSchema.js +80 -0
  15. package/dist/adapters/nativeOutputSchema.js.map +1 -0
  16. package/dist/adapters/requestRefusal.js +2 -0
  17. package/dist/adapters/requestRefusal.js.map +1 -1
  18. package/dist/adapters/types.js.map +1 -1
  19. package/dist/core/Agent.js +74 -22
  20. package/dist/core/Agent.js.map +1 -1
  21. package/dist/core/agent/AgentBuilder.js +23 -0
  22. package/dist/core/agent/AgentBuilder.js.map +1 -1
  23. package/dist/core/agent/buildDynamicAgentChart.js +5 -0
  24. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  25. package/dist/core/agent/findings/reserved.js +50 -1
  26. package/dist/core/agent/findings/reserved.js.map +1 -1
  27. package/dist/core/agent/nativeOutputFormat.js +389 -0
  28. package/dist/core/agent/nativeOutputFormat.js.map +1 -0
  29. package/dist/core/agent/outputEnforcement.js +35 -1
  30. package/dist/core/agent/outputEnforcement.js.map +1 -1
  31. package/dist/core/agent/stages/answerValidation.js +14 -4
  32. package/dist/core/agent/stages/answerValidation.js.map +1 -1
  33. package/dist/core/agent/stages/callLLM.js +24 -0
  34. package/dist/core/agent/stages/callLLM.js.map +1 -1
  35. package/dist/core/agent/stages/outputRetry.js +1 -0
  36. package/dist/core/agent/stages/outputRetry.js.map +1 -1
  37. package/dist/core/agent/stages/route.js +33 -10
  38. package/dist/core/agent/stages/route.js.map +1 -1
  39. package/dist/core/outputSchema.js.map +1 -1
  40. package/dist/esm/adapters/llm/AnthropicProvider.d.ts +3 -0
  41. package/dist/esm/adapters/llm/AnthropicProvider.js +12 -3
  42. package/dist/esm/adapters/llm/AnthropicProvider.js.map +1 -1
  43. package/dist/esm/adapters/llm/BrowserAnthropicProvider.d.ts +3 -0
  44. package/dist/esm/adapters/llm/BrowserAnthropicProvider.js +12 -3
  45. package/dist/esm/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
  46. package/dist/esm/adapters/llm/MockProvider.d.ts +7 -0
  47. package/dist/esm/adapters/llm/MockProvider.js +11 -1
  48. package/dist/esm/adapters/llm/MockProvider.js.map +1 -1
  49. package/dist/esm/adapters/llm/anthropicMessagesWire.d.ts +13 -0
  50. package/dist/esm/adapters/llm/anthropicMessagesWire.js +19 -0
  51. package/dist/esm/adapters/llm/anthropicMessagesWire.js.map +1 -1
  52. package/dist/esm/adapters/llm/anthropicModels.d.ts +36 -3
  53. package/dist/esm/adapters/llm/anthropicModels.js +46 -13
  54. package/dist/esm/adapters/llm/anthropicModels.js.map +1 -1
  55. package/dist/esm/adapters/llm/wireManifest.d.ts +9 -1
  56. package/dist/esm/adapters/llm/wireManifest.js +8 -2
  57. package/dist/esm/adapters/llm/wireManifest.js.map +1 -1
  58. package/dist/esm/adapters/nativeOutputSchema.d.ts +66 -0
  59. package/dist/esm/adapters/nativeOutputSchema.js +75 -0
  60. package/dist/esm/adapters/nativeOutputSchema.js.map +1 -0
  61. package/dist/esm/adapters/requestRefusal.js +2 -0
  62. package/dist/esm/adapters/requestRefusal.js.map +1 -1
  63. package/dist/esm/adapters/types.d.ts +40 -0
  64. package/dist/esm/adapters/types.js.map +1 -1
  65. package/dist/esm/core/Agent.d.ts +16 -0
  66. package/dist/esm/core/Agent.js +74 -22
  67. package/dist/esm/core/Agent.js.map +1 -1
  68. package/dist/esm/core/agent/AgentBuilder.js +23 -0
  69. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  70. package/dist/esm/core/agent/buildDynamicAgentChart.js +5 -0
  71. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  72. package/dist/esm/core/agent/findings/reserved.d.ts +16 -0
  73. package/dist/esm/core/agent/findings/reserved.js +48 -0
  74. package/dist/esm/core/agent/findings/reserved.js.map +1 -1
  75. package/dist/esm/core/agent/nativeOutputFormat.d.ts +85 -0
  76. package/dist/esm/core/agent/nativeOutputFormat.js +384 -0
  77. package/dist/esm/core/agent/nativeOutputFormat.js.map +1 -0
  78. package/dist/esm/core/agent/outputEnforcement.d.ts +33 -1
  79. package/dist/esm/core/agent/outputEnforcement.js +33 -0
  80. package/dist/esm/core/agent/outputEnforcement.js.map +1 -1
  81. package/dist/esm/core/agent/stages/answerValidation.d.ts +1 -1
  82. package/dist/esm/core/agent/stages/answerValidation.js +14 -4
  83. package/dist/esm/core/agent/stages/answerValidation.js.map +1 -1
  84. package/dist/esm/core/agent/stages/callLLM.d.ts +9 -1
  85. package/dist/esm/core/agent/stages/callLLM.js +24 -0
  86. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  87. package/dist/esm/core/agent/stages/outputRetry.js +1 -0
  88. package/dist/esm/core/agent/stages/outputRetry.js.map +1 -1
  89. package/dist/esm/core/agent/stages/route.js +34 -11
  90. package/dist/esm/core/agent/stages/route.js.map +1 -1
  91. package/dist/esm/core/agent/types.d.ts +19 -3
  92. package/dist/esm/core/outputSchema.d.ts +30 -3
  93. package/dist/esm/core/outputSchema.js.map +1 -1
  94. package/dist/esm/lib/time-travel/receipt.d.ts +11 -0
  95. package/dist/esm/lib/time-travel/receipt.js +8 -2
  96. package/dist/esm/lib/time-travel/receipt.js.map +1 -1
  97. package/dist/esm/providers.d.ts +1 -0
  98. package/dist/esm/providers.js +1 -0
  99. package/dist/esm/providers.js.map +1 -1
  100. package/dist/esm/resilience/withCircuitBreaker.js +7 -0
  101. package/dist/esm/resilience/withCircuitBreaker.js.map +1 -1
  102. package/dist/esm/resilience/withFallback.js +10 -0
  103. package/dist/esm/resilience/withFallback.js.map +1 -1
  104. package/dist/esm/resilience/withRetry.js +8 -0
  105. package/dist/esm/resilience/withRetry.js.map +1 -1
  106. package/dist/lib/time-travel/receipt.js +8 -2
  107. package/dist/lib/time-travel/receipt.js.map +1 -1
  108. package/dist/providers.js +4 -1
  109. package/dist/providers.js.map +1 -1
  110. package/dist/resilience/withCircuitBreaker.js +7 -0
  111. package/dist/resilience/withCircuitBreaker.js.map +1 -1
  112. package/dist/resilience/withFallback.js +10 -0
  113. package/dist/resilience/withFallback.js.map +1 -1
  114. package/dist/resilience/withRetry.js +8 -0
  115. package/dist/resilience/withRetry.js.map +1 -1
  116. package/dist/types/adapters/llm/AnthropicProvider.d.ts +3 -0
  117. package/dist/types/adapters/llm/AnthropicProvider.d.ts.map +1 -1
  118. package/dist/types/adapters/llm/BrowserAnthropicProvider.d.ts +3 -0
  119. package/dist/types/adapters/llm/BrowserAnthropicProvider.d.ts.map +1 -1
  120. package/dist/types/adapters/llm/MockProvider.d.ts +7 -0
  121. package/dist/types/adapters/llm/MockProvider.d.ts.map +1 -1
  122. package/dist/types/adapters/llm/anthropicMessagesWire.d.ts +13 -0
  123. package/dist/types/adapters/llm/anthropicMessagesWire.d.ts.map +1 -1
  124. package/dist/types/adapters/llm/anthropicModels.d.ts +36 -3
  125. package/dist/types/adapters/llm/anthropicModels.d.ts.map +1 -1
  126. package/dist/types/adapters/llm/wireManifest.d.ts +9 -1
  127. package/dist/types/adapters/llm/wireManifest.d.ts.map +1 -1
  128. package/dist/types/adapters/nativeOutputSchema.d.ts +67 -0
  129. package/dist/types/adapters/nativeOutputSchema.d.ts.map +1 -0
  130. package/dist/types/adapters/requestRefusal.d.ts.map +1 -1
  131. package/dist/types/adapters/types.d.ts +40 -0
  132. package/dist/types/adapters/types.d.ts.map +1 -1
  133. package/dist/types/core/Agent.d.ts +16 -0
  134. package/dist/types/core/Agent.d.ts.map +1 -1
  135. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  136. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  137. package/dist/types/core/agent/findings/reserved.d.ts +16 -0
  138. package/dist/types/core/agent/findings/reserved.d.ts.map +1 -1
  139. package/dist/types/core/agent/nativeOutputFormat.d.ts +86 -0
  140. package/dist/types/core/agent/nativeOutputFormat.d.ts.map +1 -0
  141. package/dist/types/core/agent/outputEnforcement.d.ts +33 -1
  142. package/dist/types/core/agent/outputEnforcement.d.ts.map +1 -1
  143. package/dist/types/core/agent/stages/answerValidation.d.ts +1 -1
  144. package/dist/types/core/agent/stages/answerValidation.d.ts.map +1 -1
  145. package/dist/types/core/agent/stages/callLLM.d.ts +9 -1
  146. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  147. package/dist/types/core/agent/stages/outputRetry.d.ts.map +1 -1
  148. package/dist/types/core/agent/stages/route.d.ts.map +1 -1
  149. package/dist/types/core/agent/types.d.ts +19 -3
  150. package/dist/types/core/agent/types.d.ts.map +1 -1
  151. package/dist/types/core/outputSchema.d.ts +30 -3
  152. package/dist/types/core/outputSchema.d.ts.map +1 -1
  153. package/dist/types/lib/time-travel/receipt.d.ts +11 -0
  154. package/dist/types/lib/time-travel/receipt.d.ts.map +1 -1
  155. package/dist/types/providers.d.ts +1 -0
  156. package/dist/types/providers.d.ts.map +1 -1
  157. package/dist/types/resilience/withCircuitBreaker.d.ts.map +1 -1
  158. package/dist/types/resilience/withFallback.d.ts.map +1 -1
  159. package/dist/types/resilience/withRetry.d.ts.map +1 -1
  160. package/package.json +1 -1
@@ -1,10 +1,12 @@
1
1
  /** Request-contract refusals are terminal, not provider availability failures. */
2
2
  import { UnsupportedToolChoiceError } from './forcedToolChoice.js';
3
+ import { UnsupportedNativeOutputError } from './nativeOutputSchema.js';
3
4
  import { UnsupportedThinkingError } from '../thinking/errors.js';
4
5
  import { UnsafeThinkingReplayError } from '../thinking/replay.js';
5
6
  /** Deliberately narrow: unrelated application errors keep their existing policy. */
6
7
  export function isRequestRefusal(error) {
7
8
  return (error instanceof UnsupportedToolChoiceError ||
9
+ error instanceof UnsupportedNativeOutputError ||
8
10
  error instanceof UnsupportedThinkingError ||
9
11
  error instanceof UnsafeThinkingReplayError);
10
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"requestRefusal.js","sourceRoot":"","sources":["../../../src/adapters/requestRefusal.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,oFAAoF;AACpF,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,CACL,KAAK,YAAY,0BAA0B;QAC3C,KAAK,YAAY,wBAAwB;QACzC,KAAK,YAAY,yBAAyB,CAC3C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"requestRefusal.js","sourceRoot":"","sources":["../../../src/adapters/requestRefusal.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,oFAAoF;AACpF,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,CACL,KAAK,YAAY,0BAA0B;QAC3C,KAAK,YAAY,4BAA4B;QAC7C,KAAK,YAAY,wBAAwB;QACzC,KAAK,YAAY,yBAAyB,CAC3C,CAAC;AACJ,CAAC"}
@@ -318,6 +318,22 @@ export interface LLMRequest {
318
318
  readonly type: 'tool';
319
319
  readonly name: string;
320
320
  };
321
+ /**
322
+ * Constrain the model's TEXT answer to a JSON Schema with the provider's
323
+ * own structured output — `.outputSchema(parser, { strategy: 'native' })`.
324
+ * The Anthropic adapters write it as `output_config: { format }`
325
+ * (https://platform.claude.com/docs/en/build-with-claude/structured-outputs).
326
+ *
327
+ * Same rule as {@link toolChoice}: when `nativeOutputSchemaFor(provider,
328
+ * model)` answers false the agent refuses at run start, naming both, and an
329
+ * adapter that cannot put it on its wire refuses with an
330
+ * `UnsupportedNativeOutputError` before anything is sent — never drops it.
331
+ * The schema is the wire copy `nativeOutputFormat` built; send it as-is.
332
+ */
333
+ readonly outputFormat?: {
334
+ readonly type: 'json_schema';
335
+ readonly schema: Readonly<Record<string, unknown>>;
336
+ };
321
337
  }
322
338
  export interface LLMResponse {
323
339
  /** Ordered replay evidence, retained with the assistant message. */
@@ -421,6 +437,14 @@ export interface LLMResponse {
421
437
  export interface WireToolManifest {
422
438
  /** Tool names as they appear in the serialized body, in wire order. */
423
439
  readonly toolNames: readonly string[];
440
+ /**
441
+ * Present only when the serialized body carried a structured-output format
442
+ * (Anthropic's `output_config.format`) — its `type`, read back from the
443
+ * body. Absent means none crossed. A `strategy: 'native'` agent refuses a
444
+ * stated manifest without it: the provider declared the capability and the
445
+ * request went out unconstrained.
446
+ */
447
+ readonly outputFormat?: 'json_schema';
424
448
  }
425
449
  export interface LLMChunk {
426
450
  readonly tokenIndex: number;
@@ -680,6 +704,22 @@ export interface LLMProvider {
680
704
  * forward it as a value. `withFallback` intersects both sides per model.
681
705
  */
682
706
  readonly supportsForcedToolChoice?: (model: string) => boolean;
707
+ /**
708
+ * Whether this adapter puts {@link LLMRequest.outputFormat} on its wire —
709
+ * the provider's own structured output, `strategy: 'native'`. **Absence
710
+ * means NO**, for the reason `carriesForcedToolChoice` gives: a format that
711
+ * quietly vanishes costs the guarantee the strategy was chosen for. Declared
712
+ * by `anthropic()`, `browserAnthropic()` and the mock; read with
713
+ * `nativeOutputSchemaFor(provider, model)`. A WRAPPER must forward it;
714
+ * `withFallback` publishes the AND of its pair.
715
+ */
716
+ readonly carriesNativeOutputSchema?: boolean;
717
+ /**
718
+ * Optional per-model restriction on {@link carriesNativeOutputSchema}, the
719
+ * `supportsForcedToolChoice` twin: both must answer true. A plain function
720
+ * of the model id (no `this`); the adapter resolves its own shorthand.
721
+ */
722
+ readonly supportsNativeOutputSchema?: (model: string) => boolean;
683
723
  /**
684
724
  * `hooks` (v7.8) is optional and additive — implementations may declare
685
725
  * `complete(req)` with no second parameter and stay assignable. A LEAF
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAkOH;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAwB,MAAM,CAAC,MAAM,CAAC;IAC5E,MAAM;IACN,WAAW;CACZ,CAAC,CAAC;AAqpBH;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAsC,EACtC,UAAgC;IAEhC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,UAAU,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC5C,OAAO,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;AACxD,CAAC;AAqID;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAgGpD;uDACuD;AACvD,MAAM,UAAU,kBAAkB,CAChC,OAAoB;IAEpB,OAAO,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAkOH;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAwB,MAAM,CAAC,MAAM,CAAC;IAC5E,MAAM;IACN,WAAW;CACZ,CAAC,CAAC;AA6rBH;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAsC,EACtC,UAAgC;IAEhC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,UAAU,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC5C,OAAO,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;AACxD,CAAC;AAqID;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAgGpD;uDACuD;AACvD,MAAM,UAAU,kBAAkB,CAChC,OAAoB;IAEpB,OAAO,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU,CAAC;AACnD,CAAC"}
@@ -812,6 +812,12 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
812
812
  * on validation failure.
813
813
  */
814
814
  parseOutputAsync<T = unknown>(raw: string): Promise<T>;
815
+ /**
816
+ * A typed answer that failed: rethrow, or — with `.outputFallback()` and an
817
+ * `OutputSchemaError` — hand it to the 3-tier fallback. The one settle for
818
+ * `parseOutputAsync`'s parse failure and `runTyped`'s native stop failure.
819
+ */
820
+ private settleTypedFailure;
815
821
  /**
816
822
  * Corrective re-asks the agent's LAST run paid for, read off its own ledger.
817
823
  *
@@ -1425,6 +1431,16 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
1425
1431
  * even show was broken.
1426
1432
  */
1427
1433
  private assertForcedToolChoiceSupported;
1434
+ /**
1435
+ * Refuse, at run start, a `'native'` output strategy on a provider that
1436
+ * does not put a structured-output format on its wire, or on a model that
1437
+ * does not take one — the `assertForcedToolChoiceSupported` twin, for the
1438
+ * same reasons: run start because a decorated provider is only what it is
1439
+ * once composed; a refusal because `'instruct'` asks in prose for what this
1440
+ * strategy constrains at decoding, and a quiet swap would be config that
1441
+ * lies.
1442
+ */
1443
+ private assertNativeOutputSchemaSupported;
1428
1444
  private createExecutor;
1429
1445
  /**
1430
1446
  * File the run-configuration manifest (9.41.0) — which adapters and
@@ -20,6 +20,7 @@ import { PolicyHaltError } from '../security/PolicyHaltError.js';
20
20
  import { updateSkillHistory as updateSkillHistoryStage } from '../cache/CacheGateDecider.js';
21
21
  import { cacheStrategyFor } from '../cache/cacheStrategyFor.js';
22
22
  import { forcedToolChoiceFor, UnsupportedToolChoiceError } from '../adapters/forcedToolChoice.js';
23
+ import { nativeOutputSchemaFor, UnsupportedNativeOutputError, } from '../adapters/nativeOutputSchema.js';
23
24
  import { isRequestRefusal } from '../adapters/requestRefusal.js';
24
25
  import { assistantReplayFields } from './agent/assistantReplay.js';
25
26
  import { buildBrainFor, describeServingBrain } from './agent/skillBrains.js';
@@ -1423,29 +1424,38 @@ export class Agent extends RunnerBase {
1423
1424
  return applyOutputSchema(raw, parser);
1424
1425
  }
1425
1426
  catch (err) {
1426
- if (!this.outputFallbackCfg || !(err instanceof OutputSchemaError))
1427
- throw err;
1428
- // Engage the 3-tier fallback. The dispatcher gives us the
1429
- // typed-event entry; we synthesize a minimal event shape since
1430
- // these events have no per-stage anchor.
1431
- // Typed via `OutputFallbackEmit`, so the registry — not a grep — is what
1432
- // decides these two names are real. The cast is now only the envelope
1433
- // assembly (type + payload are already checked against the event map).
1434
- const emit = (eventType, payload) => {
1435
- try {
1436
- this.dispatcher.dispatch({
1437
- type: eventType,
1438
- timestamp: Date.now(),
1439
- payload,
1440
- });
1441
- }
1442
- catch {
1443
- /* observability errors must not poison the fallback path */
1444
- }
1445
- };
1446
- return applyOutputFallback(raw, parser, this.outputFallbackCfg, emit, err, this.lastRunRetriesSpent());
1427
+ return this.settleTypedFailure(raw, err);
1447
1428
  }
1448
1429
  }
1430
+ /**
1431
+ * A typed answer that failed: rethrow, or — with `.outputFallback()` and an
1432
+ * `OutputSchemaError` — hand it to the 3-tier fallback. The one settle for
1433
+ * `parseOutputAsync`'s parse failure and `runTyped`'s native stop failure.
1434
+ */
1435
+ async settleTypedFailure(raw, err) {
1436
+ const parser = this.outputSchemaParser;
1437
+ if (!this.outputFallbackCfg || !(err instanceof OutputSchemaError))
1438
+ throw err;
1439
+ // Engage the 3-tier fallback. The dispatcher gives us the
1440
+ // typed-event entry; we synthesize a minimal event shape since
1441
+ // these events have no per-stage anchor.
1442
+ // Typed via `OutputFallbackEmit`, so the registry — not a grep — is what
1443
+ // decides these two names are real. The cast is now only the envelope
1444
+ // assembly (type + payload are already checked against the event map).
1445
+ const emit = (eventType, payload) => {
1446
+ try {
1447
+ this.dispatcher.dispatch({
1448
+ type: eventType,
1449
+ timestamp: Date.now(),
1450
+ payload,
1451
+ });
1452
+ }
1453
+ catch {
1454
+ /* observability errors must not poison the fallback path */
1455
+ }
1456
+ };
1457
+ return applyOutputFallback(raw, parser, this.outputFallbackCfg, emit, err, this.lastRunRetriesSpent());
1458
+ }
1449
1459
  /**
1450
1460
  * Corrective re-asks the agent's LAST run paid for, read off its own ledger.
1451
1461
  *
@@ -1484,6 +1494,15 @@ export class Agent extends RunnerBase {
1484
1494
  throw new Error('Agent.runTyped: run paused — typed mode does not support pauses. ' +
1485
1495
  'Use agent.run() + agent.parseOutput(...) after resume.');
1486
1496
  }
1497
+ // `strategy: 'native'`: an answer whose last attempt failed on a refusal
1498
+ // or truncation stop is refused here even when its text parses — the
1499
+ // format did not hold for it (outputEnforcement.ts · nativeStopFailure).
1500
+ // FIRST, before any delivery path. It takes the same path a parse failure
1501
+ // takes, `.outputFallback()` included.
1502
+ const stopped = this.outputEnforcement?.outputFormat !== undefined ? this.outputContractUnmet() : undefined;
1503
+ if (stopped?.stopReason !== undefined) {
1504
+ return this.settleTypedFailure(out, new OutputSchemaError(stopped.error, { rawOutput: out, stage: stopped.stage }));
1505
+ }
1487
1506
  if (this.answerValidationConfig !== undefined) {
1488
1507
  // The validator judged the schema's JSON output. Do not run a transforming
1489
1508
  // or stateful parser again and hand back a value the validator never saw.
@@ -2991,9 +3010,38 @@ export class Agent extends RunnerBase {
2991
3010
  `{ strategy: 'instruct', retries: N } on this provider — it works on every wire — or ` +
2992
3011
  `run the forced strategy on a provider that declares the capability.`);
2993
3012
  }
3013
+ /**
3014
+ * Refuse, at run start, a `'native'` output strategy on a provider that
3015
+ * does not put a structured-output format on its wire, or on a model that
3016
+ * does not take one — the `assertForcedToolChoiceSupported` twin, for the
3017
+ * same reasons: run start because a decorated provider is only what it is
3018
+ * once composed; a refusal because `'instruct'` asks in prose for what this
3019
+ * strategy constrains at decoding, and a quiet swap would be config that
3020
+ * lies.
3021
+ */
3022
+ assertNativeOutputSchemaSupported() {
3023
+ if (this.outputEnforcement?.outputFormat === undefined)
3024
+ return;
3025
+ const first = this.reliabilityConfig?.providers?.[0];
3026
+ const provider = first?.provider ?? this.provider;
3027
+ const model = first?.model ?? this.model;
3028
+ if (provider.carriesNativeOutputSchema === true) {
3029
+ // A configured agent resolves its model at seed; callLLM judges it there.
3030
+ if ((first === undefined && this.runConfigFn !== undefined) ||
3031
+ nativeOutputSchemaFor(provider, model))
3032
+ return;
3033
+ throw new UnsupportedNativeOutputError({ provider: provider.name, model });
3034
+ }
3035
+ throw new Error(`Agent: .outputSchema(parser, { strategy: 'native' }) needs a provider that puts a ` +
3036
+ `structured-output format on its wire, and '${provider.name}' does not declare one. ` +
3037
+ `anthropic(), browserAnthropic() and the mock do; the Bedrock and gateway adapters do ` +
3038
+ `not in this release. Use { strategy: 'instruct', retries: N } on this provider — it ` +
3039
+ `works on every wire — or run the native strategy on a provider that declares it.`);
3040
+ }
2994
3041
  createExecutor(runOptions) {
2995
3042
  this.assertDeliverableRoles();
2996
3043
  this.assertForcedToolChoiceSupported();
3044
+ this.assertNativeOutputSchemaSupported();
2997
3045
  const correlationId = runOptions?.correlationId;
2998
3046
  const traceId = runOptions?.traceId ?? runOptions?.env?.traceId;
2999
3047
  const sessionId = runOptions?.sessionId;
@@ -4620,6 +4668,10 @@ export class Agent extends RunnerBase {
4620
4668
  ...(this.outputEnforcement?.schemaTool !== undefined && {
4621
4669
  schemaTool: this.outputEnforcement.schemaTool,
4622
4670
  }),
4671
+ // The structured-output format, under `strategy: 'native'` only.
4672
+ ...(this.outputEnforcement?.outputFormat !== undefined && {
4673
+ outputFormat: this.outputEnforcement.outputFormat,
4674
+ }),
4623
4675
  ...(this.thinkingBudget !== undefined && { thinkingBudget: this.thinkingBudget }),
4624
4676
  // Only a configured agent reads `scope.resolvedModel` — see the dep's
4625
4677
  // JSDoc for why this is a build-time flag and not a runtime fallback.
@@ -4751,7 +4803,7 @@ export class Agent extends RunnerBase {
4751
4803
  answerArmed ? true : undefined);
4752
4804
  const routeDecider = this.answerValidationConfig === undefined
4753
4805
  ? baseRouteDecider
4754
- : withAnswerValidation(baseRouteDecider, this.answerValidationConfig, this.outputSchemaParser, artifactStore, () => this.consentOutstanding.size > 0);
4806
+ : withAnswerValidation(baseRouteDecider, this.answerValidationConfig, this.outputSchemaParser, artifactStore, () => this.consentOutstanding.size > 0, this.outputEnforcement?.outputFormat !== undefined);
4755
4807
  // `.limitsTravelWithTheAnswer()` on a TYPED answer — decided once, here.
4756
4808
  // An output schema makes the answer JSON, and the appended block would
4757
4809
  // make it JSON followed by prose, which `runTyped()` cannot parse. So the