agentfootprint 7.24.0 → 7.26.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 (220) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +5 -3
  3. package/ai-instructions/claude-code/SKILL.md +1 -1
  4. package/dist/adapters/hosting/agentcore.js +112 -1
  5. package/dist/adapters/hosting/agentcore.js.map +1 -1
  6. package/dist/adapters/llm/AnthropicProvider.js +10 -0
  7. package/dist/adapters/llm/AnthropicProvider.js.map +1 -1
  8. package/dist/adapters/llm/BedrockProvider.js +13 -1
  9. package/dist/adapters/llm/BedrockProvider.js.map +1 -1
  10. package/dist/adapters/llm/BrowserAnthropicProvider.js +6 -0
  11. package/dist/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
  12. package/dist/adapters/llm/BrowserOpenAIProvider.js +18 -0
  13. package/dist/adapters/llm/BrowserOpenAIProvider.js.map +1 -1
  14. package/dist/adapters/llm/MockProvider.js +9 -0
  15. package/dist/adapters/llm/MockProvider.js.map +1 -1
  16. package/dist/adapters/llm/OpenAIProvider.js +21 -0
  17. package/dist/adapters/llm/OpenAIProvider.js.map +1 -1
  18. package/dist/conventions.js +12 -0
  19. package/dist/conventions.js.map +1 -1
  20. package/dist/core/Agent.js +56 -2
  21. package/dist/core/Agent.js.map +1 -1
  22. package/dist/core/agent/AgentBuilder.js +98 -1
  23. package/dist/core/agent/AgentBuilder.js.map +1 -1
  24. package/dist/core/agent/buildAgentChart.js +12 -2
  25. package/dist/core/agent/buildAgentChart.js.map +1 -1
  26. package/dist/core/agent/buildDynamicAgentChart.js +12 -3
  27. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  28. package/dist/core/agent/outputEnforcement.js +192 -0
  29. package/dist/core/agent/outputEnforcement.js.map +1 -0
  30. package/dist/core/agent/stages/callLLM.js +31 -1
  31. package/dist/core/agent/stages/callLLM.js.map +1 -1
  32. package/dist/core/agent/stages/outputRetry.js +102 -0
  33. package/dist/core/agent/stages/outputRetry.js.map +1 -0
  34. package/dist/core/agent/stages/route.js +111 -6
  35. package/dist/core/agent/stages/route.js.map +1 -1
  36. package/dist/core/outputSchema.js.map +1 -1
  37. package/dist/esm/adapters/hosting/agentcore.d.ts +50 -1
  38. package/dist/esm/adapters/hosting/agentcore.js +110 -0
  39. package/dist/esm/adapters/hosting/agentcore.js.map +1 -1
  40. package/dist/esm/adapters/llm/AnthropicProvider.d.ts +10 -0
  41. package/dist/esm/adapters/llm/AnthropicProvider.js +10 -0
  42. package/dist/esm/adapters/llm/AnthropicProvider.js.map +1 -1
  43. package/dist/esm/adapters/llm/BedrockProvider.d.ts +9 -0
  44. package/dist/esm/adapters/llm/BedrockProvider.js +13 -1
  45. package/dist/esm/adapters/llm/BedrockProvider.js.map +1 -1
  46. package/dist/esm/adapters/llm/BrowserAnthropicProvider.d.ts +1 -0
  47. package/dist/esm/adapters/llm/BrowserAnthropicProvider.js +6 -0
  48. package/dist/esm/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
  49. package/dist/esm/adapters/llm/BrowserOpenAIProvider.d.ts +4 -0
  50. package/dist/esm/adapters/llm/BrowserOpenAIProvider.js +18 -0
  51. package/dist/esm/adapters/llm/BrowserOpenAIProvider.js.map +1 -1
  52. package/dist/esm/adapters/llm/MockProvider.d.ts +9 -0
  53. package/dist/esm/adapters/llm/MockProvider.js +9 -0
  54. package/dist/esm/adapters/llm/MockProvider.js.map +1 -1
  55. package/dist/esm/adapters/llm/OpenAIProvider.d.ts +12 -0
  56. package/dist/esm/adapters/llm/OpenAIProvider.js +21 -0
  57. package/dist/esm/adapters/llm/OpenAIProvider.js.map +1 -1
  58. package/dist/esm/adapters/types.d.ts +46 -0
  59. package/dist/esm/conventions.d.ts +4 -0
  60. package/dist/esm/conventions.js +12 -0
  61. package/dist/esm/conventions.js.map +1 -1
  62. package/dist/esm/core/Agent.d.ts +26 -1
  63. package/dist/esm/core/Agent.js +56 -2
  64. package/dist/esm/core/Agent.js.map +1 -1
  65. package/dist/esm/core/agent/AgentBuilder.d.ts +15 -0
  66. package/dist/esm/core/agent/AgentBuilder.js +98 -1
  67. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  68. package/dist/esm/core/agent/buildAgentChart.d.ts +13 -1
  69. package/dist/esm/core/agent/buildAgentChart.js +12 -2
  70. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  71. package/dist/esm/core/agent/buildDynamicAgentChart.js +12 -3
  72. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  73. package/dist/esm/core/agent/outputEnforcement.d.ts +173 -0
  74. package/dist/esm/core/agent/outputEnforcement.js +180 -0
  75. package/dist/esm/core/agent/outputEnforcement.js.map +1 -0
  76. package/dist/esm/core/agent/stages/callLLM.d.ts +15 -0
  77. package/dist/esm/core/agent/stages/callLLM.js +31 -1
  78. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  79. package/dist/esm/core/agent/stages/outputRetry.d.ts +34 -0
  80. package/dist/esm/core/agent/stages/outputRetry.js +98 -0
  81. package/dist/esm/core/agent/stages/outputRetry.js.map +1 -0
  82. package/dist/esm/core/agent/stages/route.d.ts +18 -2
  83. package/dist/esm/core/agent/stages/route.js +111 -6
  84. package/dist/esm/core/agent/stages/route.js.map +1 -1
  85. package/dist/esm/core/agent/types.d.ts +18 -0
  86. package/dist/esm/core/outputSchema.d.ts +51 -0
  87. package/dist/esm/core/outputSchema.js.map +1 -1
  88. package/dist/esm/events/payloads.d.ts +47 -1
  89. package/dist/esm/events/registry.d.ts +3 -1
  90. package/dist/esm/events/registry.js +2 -0
  91. package/dist/esm/events/registry.js.map +1 -1
  92. package/dist/esm/hosting/errors.d.ts +44 -2
  93. package/dist/esm/hosting/errors.js +63 -0
  94. package/dist/esm/hosting/errors.js.map +1 -1
  95. package/dist/esm/hosting/headers.d.ts +16 -0
  96. package/dist/esm/hosting/headers.js +24 -0
  97. package/dist/esm/hosting/headers.js.map +1 -0
  98. package/dist/esm/hosting/httpHost.d.ts +70 -4
  99. package/dist/esm/hosting/httpHost.js +211 -47
  100. package/dist/esm/hosting/httpHost.js.map +1 -1
  101. package/dist/esm/hosting/index.d.ts +23 -8
  102. package/dist/esm/hosting/index.js +21 -6
  103. package/dist/esm/hosting/index.js.map +1 -1
  104. package/dist/esm/hosting/nodeHost.d.ts +23 -0
  105. package/dist/esm/hosting/nodeHost.js +21 -1
  106. package/dist/esm/hosting/nodeHost.js.map +1 -1
  107. package/dist/esm/hosting/types.d.ts +212 -6
  108. package/dist/esm/hosting/types.js +7 -5
  109. package/dist/esm/hosting/types.js.map +1 -1
  110. package/dist/esm/hosting/webSocketConversation.d.ts +101 -0
  111. package/dist/esm/hosting/webSocketConversation.js +341 -0
  112. package/dist/esm/hosting/webSocketConversation.js.map +1 -0
  113. package/dist/esm/hosting/webSocketFrames.d.ts +164 -0
  114. package/dist/esm/hosting/webSocketFrames.js +284 -0
  115. package/dist/esm/hosting/webSocketFrames.js.map +1 -0
  116. package/dist/esm/hosting-providers.d.ts +7 -2
  117. package/dist/esm/hosting-providers.js +7 -2
  118. package/dist/esm/hosting-providers.js.map +1 -1
  119. package/dist/esm/index.d.ts +2 -1
  120. package/dist/esm/index.js +5 -0
  121. package/dist/esm/index.js.map +1 -1
  122. package/dist/esm/resilience/withCircuitBreaker.js +5 -0
  123. package/dist/esm/resilience/withCircuitBreaker.js.map +1 -1
  124. package/dist/esm/resilience/withFallback.js +5 -0
  125. package/dist/esm/resilience/withFallback.js.map +1 -1
  126. package/dist/esm/resilience/withRetry.js +6 -0
  127. package/dist/esm/resilience/withRetry.js.map +1 -1
  128. package/dist/events/registry.js +2 -0
  129. package/dist/events/registry.js.map +1 -1
  130. package/dist/hosting/errors.js +66 -1
  131. package/dist/hosting/errors.js.map +1 -1
  132. package/dist/hosting/headers.js +28 -0
  133. package/dist/hosting/headers.js.map +1 -0
  134. package/dist/hosting/httpHost.js +211 -47
  135. package/dist/hosting/httpHost.js.map +1 -1
  136. package/dist/hosting/index.js +23 -6
  137. package/dist/hosting/index.js.map +1 -1
  138. package/dist/hosting/nodeHost.js +20 -0
  139. package/dist/hosting/nodeHost.js.map +1 -1
  140. package/dist/hosting/types.js +7 -5
  141. package/dist/hosting/types.js.map +1 -1
  142. package/dist/hosting/webSocketConversation.js +345 -0
  143. package/dist/hosting/webSocketConversation.js.map +1 -0
  144. package/dist/hosting/webSocketFrames.js +297 -0
  145. package/dist/hosting/webSocketFrames.js.map +1 -0
  146. package/dist/hosting-providers.js +8 -2
  147. package/dist/hosting-providers.js.map +1 -1
  148. package/dist/index.js +9 -1
  149. package/dist/index.js.map +1 -1
  150. package/dist/resilience/withCircuitBreaker.js +5 -0
  151. package/dist/resilience/withCircuitBreaker.js.map +1 -1
  152. package/dist/resilience/withFallback.js +5 -0
  153. package/dist/resilience/withFallback.js.map +1 -1
  154. package/dist/resilience/withRetry.js +6 -0
  155. package/dist/resilience/withRetry.js.map +1 -1
  156. package/dist/types/adapters/hosting/agentcore.d.ts +50 -1
  157. package/dist/types/adapters/hosting/agentcore.d.ts.map +1 -1
  158. package/dist/types/adapters/llm/AnthropicProvider.d.ts +10 -0
  159. package/dist/types/adapters/llm/AnthropicProvider.d.ts.map +1 -1
  160. package/dist/types/adapters/llm/BedrockProvider.d.ts +9 -0
  161. package/dist/types/adapters/llm/BedrockProvider.d.ts.map +1 -1
  162. package/dist/types/adapters/llm/BrowserAnthropicProvider.d.ts +1 -0
  163. package/dist/types/adapters/llm/BrowserAnthropicProvider.d.ts.map +1 -1
  164. package/dist/types/adapters/llm/BrowserOpenAIProvider.d.ts +4 -0
  165. package/dist/types/adapters/llm/BrowserOpenAIProvider.d.ts.map +1 -1
  166. package/dist/types/adapters/llm/MockProvider.d.ts +9 -0
  167. package/dist/types/adapters/llm/MockProvider.d.ts.map +1 -1
  168. package/dist/types/adapters/llm/OpenAIProvider.d.ts +12 -0
  169. package/dist/types/adapters/llm/OpenAIProvider.d.ts.map +1 -1
  170. package/dist/types/adapters/types.d.ts +46 -0
  171. package/dist/types/adapters/types.d.ts.map +1 -1
  172. package/dist/types/conventions.d.ts +4 -0
  173. package/dist/types/conventions.d.ts.map +1 -1
  174. package/dist/types/core/Agent.d.ts +26 -1
  175. package/dist/types/core/Agent.d.ts.map +1 -1
  176. package/dist/types/core/agent/AgentBuilder.d.ts +15 -0
  177. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  178. package/dist/types/core/agent/buildAgentChart.d.ts +13 -1
  179. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  180. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  181. package/dist/types/core/agent/outputEnforcement.d.ts +174 -0
  182. package/dist/types/core/agent/outputEnforcement.d.ts.map +1 -0
  183. package/dist/types/core/agent/stages/callLLM.d.ts +15 -0
  184. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  185. package/dist/types/core/agent/stages/outputRetry.d.ts +35 -0
  186. package/dist/types/core/agent/stages/outputRetry.d.ts.map +1 -0
  187. package/dist/types/core/agent/stages/route.d.ts +18 -2
  188. package/dist/types/core/agent/stages/route.d.ts.map +1 -1
  189. package/dist/types/core/agent/types.d.ts +18 -0
  190. package/dist/types/core/agent/types.d.ts.map +1 -1
  191. package/dist/types/core/outputSchema.d.ts +51 -0
  192. package/dist/types/core/outputSchema.d.ts.map +1 -1
  193. package/dist/types/events/payloads.d.ts +47 -1
  194. package/dist/types/events/payloads.d.ts.map +1 -1
  195. package/dist/types/events/registry.d.ts +3 -1
  196. package/dist/types/events/registry.d.ts.map +1 -1
  197. package/dist/types/hosting/errors.d.ts +44 -2
  198. package/dist/types/hosting/errors.d.ts.map +1 -1
  199. package/dist/types/hosting/headers.d.ts +17 -0
  200. package/dist/types/hosting/headers.d.ts.map +1 -0
  201. package/dist/types/hosting/httpHost.d.ts +70 -4
  202. package/dist/types/hosting/httpHost.d.ts.map +1 -1
  203. package/dist/types/hosting/index.d.ts +23 -8
  204. package/dist/types/hosting/index.d.ts.map +1 -1
  205. package/dist/types/hosting/nodeHost.d.ts +23 -0
  206. package/dist/types/hosting/nodeHost.d.ts.map +1 -1
  207. package/dist/types/hosting/types.d.ts +212 -6
  208. package/dist/types/hosting/types.d.ts.map +1 -1
  209. package/dist/types/hosting/webSocketConversation.d.ts +102 -0
  210. package/dist/types/hosting/webSocketConversation.d.ts.map +1 -0
  211. package/dist/types/hosting/webSocketFrames.d.ts +165 -0
  212. package/dist/types/hosting/webSocketFrames.d.ts.map +1 -0
  213. package/dist/types/hosting-providers.d.ts +7 -2
  214. package/dist/types/hosting-providers.d.ts.map +1 -1
  215. package/dist/types/index.d.ts +2 -1
  216. package/dist/types/index.d.ts.map +1 -1
  217. package/dist/types/resilience/withCircuitBreaker.d.ts.map +1 -1
  218. package/dist/types/resilience/withFallback.d.ts.map +1 -1
  219. package/dist/types/resilience/withRetry.d.ts.map +1 -1
  220. package/package.json +1 -1
@@ -21,6 +21,7 @@ import type { ReliabilityScope } from '../../reliability/types.js';
21
21
  import type { WindowRecord } from './window/types.js';
22
22
  import type { MessagesDelivery } from './delivery/types.js';
23
23
  import type { MiddlewareDecision } from './middleware/types.js';
24
+ import type { OutputAttempt } from './outputEnforcement.js';
24
25
  /**
25
26
  * Dials for the deferred observer queue (RFC-001) — only meaningful with
26
27
  * `observerDelivery: 'deferred'` (passing them without it throws at
@@ -360,6 +361,23 @@ export interface AgentState {
360
361
  * taken later can find the moment the text changed and who changed it.
361
362
  * Written only by an agent that configured a chain; absent otherwise. */
362
363
  middlewareDecisions?: readonly MiddlewareDecision[];
364
+ /** One row per final-answer attempt, in order: what was answered, whether
365
+ * it satisfied the schema, and — when it did not — the validator's own
366
+ * words and the correction that went back. Read it from
367
+ * `snapshot.sharedState` to see why a run took three turns to answer.
368
+ * Written only by an agent that opted into `retries`; absent otherwise. */
369
+ outputAttempts?: readonly OutputAttempt[];
370
+ /** In-flight hand-off from the Route decider (which judges the answer and
371
+ * picks the branch) to the retry stage (which writes the correction). Not
372
+ * a record — the record is `outputAttempts`. Always freshly written by the
373
+ * decider immediately before the retry branch runs, so it is never read
374
+ * stale. */
375
+ outputSchemaFailure?: {
376
+ readonly attempt: number;
377
+ readonly stage: 'json-parse' | 'schema-validate';
378
+ readonly error: string;
379
+ readonly path?: string;
380
+ };
363
381
  /** Set by the seed / prepare-final stage when a `messageMiddleware` returned
364
382
  * `deny`. Read at the API boundary, where it becomes a `MessageDeniedError`.
365
383
  * Never carries the refused content — see MessageDeniedError. */
@@ -69,6 +69,21 @@ export interface OutputSchemaParser<T> {
69
69
  */
70
70
  readonly description?: string;
71
71
  }
72
+ /**
73
+ * How the schema reaches the model.
74
+ *
75
+ * • `'instruct'` (default) — the shape is described in the system prompt
76
+ * and the model is asked for JSON. Works on every provider, because it
77
+ * is only words.
78
+ * • `'tool-forced'` — the shape is presented as a synthetic tool and the
79
+ * provider's tool choice is FORCED to it, so generation is constrained
80
+ * at the source instead of requested in prose. Requires a provider that
81
+ * declares `carriesForcedToolChoice`; a provider that does not is
82
+ * refused BY NAME at run start rather than quietly downgraded, because
83
+ * a strategy that silently falls back to the other one is config that
84
+ * lies.
85
+ */
86
+ export type OutputSchemaStrategy = 'instruct' | 'tool-forced';
72
87
  /**
73
88
  * Optional configuration for `outputSchema`.
74
89
  */
@@ -88,6 +103,42 @@ export interface OutputSchemaOptions {
88
103
  * domain-specific framing.
89
104
  */
90
105
  readonly instruction?: string;
106
+ /**
107
+ * How many corrective re-asks the run may spend when the final answer
108
+ * fails the schema. Default `0` — the historical behaviour, where the
109
+ * first answer is the only answer and `runTyped()` throws on a bad one.
110
+ *
111
+ * Each retry is a REAL turn: the failed answer and an authored corrective
112
+ * message join the conversation, the ReAct loop re-enters, and the next
113
+ * attempt gets its own `llm_start`/`llm_end` bracket and its own
114
+ * `cost.tick` against `costBudget`. A retry therefore consumes one
115
+ * iteration of the agent's budget, the same way a tool call does.
116
+ *
117
+ * When the cap is spent the last answer stands and `runTyped()` throws
118
+ * `OutputSchemaError` exactly as it always has — `.outputFallback()`
119
+ * composes on top, unchanged.
120
+ */
121
+ readonly retries?: number;
122
+ /**
123
+ * How the schema reaches the model. Default `'instruct'`.
124
+ * See {@link OutputSchemaStrategy}.
125
+ */
126
+ readonly strategy?: OutputSchemaStrategy;
127
+ /**
128
+ * The JSON Schema for the synthetic tool, required by
129
+ * `strategy: 'tool-forced'` unless the parser can produce one itself
130
+ * (a `toJsonSchema()` method, which ArkType has). The library will not
131
+ * infer a shape from a `parse()` function — guessing what your schema
132
+ * means is not a thing it gets to do.
133
+ *
134
+ * This value and the parser CAN disagree. Nothing here prevents that,
135
+ * and nothing needs to: the forced shape satisfies the wire, the parser
136
+ * still judges the answer, and a disagreement surfaces as an ordinary
137
+ * validation failure that the retry loop corrects using the validator's
138
+ * own words. The schema constrains generation; the parser remains the
139
+ * judge.
140
+ */
141
+ readonly jsonSchema?: Readonly<Record<string, unknown>>;
91
142
  }
92
143
  /**
93
144
  * Thrown by `agent.parseOutput(...)` / `agent.runTyped(...)` when the
@@ -1 +1 @@
1
- {"version":3,"file":"outputSchema.js","sourceRoot":"","sources":["../../../src/core/outputSchema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AA6CH;;;;;;;GAOG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,SAAS,CAAS;IAClB,KAAK,CAAmC;IAC/B,KAAK,CAAW;IAElC,YACE,OAAe,EACf,IAAqF;QAErF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACxD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAmC;IACzE,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,sBAAsB,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,OAAO,CACL,2DAA2D;QAC3D,6DAA6D;QAC7D,IAAI,CACL,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAI,GAAW,EAAE,MAA6B;IAC7E,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CACzB,gFAAgF,EAChF,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAC/C,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CAAC,iEAAiE,EAAE;YAC7F,SAAS,EAAE,GAAG;YACd,KAAK,EAAE,iBAAiB;YACxB,KAAK;SACN,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"outputSchema.js","sourceRoot":"","sources":["../../../src/core/outputSchema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAiGH;;;;;;;GAOG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,SAAS,CAAS;IAClB,KAAK,CAAmC;IAC/B,KAAK,CAAW;IAElC,YACE,OAAe,EACf,IAAqF;QAErF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACxD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAmC;IACzE,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,sBAAsB,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,OAAO,CACL,2DAA2D;QAC3D,6DAA6D;QAC7D,IAAI,CACL,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAI,GAAW,EAAE,MAA6B;IAC7E,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CACzB,gFAAgF,EAChF,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAC/C,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CAAC,iEAAiE,EAAE;YAC7F,SAAS,EAAE,GAAG;YACd,KAAK,EAAE,iBAAiB;YACxB,KAAK;SACN,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -106,7 +106,13 @@ export interface AgentIterationEndPayload {
106
106
  export interface AgentRouteDecidedPayload {
107
107
  readonly turnIndex: number;
108
108
  readonly iterIndex: number;
109
- readonly chosen: 'tool-calls' | 'final';
109
+ /**
110
+ * The branch the turn took. `'output-retry'` (7.26) appears only on an
111
+ * agent built with `.outputSchema(parser, { retries })`, and only on a
112
+ * turn whose answer failed the schema with retries left — the loop is
113
+ * about to ask again rather than finish.
114
+ */
115
+ readonly chosen: 'tool-calls' | 'final' | 'output-retry';
110
116
  readonly rationale?: string;
111
117
  }
112
118
  export interface AgentHandoffPayload {
@@ -621,6 +627,46 @@ export interface EvalThresholdCrossedPayload {
621
627
  * Fires BEFORE PostDecide rules evaluate, so observability sees the
622
628
  * failure even if a buggy rule routes to fail-fast or swallows it.
623
629
  */
630
+ /**
631
+ * Emitted (7.26) once per failed final answer that the run is about to
632
+ * ASK AGAIN about, on an agent built with
633
+ * `.outputSchema(parser, { retries })`.
634
+ *
635
+ * Its sibling `agent.output_schema_validation_failed` reports a failure the
636
+ * reliability gate is handling INSIDE one `call-llm` stage. This one reports
637
+ * a failure the LOOP is handling: the corrective message named here joins the
638
+ * conversation, the ReAct loop re-enters, and the next attempt arrives with
639
+ * its own `stream.llm_start` / `stream.llm_end` bracket and its own
640
+ * `cost.tick`. Subscribe to it to see how often a model needs a second ask —
641
+ * a leading indicator of drift, and of a schema that is harder to hit than
642
+ * its author thinks.
643
+ *
644
+ * Fires from the retry branch, after the corrective turn is committed, so a
645
+ * consumer that reads `snapshot.sharedState.outputAttempts` finds the
646
+ * matching row (joined by `correctiveMessageHash`) already there.
647
+ */
648
+ export interface AgentOutputSchemaRetryPayload {
649
+ /** 1-based attempt that just failed. `1` is the first answer. */
650
+ readonly attempt: number;
651
+ /** Corrective asks left AFTER this one. `0` means this is the last. */
652
+ readonly retriesRemaining: number;
653
+ /** The ReAct iteration the failed answer came from. A retry consumes an
654
+ * iteration, so the next attempt reports `iteration + 1`. */
655
+ readonly iteration: number;
656
+ /** Which half of validation failed — `'json-parse'` (the model emitted
657
+ * prose) vs `'schema-validate'` (JSON, wrong shape). They trend
658
+ * differently under model drift. */
659
+ readonly stage: 'json-parse' | 'schema-validate';
660
+ /** The validator's own message, verbatim. DATA, not narrative: it is
661
+ * quoted into the corrective message after an authored frame, and it is
662
+ * quoted here the same way. */
663
+ readonly error: string;
664
+ /** Failing field path when the parser exposes one (Zod-style issues). */
665
+ readonly path?: string;
666
+ /** `fnv1a` of the corrective message that went back to the model — the
667
+ * join to the message in `history` and to the `outputAttempts` row. */
668
+ readonly correctiveMessageHash: string;
669
+ }
624
670
  export interface AgentOutputSchemaValidationFailedPayload {
625
671
  /** Validation error message (from Zod / parser). */
626
672
  readonly message: string;
@@ -16,7 +16,7 @@
16
16
  * major bump. See agentfootprint_v2_detailed_design.md for rules.
17
17
  */
18
18
  import type { AgentfootprintEventEnvelope } from './types.js';
19
- import type { AgentHandoffPayload, AgentIterationEndPayload, AgentIterationStartPayload, AgentRouteDecidedPayload, AgentTurnEndPayload, AgentTurnStartPayload, CompositionEnterPayload, CompositionExitPayload, ConditionalRouteDecidedPayload, ContextBudgetPressurePayload, ContextEvaluatedPayload, ContextEvictedPayload, ContextInjectedPayload, ContextSlotComposedPayload, CostLimitHitPayload, CostTickPayload, EmbeddingGeneratedPayload, ErrorFatalPayload, ErrorRecoveredPayload, ErrorRetriedPayload, EvalScorePayload, EvalThresholdCrossedPayload, AgentOutputSchemaValidationFailedPayload, AgentThinkingParseFailedPayload, StreamThinkingDeltaPayload, StreamThinkingEndPayload, FallbackTriggeredPayload, LLMEndPayload, LLMStartPayload, LLMTokenPayload, LoopIterationExitPayload, LoopIterationStartPayload, MemoryAttachedPayload, MemoryDetachedPayload, MemoryStrategyAppliedPayload, MemoryWrittenPayload, ParallelBranchCompletePayload, ParallelForkStartPayload, ParallelMergeEndPayload, PauseRequestPayload, PauseResumePayload, CheckInRequestPayload, CheckInDecisionPayload, PermissionCheckPayload, PermissionGateClosedPayload, PermissionHaltPayload, PermissionGateOpenedPayload, CredentialRequestedPayload, CredentialAcquiredPayload, CredentialAuthorizationRequiredPayload, CredentialFailedPayload, ReliabilityFailFastPayload, ReliabilityRetriedPayload, ReliabilityRecoveredPayload, RiskFlaggedPayload, SkillActivatedPayload, SkillDeactivatedPayload, SkillRejectedPayload, ToolEndPayload, ToolsActivatedPayload, ToolsDeactivatedPayload, ToolsDiscoveryStartedPayload, ToolsDiscoveryCompletedPayload, ToolsDiscoveryFailedPayload, ToolsOfferedPayload, ToolStartPayload, ValidationArgsInvalidPayload, MiddlewareDecisionPayload } from './payloads.js';
19
+ import type { AgentHandoffPayload, AgentIterationEndPayload, AgentIterationStartPayload, AgentRouteDecidedPayload, AgentTurnEndPayload, AgentTurnStartPayload, CompositionEnterPayload, CompositionExitPayload, ConditionalRouteDecidedPayload, ContextBudgetPressurePayload, ContextEvaluatedPayload, ContextEvictedPayload, ContextInjectedPayload, ContextSlotComposedPayload, CostLimitHitPayload, CostTickPayload, EmbeddingGeneratedPayload, ErrorFatalPayload, ErrorRecoveredPayload, ErrorRetriedPayload, EvalScorePayload, EvalThresholdCrossedPayload, AgentOutputSchemaValidationFailedPayload, AgentOutputSchemaRetryPayload, AgentThinkingParseFailedPayload, StreamThinkingDeltaPayload, StreamThinkingEndPayload, FallbackTriggeredPayload, LLMEndPayload, LLMStartPayload, LLMTokenPayload, LoopIterationExitPayload, LoopIterationStartPayload, MemoryAttachedPayload, MemoryDetachedPayload, MemoryStrategyAppliedPayload, MemoryWrittenPayload, ParallelBranchCompletePayload, ParallelForkStartPayload, ParallelMergeEndPayload, PauseRequestPayload, PauseResumePayload, CheckInRequestPayload, CheckInDecisionPayload, PermissionCheckPayload, PermissionGateClosedPayload, PermissionHaltPayload, PermissionGateOpenedPayload, CredentialRequestedPayload, CredentialAcquiredPayload, CredentialAuthorizationRequiredPayload, CredentialFailedPayload, ReliabilityFailFastPayload, ReliabilityRetriedPayload, ReliabilityRecoveredPayload, RiskFlaggedPayload, SkillActivatedPayload, SkillDeactivatedPayload, SkillRejectedPayload, ToolEndPayload, ToolsActivatedPayload, ToolsDeactivatedPayload, ToolsDiscoveryStartedPayload, ToolsDiscoveryCompletedPayload, ToolsDiscoveryFailedPayload, ToolsOfferedPayload, ToolStartPayload, ValidationArgsInvalidPayload, MiddlewareDecisionPayload } from './payloads.js';
20
20
  export declare const EVENT_NAMES: {
21
21
  readonly composition: {
22
22
  readonly enter: "agentfootprint.composition.enter";
@@ -36,6 +36,7 @@ export declare const EVENT_NAMES: {
36
36
  readonly routeDecided: "agentfootprint.agent.route_decided";
37
37
  readonly handoff: "agentfootprint.agent.handoff";
38
38
  readonly outputSchemaValidationFailed: "agentfootprint.agent.output_schema_validation_failed";
39
+ readonly outputSchemaRetry: "agentfootprint.agent.output_schema_retry";
39
40
  readonly thinkingParseFailed: "agentfootprint.agent.thinking_parse_failed";
40
41
  };
41
42
  readonly stream: {
@@ -143,6 +144,7 @@ export interface AgentfootprintEventMap {
143
144
  'agentfootprint.agent.route_decided': AgentfootprintEventEnvelope<'agentfootprint.agent.route_decided', AgentRouteDecidedPayload>;
144
145
  'agentfootprint.agent.handoff': AgentfootprintEventEnvelope<'agentfootprint.agent.handoff', AgentHandoffPayload>;
145
146
  'agentfootprint.agent.output_schema_validation_failed': AgentfootprintEventEnvelope<'agentfootprint.agent.output_schema_validation_failed', AgentOutputSchemaValidationFailedPayload>;
147
+ 'agentfootprint.agent.output_schema_retry': AgentfootprintEventEnvelope<'agentfootprint.agent.output_schema_retry', AgentOutputSchemaRetryPayload>;
146
148
  'agentfootprint.agent.thinking_parse_failed': AgentfootprintEventEnvelope<'agentfootprint.agent.thinking_parse_failed', AgentThinkingParseFailedPayload>;
147
149
  'agentfootprint.stream.llm_start': AgentfootprintEventEnvelope<'agentfootprint.stream.llm_start', LLMStartPayload>;
148
150
  'agentfootprint.stream.llm_end': AgentfootprintEventEnvelope<'agentfootprint.stream.llm_end', LLMEndPayload>;
@@ -37,6 +37,7 @@ export const EVENT_NAMES = {
37
37
  routeDecided: 'agentfootprint.agent.route_decided',
38
38
  handoff: 'agentfootprint.agent.handoff',
39
39
  outputSchemaValidationFailed: 'agentfootprint.agent.output_schema_validation_failed',
40
+ outputSchemaRetry: 'agentfootprint.agent.output_schema_retry',
40
41
  thinkingParseFailed: 'agentfootprint.agent.thinking_parse_failed',
41
42
  },
42
43
  stream: {
@@ -148,6 +149,7 @@ export const ALL_EVENT_TYPES = [
148
149
  'agentfootprint.agent.route_decided',
149
150
  'agentfootprint.agent.handoff',
150
151
  'agentfootprint.agent.output_schema_validation_failed',
152
+ 'agentfootprint.agent.output_schema_retry',
151
153
  'agentfootprint.agent.thinking_parse_failed',
152
154
  'agentfootprint.stream.llm_start',
153
155
  'agentfootprint.stream.llm_end',
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/events/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/events/registry.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@
17
17
  * `Error`: nothing branches on "I forgot to feature-detect", it just needs to
18
18
  * say so loudly and name the adapter it is talking about.
19
19
  */
20
- import type { AgentHost, HostCapability, PendingAsk } from './types.js';
20
+ import type { AgentHost, ConversationHost, HostCapability, PendingAsk } from './types.js';
21
21
  /**
22
22
  * Thrown when a request arrives at a host that is shutting down or shut down.
23
23
  *
@@ -110,6 +110,44 @@ export declare class NoPendingAskError extends Error {
110
110
  readonly sessionId: string;
111
111
  constructor(sessionId: string);
112
112
  }
113
+ /**
114
+ * Thrown when something is sent down a conversation that has already ended.
115
+ *
116
+ * A closed channel that accepts frames and drops them is the worst of the three
117
+ * options: the sender believes the far side got it, the far side never did, and
118
+ * nothing anywhere says so. Refusing by name is the only version of this that
119
+ * leaves a trace.
120
+ *
121
+ * `onClose` is how you avoid meeting this — subscribe, and stop sending.
122
+ */
123
+ export declare class ConversationClosedError extends Error {
124
+ readonly code: "ERR_CONVERSATION_CLOSED";
125
+ /** Which adapter's door this was. */
126
+ readonly hostName: string;
127
+ /** The session the conversation claimed, when it claimed one. */
128
+ readonly sessionId?: string;
129
+ constructor(hostName: string, sessionId?: string);
130
+ }
131
+ /**
132
+ * Thrown when a frame is bigger than the ceiling the adapter DECLARED.
133
+ *
134
+ * This is the other half of {@link ConversationLimits} — a declared ceiling
135
+ * nothing enforces is a number in a doc comment. The port neither chunks nor
136
+ * truncates, on purpose: how a message is split, numbered and reassembled is
137
+ * the consumer's protocol question, and answering it inside the adapter would
138
+ * answer it for every consumer at once. So the ceiling is visible, the refusal
139
+ * names it, and the splitting happens above the port where the protocol lives.
140
+ */
141
+ export declare class FrameTooLargeError extends Error {
142
+ readonly code: "ERR_FRAME_TOO_LARGE";
143
+ /** Which adapter's door refused. */
144
+ readonly hostName: string;
145
+ /** How big the frame was, in bytes of UTF-8. */
146
+ readonly bytes: number;
147
+ /** The declared ceiling it crossed. */
148
+ readonly maxFrameBytes: number;
149
+ constructor(hostName: string, bytes: number, maxFrameBytes: number);
150
+ }
113
151
  /**
114
152
  * Thrown when a store hands back something that is **present but unreadable**
115
153
  * where a `CheckpointEnvelope` should be.
@@ -161,10 +199,14 @@ export declare class UnreadableEnvelopeError extends TypeError {
161
199
  * assumed, and asking for one that is absent tells you which adapter you are
162
200
  * actually holding rather than failing quietly somewhere downstream.
163
201
  *
202
+ * Takes either port, because both declare the same two facts — who they are and
203
+ * what they can do — and a caller holding a conversation-only host is entitled
204
+ * to the same answer as one holding a request host.
205
+ *
164
206
  * @example
165
207
  * requireCapability(host, 'streaming'); // throws unless this host streams
166
208
  *
167
209
  * // or branch instead of insisting:
168
210
  * if (host.capabilities.includes('streaming')) { ... }
169
211
  */
170
- export declare function requireCapability(host: AgentHost, capability: HostCapability): void;
212
+ export declare function requireCapability(host: AgentHost | ConversationHost, capability: HostCapability): void;
@@ -168,6 +168,65 @@ export class NoPendingAskError extends Error {
168
168
  this.sessionId = sessionId;
169
169
  }
170
170
  }
171
+ /**
172
+ * Thrown when something is sent down a conversation that has already ended.
173
+ *
174
+ * A closed channel that accepts frames and drops them is the worst of the three
175
+ * options: the sender believes the far side got it, the far side never did, and
176
+ * nothing anywhere says so. Refusing by name is the only version of this that
177
+ * leaves a trace.
178
+ *
179
+ * `onClose` is how you avoid meeting this — subscribe, and stop sending.
180
+ */
181
+ export class ConversationClosedError extends Error {
182
+ code = 'ERR_CONVERSATION_CLOSED';
183
+ /** Which adapter's door this was. */
184
+ hostName;
185
+ /** The session the conversation claimed, when it claimed one. */
186
+ sessionId;
187
+ constructor(hostName, sessionId) {
188
+ super(`[hosting] this conversation on the '${hostName}' host has ended` +
189
+ (sessionId !== undefined ? ` (session '${sessionId}')` : '') +
190
+ `, so there is nowhere for that frame to go. Refusing rather than accepting it ` +
191
+ `and dropping it — a send that silently goes nowhere looks identical to a send ` +
192
+ `that worked. Subscribe with onClose(...) and stop sending when it fires, or open ` +
193
+ `a new conversation.`);
194
+ this.name = 'ConversationClosedError';
195
+ this.hostName = hostName;
196
+ if (sessionId !== undefined)
197
+ this.sessionId = sessionId;
198
+ }
199
+ }
200
+ /**
201
+ * Thrown when a frame is bigger than the ceiling the adapter DECLARED.
202
+ *
203
+ * This is the other half of {@link ConversationLimits} — a declared ceiling
204
+ * nothing enforces is a number in a doc comment. The port neither chunks nor
205
+ * truncates, on purpose: how a message is split, numbered and reassembled is
206
+ * the consumer's protocol question, and answering it inside the adapter would
207
+ * answer it for every consumer at once. So the ceiling is visible, the refusal
208
+ * names it, and the splitting happens above the port where the protocol lives.
209
+ */
210
+ export class FrameTooLargeError extends Error {
211
+ code = 'ERR_FRAME_TOO_LARGE';
212
+ /** Which adapter's door refused. */
213
+ hostName;
214
+ /** How big the frame was, in bytes of UTF-8. */
215
+ bytes;
216
+ /** The declared ceiling it crossed. */
217
+ maxFrameBytes;
218
+ constructor(hostName, bytes, maxFrameBytes) {
219
+ super(`[hosting] this frame is ${bytes} bytes and the '${hostName}' host declares a ` +
220
+ `maxFrameBytes of ${maxFrameBytes}. Refusing rather than truncating it or splitting ` +
221
+ `it for you: how a message is chunked, numbered and put back together is your ` +
222
+ `protocol's question, and an adapter that answered it would answer it for every ` +
223
+ `consumer at once. Read host.conversationLimits and chunk above the port.`);
224
+ this.name = 'FrameTooLargeError';
225
+ this.hostName = hostName;
226
+ this.bytes = bytes;
227
+ this.maxFrameBytes = maxFrameBytes;
228
+ }
229
+ }
171
230
  /**
172
231
  * An already-computed preview, so {@link UnreadableEnvelopeError.withSession}
173
232
  * can copy a refusal without being handed the stored bytes a second time. Not
@@ -255,6 +314,10 @@ export class UnreadableEnvelopeError extends TypeError {
255
314
  * assumed, and asking for one that is absent tells you which adapter you are
256
315
  * actually holding rather than failing quietly somewhere downstream.
257
316
  *
317
+ * Takes either port, because both declare the same two facts — who they are and
318
+ * what they can do — and a caller holding a conversation-only host is entitled
319
+ * to the same answer as one holding a request host.
320
+ *
258
321
  * @example
259
322
  * requireCapability(host, 'streaming'); // throws unless this host streams
260
323
  *
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/hosting/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/hosting/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * hosting/headers — one lower-casing of one header bag, shared by every door.
3
+ *
4
+ * A six-line helper gets its own file for the reason every other shared piece
5
+ * in this folder does: two copies of it is how the request door and the
6
+ * conversation door end up disagreeing about whether a header the caller sent
7
+ * as `X-Session-Id` is present, and that disagreement would surface as one door
8
+ * seeing a session the other cannot.
9
+ */
10
+ /// <reference types="node" />
11
+ import type { IncomingMessage } from 'node:http';
12
+ /**
13
+ * Header names lower-cased, repeated values joined — the shape every wire reads
14
+ * from, so no wire ever has to guess at casing.
15
+ */
16
+ export declare function lowerCasedHeaders(headers: IncomingMessage['headers']): Record<string, string>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * hosting/headers — one lower-casing of one header bag, shared by every door.
3
+ *
4
+ * A six-line helper gets its own file for the reason every other shared piece
5
+ * in this folder does: two copies of it is how the request door and the
6
+ * conversation door end up disagreeing about whether a header the caller sent
7
+ * as `X-Session-Id` is present, and that disagreement would surface as one door
8
+ * seeing a session the other cannot.
9
+ */
10
+ /**
11
+ * Header names lower-cased, repeated values joined — the shape every wire reads
12
+ * from, so no wire ever has to guess at casing.
13
+ */
14
+ export function lowerCasedHeaders(headers) {
15
+ const out = {};
16
+ for (const [name, value] of Object.entries(headers)) {
17
+ if (typeof value === 'string')
18
+ out[name.toLowerCase()] = value;
19
+ else if (Array.isArray(value))
20
+ out[name.toLowerCase()] = value.join(', ');
21
+ }
22
+ return out;
23
+ }
24
+ //# sourceMappingURL=headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../src/hosting/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAmC;IACnE,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC;aAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -34,12 +34,28 @@
34
34
  * detaches and drains without closing a socket it never opened. That is the
35
35
  * whole difference; every other law on this page is the same either way.
36
36
  *
37
+ * ── The third door: a conversation ───────────────────────────────────────────
38
+ * `serveConversations(handler)` sits beside `serve(handler)` and takes upgrades
39
+ * on `conversationPath`, because `HostRequest → HostReply` is one exchange and
40
+ * some doors are not. Give a host a `conversationPath` and it declares
41
+ * `'conversation'`; leave it out and `serveConversations` refuses by name.
42
+ *
43
+ * **Both doors share ONE socket.** That is not an optimisation, it is the
44
+ * premise: the runtimes that need a conversation are the ones that hand a
45
+ * container exactly one port, so a host whose two doors each bound their own
46
+ * would fail with `EADDRINUSE` on the deployment it exists for. On a private
47
+ * socket the server is created by whichever door opens first and closed by
48
+ * whichever closes last; on a caller-owned one each door attaches and detaches
49
+ * its own listener and neither touches the socket.
50
+ *
37
51
  * Pattern: Template method via configuration (Strategy on the wire format).
38
52
  * Everything HTTP lives here and in the wires; `types.ts` knows none of it.
39
53
  */
40
54
  /// <reference types="node" />
41
55
  import type { Server } from 'node:http';
42
- import type { AgentHost, HostCapability, HostHandle, HostHandler, PendingAsk } from './types.js';
56
+ import type { AgentHost, ConversationHandler, ConversationHost, ConversationLimits, HostCapability, HostHandle, HostHandler, PendingAsk } from './types.js';
57
+ import { type ConversationHandshake, type HandshakeFacts } from './webSocketConversation.js';
58
+ export type { ConversationHandshake, HandshakeFacts };
43
59
  /** Everything a {@link HttpWire} may read when pulling a request apart. */
44
60
  export interface HttpRequestFacts {
45
61
  /** The parsed JSON body, or `{}` for an empty one. */
@@ -93,6 +109,17 @@ export interface HttpWire {
93
109
  * either way.
94
110
  */
95
111
  awaiting?(pending: PendingAsk): unknown;
112
+ /**
113
+ * Pull the port's vocabulary out of one conversation handshake — the session
114
+ * this conversation claims, any header mapping this dialect performs, and the
115
+ * subprotocol to echo.
116
+ *
117
+ * Optional, and absent means "raw headers, no session": there is no body in a
118
+ * handshake, so a dialect that wants a session id has to name where it looks,
119
+ * and guessing on its behalf would invent an affinity rule the deployment
120
+ * never agreed to.
121
+ */
122
+ readConversation?(facts: HandshakeFacts): ConversationHandshake;
96
123
  }
97
124
  /** Options for {@link httpHost}. */
98
125
  export interface HttpHostOptions {
@@ -161,6 +188,31 @@ export interface HttpHostOptions {
161
188
  * await handle.close();
162
189
  */
163
190
  readonly server?: Server;
191
+ /**
192
+ * Path that takes a conversation upgrade.
193
+ *
194
+ * **No default, for exactly the reason `invokePath` has none** — a default
195
+ * here is inherited by every adapter built on this file, and one that
196
+ * silently matched somebody's runtime contract is that runtime leaking into a
197
+ * library that promises not to know about one.
198
+ *
199
+ * ABSENT is meaningful: the host does not declare `'conversation'` and
200
+ * {@link HttpHost.serveConversations} refuses by name. Present, and the host
201
+ * can carry conversations whether or not anybody serves them.
202
+ */
203
+ readonly conversationPath?: string;
204
+ /**
205
+ * What the conversation door caps. Whatever is left out is filled with this
206
+ * file's defaults and then DECLARED, so `conversationLimits` on the host is
207
+ * always what is actually enforced rather than what was passed in.
208
+ *
209
+ * An unset `maxFrameBytes` would mean an unbounded buffer somebody else
210
+ * fills, which is a way to kill this process; an unset `maxPendingBytes` the
211
+ * same, one layer up. `idleMs` has no default because this door does not idle
212
+ * anything out — it reports the ceiling of whatever sits in front of it, and
213
+ * inventing one would be reporting a fact nobody established.
214
+ */
215
+ readonly conversationLimits?: ConversationLimits;
164
216
  }
165
217
  /** A {@link HostHandle} that also says where it landed. */
166
218
  export interface HttpHostHandle extends HostHandle {
@@ -174,9 +226,18 @@ export interface HttpHostHandle extends HostHandle {
174
226
  /** The port it actually bound — the real one, when you asked for `0`. */
175
227
  readonly port: number;
176
228
  }
177
- /** {@link AgentHost} narrowed to an HTTP handle. */
178
- export interface HttpHost extends AgentHost {
229
+ /**
230
+ * {@link AgentHost} and {@link ConversationHost} narrowed to an HTTP handle.
231
+ *
232
+ * One object with two doors, because they share one socket. Whether the
233
+ * conversation door is USABLE is `capabilities`' answer, not this type's: a
234
+ * host built without a `conversationPath` still has the method and refuses by
235
+ * name, which is a better error than a method that is missing at runtime on
236
+ * some adapters and present on others.
237
+ */
238
+ export interface HttpHost extends AgentHost, ConversationHost {
179
239
  serve(handler: HostHandler): Promise<HttpHostHandle>;
240
+ serveConversations(handler: ConversationHandler): Promise<HttpHostHandle>;
180
241
  }
181
242
  /**
182
243
  * An HTTP host for one handler, speaking the dialect you hand it.
@@ -192,5 +253,10 @@ export declare function httpHost(options: HttpHostOptions): HttpHost;
192
253
  * Exported because every wire that maps a header needs it and re-deriving it
193
254
  * per adapter is how one of them ends up matching only the exact casing the
194
255
  * author happened to test with.
256
+ *
257
+ * Takes anything carrying lower-cased headers, so a request wire and a
258
+ * handshake wire read a header the same way rather than each growing their own.
195
259
  */
196
- export declare function headerValue(facts: HttpRequestFacts, name: string, ...fallbacks: string[]): string | undefined;
260
+ export declare function headerValue(facts: {
261
+ readonly headers: Readonly<Record<string, string>>;
262
+ }, name: string, ...fallbacks: string[]): string | undefined;