@yanlinglabs/winter-agent-runtime 0.0.27

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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +41 -0
  3. package/README.md +64 -0
  4. package/dist/checkpoint/file-history.d.ts +81 -0
  5. package/dist/checkpoint/rewind.d.ts +55 -0
  6. package/dist/checkpoint/seam.d.ts +47 -0
  7. package/dist/checkpoint/sink.d.ts +66 -0
  8. package/dist/commands/builtins-listing.d.ts +40 -0
  9. package/dist/commands/resolver.d.ts +103 -0
  10. package/dist/commands/seam.d.ts +53 -0
  11. package/dist/compaction/controller.d.ts +23 -0
  12. package/dist/compaction/retention.d.ts +35 -0
  13. package/dist/compaction/seam.d.ts +115 -0
  14. package/dist/compaction/summarizer.d.ts +79 -0
  15. package/dist/context/agent-listing.d.ts +39 -0
  16. package/dist/context/assembler.d.ts +46 -0
  17. package/dist/context/attachments.d.ts +104 -0
  18. package/dist/context/dynamic-sections.d.ts +31 -0
  19. package/dist/context/git-fixture.d.ts +18 -0
  20. package/dist/context/git-status.d.ts +16 -0
  21. package/dist/context/imports.d.ts +22 -0
  22. package/dist/context/injection.d.ts +53 -0
  23. package/dist/context/memory-key.d.ts +46 -0
  24. package/dist/context/memory.d.ts +28 -0
  25. package/dist/context/minimal-prompt.d.ts +5 -0
  26. package/dist/context/output-styles.d.ts +68 -0
  27. package/dist/context/plan-mode.d.ts +29 -0
  28. package/dist/context/request-layout.d.ts +138 -0
  29. package/dist/context/rules.d.ts +63 -0
  30. package/dist/context/seam.d.ts +136 -0
  31. package/dist/context/tool-epoch.d.ts +118 -0
  32. package/dist/context/winter-code-preset.d.ts +39 -0
  33. package/dist/context/winter-md.d.ts +81 -0
  34. package/dist/embedded-host.d.ts +48 -0
  35. package/dist/embedded-host.js +155 -0
  36. package/dist/embedded-protocol.d.ts +44 -0
  37. package/dist/embedded-worker.d.ts +1 -0
  38. package/dist/embedded-worker.js +74 -0
  39. package/dist/embedded.d.ts +34 -0
  40. package/dist/embedded.js +9 -0
  41. package/dist/engine.d.ts +1298 -0
  42. package/dist/hooks/additional-context.d.ts +21 -0
  43. package/dist/hooks/bounds.d.ts +6 -0
  44. package/dist/hooks/bridge-invoker.d.ts +3 -0
  45. package/dist/hooks/command-invoker.d.ts +52 -0
  46. package/dist/hooks/from-config.d.ts +31 -0
  47. package/dist/hooks/hook-stage.d.ts +25 -0
  48. package/dist/hooks/input-validator.d.ts +6 -0
  49. package/dist/hooks/reducer.d.ts +74 -0
  50. package/dist/hooks/registry.d.ts +33 -0
  51. package/dist/hooks/runner.d.ts +105 -0
  52. package/dist/index-584yahed.js +6037 -0
  53. package/dist/index-97t2rmtf.js +42 -0
  54. package/dist/index-9qgkpv56.js +27183 -0
  55. package/dist/index-bef62z3r.js +437 -0
  56. package/dist/index-rkhh0457.js +187 -0
  57. package/dist/index.d.ts +37 -0
  58. package/dist/index.js +353 -0
  59. package/dist/main.d.ts +1 -0
  60. package/dist/mcp/client.d.ts +105 -0
  61. package/dist/mcp/control-seam.d.ts +25 -0
  62. package/dist/mcp/control.d.ts +5 -0
  63. package/dist/mcp/elicitation.d.ts +35 -0
  64. package/dist/mcp/env.d.ts +12 -0
  65. package/dist/mcp/lifecycle.d.ts +142 -0
  66. package/dist/mcp/output-cap.d.ts +15 -0
  67. package/dist/mcp/state.d.ts +24 -0
  68. package/dist/mcp/test-fixtures.d.ts +88 -0
  69. package/dist/mcp/transports/__fixtures__/stdio-server.d.ts +1 -0
  70. package/dist/mcp/transports/http.d.ts +5 -0
  71. package/dist/mcp/transports/sdk.d.ts +5 -0
  72. package/dist/mcp/transports/sse.d.ts +3 -0
  73. package/dist/mcp/transports/stdio.d.ts +35 -0
  74. package/dist/mcp/winter-server.d.ts +2 -0
  75. package/dist/messaging/reference-adapter.d.ts +88 -0
  76. package/dist/messaging/router.d.ts +8 -0
  77. package/dist/paths/project-dir-name.d.ts +2 -0
  78. package/dist/paths/temp.d.ts +25 -0
  79. package/dist/permissions/approvals.d.ts +107 -0
  80. package/dist/permissions/auto/caches.d.ts +53 -0
  81. package/dist/permissions/auto/config.d.ts +37 -0
  82. package/dist/permissions/auto/engine.d.ts +74 -0
  83. package/dist/permissions/auto/envelope.d.ts +45 -0
  84. package/dist/permissions/auto/inheritance.d.ts +27 -0
  85. package/dist/permissions/edit-recognition.d.ts +30 -0
  86. package/dist/permissions/evaluator.d.ts +284 -0
  87. package/dist/permissions/file-rules.d.ts +384 -0
  88. package/dist/permissions/grammar.d.ts +113 -0
  89. package/dist/permissions/paths.d.ts +32 -0
  90. package/dist/permissions/policy-state.d.ts +64 -0
  91. package/dist/permissions/prompt-stage.d.ts +3 -0
  92. package/dist/permissions/protected.d.ts +54 -0
  93. package/dist/permissions/ruleset.d.ts +134 -0
  94. package/dist/permissions/shell-structure.d.ts +41 -0
  95. package/dist/plugins/bundle.d.ts +100 -0
  96. package/dist/plugins/installed.d.ts +30 -0
  97. package/dist/plugins/loader.d.ts +56 -0
  98. package/dist/plugins/manifest.d.ts +115 -0
  99. package/dist/production-wiring.d.ts +340 -0
  100. package/dist/protocol/channel.d.ts +22 -0
  101. package/dist/provider/advisor-route.d.ts +47 -0
  102. package/dist/provider/bridge.d.ts +124 -0
  103. package/dist/provider/classifier/model-classifier.d.ts +82 -0
  104. package/dist/provider/classifier/prompt.d.ts +62 -0
  105. package/dist/provider/classifier/verdict-schema.d.ts +83 -0
  106. package/dist/provider/credential-api.d.ts +160 -0
  107. package/dist/provider/family-listing.d.ts +27 -0
  108. package/dist/provider/first-party.d.ts +4 -0
  109. package/dist/provider/keychain-store.d.ts +59 -0
  110. package/dist/provider/lean-prompt.d.ts +7 -0
  111. package/dist/provider/mock.d.ts +55 -0
  112. package/dist/provider/scenario-fake.d.ts +96 -0
  113. package/dist/provider/selection.d.ts +115 -0
  114. package/dist/provider/session-provider.d.ts +426 -0
  115. package/dist/provider/slots.d.ts +120 -0
  116. package/dist/provider/stream-frames.d.ts +25 -0
  117. package/dist/provider/tool-secret.d.ts +57 -0
  118. package/dist/rpc/bridge.d.ts +14 -0
  119. package/dist/rpc/mcp-control.d.ts +26 -0
  120. package/dist/runtime.d.ts +14 -0
  121. package/dist/sandbox/profile.d.ts +249 -0
  122. package/dist/sandbox/spawn.d.ts +139 -0
  123. package/dist/settings/env-filter.d.ts +52 -0
  124. package/dist/settings/loaders/hooks.d.ts +44 -0
  125. package/dist/settings/loaders/mcp-config.d.ts +83 -0
  126. package/dist/settings/loaders/plugin-mcp.d.ts +3 -0
  127. package/dist/settings/loaders/strict-plugin-only.d.ts +13 -0
  128. package/dist/settings/resolve.d.ts +2 -0
  129. package/dist/settings/sources.d.ts +2 -0
  130. package/dist/settings/trust.d.ts +36 -0
  131. package/dist/skills/attachment.d.ts +25 -0
  132. package/dist/skills/frontmatter.d.ts +64 -0
  133. package/dist/skills/index.d.ts +16 -0
  134. package/dist/skills/listing.d.ts +89 -0
  135. package/dist/skills/loader.d.ts +104 -0
  136. package/dist/skills/option.d.ts +68 -0
  137. package/dist/skills/permission-rules.d.ts +21 -0
  138. package/dist/skills/runtime.d.ts +21 -0
  139. package/dist/skills/store.d.ts +163 -0
  140. package/dist/store/continuation-attach.d.ts +44 -0
  141. package/dist/store/dialect.d.ts +526 -0
  142. package/dist/store/provider-state.d.ts +188 -0
  143. package/dist/store/resume.d.ts +92 -0
  144. package/dist/structured/ajv-seam.d.ts +7 -0
  145. package/dist/structured/descriptor.d.ts +9 -0
  146. package/dist/structured/seam.d.ts +51 -0
  147. package/dist/structured/validator.d.ts +22 -0
  148. package/dist/subagents/activity.d.ts +13 -0
  149. package/dist/subagents/availability.d.ts +30 -0
  150. package/dist/subagents/builtin-agents.d.ts +37 -0
  151. package/dist/subagents/child-engine.d.ts +198 -0
  152. package/dist/subagents/child-handle.d.ts +344 -0
  153. package/dist/subagents/definitions.d.ts +189 -0
  154. package/dist/subagents/fork.d.ts +55 -0
  155. package/dist/subagents/git-root.d.ts +1 -0
  156. package/dist/subagents/limits.d.ts +28 -0
  157. package/dist/subagents/notification-queue.d.ts +233 -0
  158. package/dist/subagents/plugin-agents.d.ts +5 -0
  159. package/dist/subagents/policy.d.ts +46 -0
  160. package/dist/subagents/register-default-factory.d.ts +66 -0
  161. package/dist/subagents/resolution.d.ts +56 -0
  162. package/dist/subagents/restore.d.ts +9 -0
  163. package/dist/subagents/roster.d.ts +17 -0
  164. package/dist/subagents/test-fakes.d.ts +12 -0
  165. package/dist/subagents/tool-pools.d.ts +69 -0
  166. package/dist/subagents/watchdog.d.ts +13 -0
  167. package/dist/subagents/workspace.d.ts +27 -0
  168. package/dist/testing.d.ts +5 -0
  169. package/dist/testing.js +194 -0
  170. package/dist/tools/background-tasks.d.ts +10 -0
  171. package/dist/tools/descriptors/_shared.d.ts +34 -0
  172. package/dist/tools/descriptors/advisor.d.ts +1 -0
  173. package/dist/tools/descriptors/agent.d.ts +47 -0
  174. package/dist/tools/descriptors/artifact.d.ts +1 -0
  175. package/dist/tools/descriptors/ask-user-question.d.ts +1 -0
  176. package/dist/tools/descriptors/bash.d.ts +20 -0
  177. package/dist/tools/descriptors/claude-design.d.ts +1 -0
  178. package/dist/tools/descriptors/cron-create.d.ts +1 -0
  179. package/dist/tools/descriptors/cron-delete.d.ts +1 -0
  180. package/dist/tools/descriptors/cron-list.d.ts +1 -0
  181. package/dist/tools/descriptors/edit.d.ts +1 -0
  182. package/dist/tools/descriptors/end-conversation.d.ts +1 -0
  183. package/dist/tools/descriptors/enter-plan-mode.d.ts +1 -0
  184. package/dist/tools/descriptors/enter-worktree.d.ts +1 -0
  185. package/dist/tools/descriptors/exit-plan-mode.d.ts +1 -0
  186. package/dist/tools/descriptors/exit-worktree.d.ts +1 -0
  187. package/dist/tools/descriptors/glob.d.ts +1 -0
  188. package/dist/tools/descriptors/grep.d.ts +1 -0
  189. package/dist/tools/descriptors/index.d.ts +59 -0
  190. package/dist/tools/descriptors/list-agents.d.ts +1 -0
  191. package/dist/tools/descriptors/list-mcp-resources-tool.d.ts +1 -0
  192. package/dist/tools/descriptors/lsp.d.ts +1 -0
  193. package/dist/tools/descriptors/monitor.d.ts +1 -0
  194. package/dist/tools/descriptors/notebook-edit.d.ts +1 -0
  195. package/dist/tools/descriptors/powershell.d.ts +1 -0
  196. package/dist/tools/descriptors/projects.d.ts +1 -0
  197. package/dist/tools/descriptors/propose-goal.d.ts +1 -0
  198. package/dist/tools/descriptors/propose-skills.d.ts +1 -0
  199. package/dist/tools/descriptors/push-notification.d.ts +1 -0
  200. package/dist/tools/descriptors/read-mcp-resource-dir-tool.d.ts +1 -0
  201. package/dist/tools/descriptors/read-mcp-resource-tool.d.ts +1 -0
  202. package/dist/tools/descriptors/read-notifications.d.ts +1 -0
  203. package/dist/tools/descriptors/read.d.ts +1 -0
  204. package/dist/tools/descriptors/refresh-mcp-tools.d.ts +1 -0
  205. package/dist/tools/descriptors/remote-trigger.d.ts +1 -0
  206. package/dist/tools/descriptors/repl.d.ts +1 -0
  207. package/dist/tools/descriptors/report-findings.d.ts +1 -0
  208. package/dist/tools/descriptors/schedule-wakeup.d.ts +1 -0
  209. package/dist/tools/descriptors/send-feedback.d.ts +1 -0
  210. package/dist/tools/descriptors/send-message.d.ts +1 -0
  211. package/dist/tools/descriptors/send-user-file.d.ts +1 -0
  212. package/dist/tools/descriptors/share-onboarding-guide.d.ts +1 -0
  213. package/dist/tools/descriptors/show-onboarding-role-picker.d.ts +1 -0
  214. package/dist/tools/descriptors/skill.d.ts +1 -0
  215. package/dist/tools/descriptors/structured-output.d.ts +1 -0
  216. package/dist/tools/descriptors/task-create.d.ts +1 -0
  217. package/dist/tools/descriptors/task-get.d.ts +1 -0
  218. package/dist/tools/descriptors/task-list.d.ts +1 -0
  219. package/dist/tools/descriptors/task-output.d.ts +1 -0
  220. package/dist/tools/descriptors/task-stop.d.ts +1 -0
  221. package/dist/tools/descriptors/task-update.d.ts +1 -0
  222. package/dist/tools/descriptors/todo-write.d.ts +1 -0
  223. package/dist/tools/descriptors/tool-search.d.ts +1 -0
  224. package/dist/tools/descriptors/wait-for-mcp-servers.d.ts +1 -0
  225. package/dist/tools/descriptors/web-fetch.d.ts +8 -0
  226. package/dist/tools/descriptors/web-search.d.ts +15 -0
  227. package/dist/tools/descriptors/winter-list-agents.d.ts +1 -0
  228. package/dist/tools/descriptors/winter-send-message.d.ts +1 -0
  229. package/dist/tools/descriptors/workflow.d.ts +1 -0
  230. package/dist/tools/descriptors/write.d.ts +1 -0
  231. package/dist/tools/impl/_caller.d.ts +14 -0
  232. package/dist/tools/impl/_domains.d.ts +25 -0
  233. package/dist/tools/impl/_exa-client.d.ts +122 -0
  234. package/dist/tools/impl/_exa-session-client.d.ts +23 -0
  235. package/dist/tools/impl/_inner-model.d.ts +135 -0
  236. package/dist/tools/impl/_search-budget.d.ts +36 -0
  237. package/dist/tools/impl/_web-fetch-cache.d.ts +37 -0
  238. package/dist/tools/impl/_web-fetch-html.d.ts +26 -0
  239. package/dist/tools/impl/_web-fetch-net.d.ts +99 -0
  240. package/dist/tools/impl/_web-search-assembler.d.ts +57 -0
  241. package/dist/tools/impl/advisor.d.ts +37 -0
  242. package/dist/tools/impl/agent.d.ts +10 -0
  243. package/dist/tools/impl/ask-user-question.d.ts +5 -0
  244. package/dist/tools/impl/background-task-runtime.d.ts +272 -0
  245. package/dist/tools/impl/bash.d.ts +78 -0
  246. package/dist/tools/impl/cron.d.ts +11 -0
  247. package/dist/tools/impl/edit.d.ts +1 -0
  248. package/dist/tools/impl/enter-plan-mode.d.ts +4 -0
  249. package/dist/tools/impl/enter-worktree.d.ts +25 -0
  250. package/dist/tools/impl/exit-plan-mode.d.ts +4 -0
  251. package/dist/tools/impl/exit-worktree.d.ts +4 -0
  252. package/dist/tools/impl/glob.d.ts +1 -0
  253. package/dist/tools/impl/grep.d.ts +19 -0
  254. package/dist/tools/impl/index.d.ts +37 -0
  255. package/dist/tools/impl/list-agents.d.ts +7 -0
  256. package/dist/tools/impl/list-mcp-resources-tool.d.ts +9 -0
  257. package/dist/tools/impl/monitor.d.ts +66 -0
  258. package/dist/tools/impl/notebook-edit.d.ts +1 -0
  259. package/dist/tools/impl/push-notification.d.ts +4 -0
  260. package/dist/tools/impl/read-ladder.d.ts +25 -0
  261. package/dist/tools/impl/read-mcp-resource-dir-tool.d.ts +9 -0
  262. package/dist/tools/impl/read-mcp-resource-tool.d.ts +9 -0
  263. package/dist/tools/impl/read-notifications.d.ts +5 -0
  264. package/dist/tools/impl/read.d.ts +44 -0
  265. package/dist/tools/impl/refresh-mcp-tools.d.ts +8 -0
  266. package/dist/tools/impl/report-findings.d.ts +1 -0
  267. package/dist/tools/impl/schedule-wakeup.d.ts +2 -0
  268. package/dist/tools/impl/send-message.d.ts +7 -0
  269. package/dist/tools/impl/skill.d.ts +5 -0
  270. package/dist/tools/impl/task-graph.d.ts +1 -0
  271. package/dist/tools/impl/task-output.d.ts +16 -0
  272. package/dist/tools/impl/task-stop.d.ts +11 -0
  273. package/dist/tools/impl/todo-write.d.ts +8 -0
  274. package/dist/tools/impl/tool-search.d.ts +4 -0
  275. package/dist/tools/impl/wait-for-mcp-servers.d.ts +29 -0
  276. package/dist/tools/impl/web-fetch.d.ts +36 -0
  277. package/dist/tools/impl/web-search.d.ts +30 -0
  278. package/dist/tools/impl/workflow.d.ts +5 -0
  279. package/dist/tools/impl/write.d.ts +8 -0
  280. package/dist/tools/paths-seam.d.ts +6 -0
  281. package/dist/tools/read-state.d.ts +12 -0
  282. package/dist/tools/registry.d.ts +423 -0
  283. package/dist/tools/task-graph-store.d.ts +61 -0
  284. package/dist/toolsearch/aliases.d.ts +26 -0
  285. package/dist/toolsearch/exposure.d.ts +30 -0
  286. package/dist/toolsearch/ranking.d.ts +6 -0
  287. package/dist/toolsearch/search.d.ts +45 -0
  288. package/dist/version.d.ts +1 -0
  289. package/dist/version.js +5 -0
  290. package/dist/web/fetchable-url.d.ts +28 -0
  291. package/dist/web/preapproved-hosts.d.ts +52 -0
  292. package/dist/web/private-address.d.ts +55 -0
  293. package/dist/web/session-runtime.d.ts +86 -0
  294. package/dist/workflows/bridge.d.ts +87 -0
  295. package/dist/workflows/budget.d.ts +24 -0
  296. package/dist/workflows/host-registry.d.ts +142 -0
  297. package/dist/workflows/journal.d.ts +29 -0
  298. package/dist/workflows/meta.d.ts +45 -0
  299. package/dist/workflows/registry.d.ts +24 -0
  300. package/dist/workflows/runtime.d.ts +254 -0
  301. package/dist/workflows/sandbox.d.ts +49 -0
  302. package/dist/workflows/script-api.d.ts +58 -0
  303. package/dist/workflows/seam.d.ts +92 -0
  304. package/dist/workflows/semaphore.d.ts +16 -0
  305. package/dist/workflows/store.d.ts +177 -0
  306. package/dist/workflows/subprocess-entry.d.ts +38 -0
  307. package/dist/workflows/subprocess-entry.js +14 -0
  308. package/dist/workflows/transcript.d.ts +56 -0
  309. package/dist/workflows/types.d.ts +84 -0
  310. package/dist/workflows/worker-harness.d.ts +45 -0
  311. package/package.json +76 -0
@@ -0,0 +1,115 @@
1
+ import type { WinterCatalog } from "@yanlinglabs/winter-provider-catalog";
2
+ import type { CredentialStore, ProviderContext, ProviderRegistry, ResolvedModel } from "@yanlinglabs/winter-provider-runtime";
3
+ import { type CredentialRef, type RuntimeConfig } from "@yanlinglabs/winter-agent-sdk";
4
+ import type { Provider } from "../engine.js";
5
+ /**
6
+ * The reserved namespace that reaches the in-process scripted double (R6-13).
7
+ *
8
+ * A NAMESPACE rather than an env var, and the ruling is worth restating because it inverts a P1
9
+ * carry: "remove `WINTER_TEST_PROVIDER` affordances" is NOT taken as written, because `main.ts` also
10
+ * uses that name to register in-process test TOOLS in the spawned runtime -- something no loopback
11
+ * server can do. So production selection is catalog-first, the double is reachable only through this
12
+ * namespace, and the env var survives ONLY as the harness's alias for it.
13
+ */
14
+ export declare const WINTER_TEST_NAMESPACE = "winter-test";
15
+ /** R6-9: the resolved identity that rides `system/init`'s Winter-only `winter_provider` extension and the dialect record. */
16
+ export interface WinterProviderIdentity {
17
+ providerId: string;
18
+ modelKey: string;
19
+ adapterId: string;
20
+ adapterVersion: string;
21
+ catalogVersion: string;
22
+ continuationDomain?: string;
23
+ authRefKind: CredentialRef["kind"];
24
+ }
25
+ /** What a session gets back. The `testProvider` arm is the reserved namespace's -- a scripted double has no catalog identity to report, and pretending otherwise would put a fake row in the init frame. */
26
+ export type SessionProviderSelection = {
27
+ provider: Provider;
28
+ identity: WinterProviderIdentity;
29
+ resolved: ResolvedModel;
30
+ contextWindow?: number;
31
+ supportsToolSearch: boolean;
32
+ familyMetadata: {
33
+ taskNative?: boolean;
34
+ };
35
+ /** R6-9: the fallback candidates, already domain-checked. Empty when none was configured. */
36
+ fallbackModels: ResolvedModel[];
37
+ } | {
38
+ testProvider: Provider;
39
+ };
40
+ export interface SelectionDeps {
41
+ registry: ProviderRegistry;
42
+ credentials: CredentialStore;
43
+ env: Record<string, string | undefined>;
44
+ /** R6-13: the in-process scripted double, resolved by name. Absent -> a `winter-test/<name>` model is a typed refusal rather than a silent miss. */
45
+ testProviders?: (name: string) => Provider | undefined;
46
+ /** How a resolved model becomes a `Provider`. Injected so this module never imports the bridge's own construction path in a test. */
47
+ buildProvider?: (resolved: ResolvedModel) => Provider;
48
+ /**
49
+ * WS-13b R6b-7: the resolved `settings.providers` map, as a GETTER.
50
+ *
51
+ * A getter and not a value, and that is the whole hot-reload seam. WS-11 §5's "no setting may
52
+ * require a restart" is a product rule above the SDK boundary -- this package starts no watchers
53
+ * (production-wiring's own header says so) -- so what it owes instead is a read that happens AT
54
+ * RESOLUTION TIME rather than a snapshot taken when the deps object was built. A host that
55
+ * re-resolves its settings sees the new value at the session's next resolution and at every
56
+ * `set_model`, with nothing rebuilt.
57
+ *
58
+ * Absent, or an id absent from the map, means ENABLED. Silence is never a disablement.
59
+ */
60
+ providerSettings?: () => Record<string, {
61
+ enabled: boolean;
62
+ }> | undefined;
63
+ }
64
+ /**
65
+ * Resolves the session's provider and model.
66
+ *
67
+ * Order, and each step exists because the one before it cannot answer:
68
+ * 1. the reserved `winter-test/<name>` namespace -- checked FIRST so a test double can never be
69
+ * shadowed by a catalog row, and so the check is independent of every credential question;
70
+ * 2. a QUALIFIED `<providerId>/<model>` key -> the catalog, verbatim;
71
+ * 3. a pinned Anthropic ALIAS -> the `anthropic` provider, but only with a credential ref for it;
72
+ * 4. a BARE id -> `config.provider.providerId`;
73
+ * 5. no model and no provider -> a typed refusal.
74
+ */
75
+ export declare function resolveSessionProvider(config: RuntimeConfig, deps: SelectionDeps): SessionProviderSelection;
76
+ /**
77
+ * Redacts a `CredentialRef` for a frame, a log line or an error message.
78
+ *
79
+ * `inline` is the case this exists for: R6-10 makes it a HOST responsibility that the SDK never
80
+ * persists, and its value is a live secret sitting in the session's own config -- so anything that
81
+ * renders a ref renders it through here. The others carry only locators, and those are reproduced
82
+ * because a locator is what makes a credential problem diagnosable.
83
+ */
84
+ export declare function redactCredentialRef(ref: CredentialRef): string;
85
+ /**
86
+ * R6-6: how the session's stall timeout reaches an adapter.
87
+ *
88
+ * THROUGH `ProviderContext`, not `ProviderRequest`, and the placement is the design. A stall watchdog
89
+ * is a property of the CONNECTION -- an adapter arms it around its own `boundedFetch`/`parseSse`,
90
+ * once, for every call it makes -- not of one turn's payload. Putting it on the request would invite
91
+ * a per-turn override that no ruling asks for and that an adapter would have to re-arm mid-stream.
92
+ *
93
+ * One resolution site, so the disclosed default cannot be applied differently by two callers.
94
+ */
95
+ export declare function resolveStallTimeoutMs(config: RuntimeConfig): number;
96
+ /**
97
+ * Assembles the `ProviderContext` an adapter runs under.
98
+ *
99
+ * THE PRODUCTION CALLER OF `resolveStallTimeoutMs`, and the reason this function exists rather than
100
+ * leaving five separate decisions to whoever wires a session (review round 1, M1). The stall timeout
101
+ * is the one that shows why: `sse.ts` reads `ctx.stallTimeoutMs` on every chunk, so a caller that
102
+ * assembled a context without it would silently disable R6-6's watchdog on every stream — a disclosed
103
+ * option that quietly did nothing.
104
+ *
105
+ * `log` defaults to a NO-OP rather than to a console writer: `ProviderContext.log`'s own contract is
106
+ * provider/model identifiers and byte COUNTS only, and a default that wrote anywhere would be a
107
+ * default that a careless adapter could turn into a content leak.
108
+ */
109
+ export declare function createProviderContext(config: RuntimeConfig, deps: {
110
+ providerId: string;
111
+ credentials: CredentialStore;
112
+ log?: ProviderContext["log"];
113
+ }): ProviderContext;
114
+ /** Convenience for a caller that has a catalog rather than a registry. One construction site, so a registry is never built twice for one session. */
115
+ export declare function createSelectionRegistry(catalog: WinterCatalog): ProviderRegistry;
@@ -0,0 +1,426 @@
1
+ import type { WinterCatalog, WinterProviderDescriptor } from "@yanlinglabs/winter-provider-catalog";
2
+ import type { CredentialRef, ProviderConnectionConfig, RuntimeConfig } from "@yanlinglabs/winter-agent-sdk";
3
+ import type { CredentialStore, ModelInfo, ProviderContext, ProviderRegistry, ResolvedModel } from "@yanlinglabs/winter-provider-runtime";
4
+ import { WinterProviderResolutionError, DECORATION_CHAR_BUDGET, MAX_DECORATION_CHARS } from "@yanlinglabs/winter-provider-runtime";
5
+ import { type KeychainSecretReader } from "./keychain-store.js";
6
+ import { type ToolSecretResolver } from "./tool-secret.js";
7
+ import { type WinterProviderIdentity } from "./selection.js";
8
+ import { type ClassifierRoute } from "./classifier/model-classifier.js";
9
+ import type { ClassifierInterface } from "../permissions/auto/engine.js";
10
+ import { type ContinuationChain, type ProviderStateRecord, type ProviderStateRecordInput } from "../store/provider-state.js";
11
+ import type { PricedUsage, Provider, ProviderUsage, ResolveModelSwitch, UsageRowFacts } from "../engine.js";
12
+ import { type SlotProviderResolution } from "./slots.js";
13
+ /**
14
+ * The pinned `ApiKeySource` vocabulary (`sdk.d.ts:127`), of which the JSDoc marks five members
15
+ * legacy — the live set is these four.
16
+ *
17
+ * WINTER'S MAPPING, and it is a DISCLOSED gap-fill rather than a translation. The union has exactly
18
+ * one spelling for "an API key", and it names an environment variable: `'ANTHROPIC_API_KEY'`. It has
19
+ * no spelling for "a key from the Keychain", "a key from a file" or "a key the host passed inline" —
20
+ * every credential shape R6-10 adds. So Winter reports `'ANTHROPIC_API_KEY'` for exactly that env
21
+ * name and `'none'` for everything else, on the pin's own gloss that `'none'` means "not via an API
22
+ * key" and is what the pinned runtime itself reports for OAuth, bearer and third-party-cloud auth.
23
+ *
24
+ * The REAL fact is never lost: it rides `winter_provider.authRefKind` on the same frame, which is
25
+ * where a consumer that cares about Winter's credential model is supposed to look. Inventing a fifth
26
+ * member of a closed pinned union would be the divergence; reporting the pin's own catch-all is not.
27
+ */
28
+ export type ApiKeySource = "ANTHROPIC_API_KEY" | "apiKeyHelper" | "/login managed key" | "none";
29
+ export declare function apiKeySourceFor(ref: CredentialRef | undefined): ApiKeySource;
30
+ /** The `AccountInfo` shape the pin declares (`sdk.d.ts:23-33`) — every field optional, an empty object valid. */
31
+ export interface AccountInfo {
32
+ email?: string;
33
+ organization?: string;
34
+ subscriptionType?: string;
35
+ tokenSource?: string;
36
+ apiKeySource?: string;
37
+ apiProvider?: "firstParty" | "bedrock" | "vertex" | "foundry" | "anthropicAws" | "anthropicGoogleCloud" | "mantle" | "gateway";
38
+ }
39
+ /** The one read of the table above (exported for its own unit test, exactly as `apiKeySourceFor` is). `undefined` = this provider has no member of its own and reports nothing. */
40
+ export declare function apiProviderFor(providerId: string | undefined): AccountInfo["apiProvider"] | undefined;
41
+ export interface SessionProviderOptions {
42
+ /** The session's EFFECTIVE config. */
43
+ config: RuntimeConfig;
44
+ /** The environment governing R6-13's harness alias and the `env` credential store. Explicit at every entrypoint. */
45
+ env: Record<string, string | undefined>;
46
+ /** Injected in tests so a fixture owns its own rows. Production: the catalog compiled into this build. */
47
+ catalog?: WinterCatalog;
48
+ /** Injected in tests (an in-memory store). Production: keychain + env + file + inline, composed below. */
49
+ credentials?: CredentialStore;
50
+ /**
51
+ * R6-13: the reserved `winter-test/<name>` namespace's in-process double.
52
+ *
53
+ * DEFAULTS TO `testProviderForNamespace` (`provider/mock.ts`) — the namespace is a DISCLOSED test
54
+ * affordance that exists in production by ruling, not an injection point a caller has to remember,
55
+ * and a default that refused it would make the namespace work on one leg and not another. A caller
56
+ * overrides it only to supply something the shared table cannot: `main.ts` wraps it to register the
57
+ * `bgtask` fixture's paired TOOL, and `testing.ts` replaces it with the live JS provider its caller
58
+ * handed the leg — the one thing a spawned process can never be given.
59
+ */
60
+ testProviders?: (name: string) => Provider | undefined;
61
+ /**
62
+ * R6-7: the resumed continuation chain, as a GETTER.
63
+ *
64
+ * A getter rather than a value because the chain is re-attached asynchronously at the start of the
65
+ * run (`attachContinuationChain`), after this wiring is built — a captured snapshot would always
66
+ * be the empty one.
67
+ */
68
+ chain?: () => ContinuationChain;
69
+ /**
70
+ * Review r1, M-1: where the renderer's sticky decoration decisions persist (the session's own
71
+ * provider-state sidecar, `SessionPersistence.recordProviderState`). Absent: they hold for this run only.
72
+ */
73
+ recordProviderState?: (record: ProviderStateRecordInput) => void | Promise<void>;
74
+ /** `ProviderContext.log` — provider/model identifiers and BYTE COUNTS only, never content. Defaults to a no-op. */
75
+ log?: ProviderContext["log"];
76
+ /**
77
+ * The OS home the `file` credential store resolves `~/.aws/credentials` under.
78
+ *
79
+ * Explicit at every entrypoint and NEVER defaulted to `os.homedir()` here: a default would make
80
+ * every test that forgot to set it read the developer's real credentials file, which is precisely
81
+ * the hazard the Global Constraints forbid. `env.HOME` is the caller's usual answer.
82
+ */
83
+ home?: string;
84
+ /**
85
+ * WS-13b R6b-7: the resolved `settings.providers` map, as a GETTER (see `SelectionDeps`' own
86
+ * field for why a getter is the hot-reload seam).
87
+ *
88
+ * Threaded into selection AND read again at the `set_model` seam: R6-K put resolution under the
89
+ * session provider precisely so a switch cannot walk around a rule the session start applied, and
90
+ * a disable that held only at start would be exactly such a walk-around.
91
+ */
92
+ providerSettings?: () => Record<string, {
93
+ enabled: boolean;
94
+ }> | undefined;
95
+ /**
96
+ * WS-13c §4 step 6 (P6.6): the slot resolver, so `set_model` accepts a SLOT NAME.
97
+ *
98
+ * Consulted only for a BARE name — a qualified `<providerId>/<model>` key is already an
99
+ * unambiguous statement and goes straight to R6-K's own rules, unchanged. A refusal is returned as
100
+ * the seam's typed refusal and becomes the control response, exactly like `provider-mismatch`:
101
+ * never a parked switch, never a substitution.
102
+ *
103
+ * ABSENT -> `set_model` keeps its pre-P6.6 shape verbatim (every scripted double, every pre-P6.6
104
+ * fixture, and the reserved `winter-test/<name>` namespace, for which the wiring withholds it).
105
+ */
106
+ resolveSlot?: (requested: string, currentModelKey: string | undefined) => SlotProviderResolution;
107
+ /**
108
+ * P7a LANE B (D30): `settings.advisor.model`, as a GETTER over the same live settings view
109
+ * `providerSettings` reads.
110
+ *
111
+ * A GETTER for the reason every other settings seam in this file is one: the value is HOT (a
112
+ * Global Constraint of this phase -- "takes effect at the next quiescent boundary through the live
113
+ * settings getter, no restart"), and a string captured at construction could only ever be the
114
+ * value the session started with.
115
+ *
116
+ * ABSENT -> no setting is in play and the precedence falls to `Options.advisor.model` and then to
117
+ * D30's per-family default, which is exactly what a host that resolves no settings should get.
118
+ */
119
+ advisorModelSetting?: () => string | undefined;
120
+ /**
121
+ * P7a LANE B, fix r1 (review M-1): a monotonic number the wiring bumps whenever it LEARNS something
122
+ * about a provider's credential, so a memo taken on a cold view cannot outlive that view.
123
+ *
124
+ * WHY IT HAS TO EXIST. `production-wiring.ts`'s `credentialPresent` is a synchronous answer over an
125
+ * asynchronous fact: the session's own provider is `"present"` by construction, every other
126
+ * provider is `"unknown"` until a background probe lands, and nothing awaits those probes. The very
127
+ * first consumer is `reviewerResolves()` computing `init.tools`, which is what FIRES the prewarm --
128
+ * so the advisor's first resolution is necessarily cold, and a memo without this term pins that
129
+ * cold answer for the session's whole life.
130
+ *
131
+ * A VERSION rather than the credential view itself, for the same reason `settingsVersion` is a
132
+ * number: the memo compares it, and comparing a view by value would mean re-deriving the whole
133
+ * presence map on every capability check.
134
+ *
135
+ * ABSENT -> `0`, i.e. "nothing here ever learns anything", which is the truth for a caller that
136
+ * builds a wiring directly with a fixed credential store.
137
+ */
138
+ credentialEpoch?: () => number;
139
+ /**
140
+ * The keychain's RAW reader, for `resolveToolSecret` (a tool's key may be a bare string, which the
141
+ * credential store rightly refuses -- see `tool-secret.ts`).
142
+ *
143
+ * DEFAULTS TO THE REAL ONE ONLY WHEN `credentials` IS ALSO DEFAULTED. A caller that injects a
144
+ * credential store (every test) has said "this is the only source", and quietly reading the real
145
+ * keychain beside it would be exactly the test-touches-the-login-keychain hazard the store's own
146
+ * injection exists to prevent. Such a caller passes a reader over a fake backend, or none at all.
147
+ */
148
+ readKeychainSecret?: KeychainSecretReader;
149
+ }
150
+ /**
151
+ * What `resolveAuxiliaryModel` answers: a BUILT, non-streaming provider for the tag, or a typed
152
+ * refusal. A VALUE in both arms -- the consumer is a tool executor, which must never throw.
153
+ */
154
+ export type AuxiliaryModelResolution = {
155
+ ok: true;
156
+ provider: Provider;
157
+ modelKey: string;
158
+ } | {
159
+ ok: false;
160
+ code: string;
161
+ message: string;
162
+ };
163
+ export interface SessionProviderWiring {
164
+ /** What `runEngine` is handed. Either the catalog-resolved adapter chain or the reserved namespace's scripted double. */
165
+ provider: Provider;
166
+ registry: ProviderRegistry;
167
+ credentials: CredentialStore;
168
+ catalog: WinterCatalog;
169
+ /** ABSENT for a `winter-test/<name>` session: a scripted double has no catalog identity, and putting a fake row in the init frame would be worse than omitting it. */
170
+ identity?: WinterProviderIdentity;
171
+ resolved?: ResolvedModel;
172
+ /**
173
+ * PRESENT when selection REFUSED, in which case this wiring's `provider` is the one that rethrows
174
+ * the refusal on its first generation (see `buildSessionProvider`'s own header for the ruling).
175
+ *
176
+ * Exposed rather than swallowed so an entrypoint can also report the reason on stderr: the frame
177
+ * stream is the host's channel, stderr is the operator's, and a refusal deserves both.
178
+ */
179
+ resolutionError?: WinterProviderResolutionError;
180
+ /** R6-9: the pinned `system/init.apiKeySource`. Always present — the pin makes the field REQUIRED. */
181
+ apiKeySource: ApiKeySource;
182
+ /** P4 carry: `toolCalling === "native"`, from the descriptor's own evidence. Absent when nothing is known. */
183
+ providerSupportsToolSearch?: boolean;
184
+ /** The descriptor's context window, unless the host set `contextWindowTokens` explicitly. */
185
+ contextWindowTokens?: number;
186
+ /** R6-14: which classifier this session got, and why. Recorded so `fallback_state` can name the reason. */
187
+ classifierRoute: ClassifierRoute;
188
+ /** ABSENT unless the route produced a real one — `createAutoEngine`'s own default (always `no_verdict`) is what a manual fallback means. */
189
+ classifier?: ClassifierInterface;
190
+ /**
191
+ * P7a LANE B (D29/D30) — THE ADVISOR'S REVIEWER, resolved on demand.
192
+ *
193
+ * REPLACES the P2-carry `advisorProvider`, which was a single provider built once from
194
+ * `config.advisor.model` and nothing else. Three things forced a function:
195
+ *
196
+ * - the reviewer's model can come from `settings.advisor.model`, which is HOT (a Global
197
+ * Constraint of this phase): a value captured at session start could never see an edit;
198
+ * - its DEFAULT depends on the session's family (D30), and the session's family changes with
199
+ * `set_model` -- so the answer depends on the LIVE model key, which is the argument;
200
+ * - the advisor tool's own contract is "a reviewer is resolvable RIGHT NOW" (its
201
+ * `winter.reviewer-model` capability gate), which is a question, not a stored object.
202
+ *
203
+ * PINNED AT FIRST USE (WS-13 R6-G): the built provider is memoised on the inputs that chose it
204
+ * (the option, the live setting, the session's model key), so repeated calls within one settings
205
+ * version return the SAME provider instance -- and a settings edit re-pins at the next call, which
206
+ * is the next quiescent boundary. No cache is shared with the classifier (R6-G's own rule); this
207
+ * memo holds one entry and its key is the route's own inputs.
208
+ *
209
+ * ABSENT for a session with no catalog identity (the reserved `winter-test/<name>` namespace and a
210
+ * session whose own model failed to resolve): there is no family to default from and no row to
211
+ * resolve against, and a fabricated answer would be worse than the honest "no reviewer".
212
+ */
213
+ resolveReviewer?: (currentModelKey?: string) => {
214
+ provider: Provider;
215
+ model: string;
216
+ } | undefined;
217
+ /**
218
+ * A TOOL'S OWN INNER MODEL, by tag -- `WebFetch`'s page-digest model is the first consumer.
219
+ *
220
+ * `tag` is a provider-qualified key or a slot name and goes through the SAME slot resolver
221
+ * `set_model`, a child spawn and the advisor use, then `registry.resolve`, then `buildProvider`
222
+ * under Ruling E-1: `opts.authRef` is the ROUTE's own credential (step 1); without it a target on
223
+ * the session's provider uses the session's material and a target on ANOTHER provider gets its own
224
+ * `<providerId>:default` record, verified at its first generation with a typed
225
+ * `no-credential-for-provider`. The session's key is never sent to another provider.
226
+ *
227
+ * The provider is wrapped `withoutStreaming` (R6-G: an auxiliary generation emits no
228
+ * `stream_event`s) and MEMOISED per `(tag, authRef, session model key, credential epoch)`, so the
229
+ * capability check that asks "does the digest model resolve" on every tool-list read costs one
230
+ * resolution per credential/settings view, and a repeated call reuses one provider object.
231
+ *
232
+ * It answers with a REFUSAL VALUE, unlike `resolveReviewer` (whose throw is a documented
233
+ * workaround for a pinned return type). "The session's own model" is NOT a tag and never comes
234
+ * here: the engine already holds that provider, live, and re-resolving it would be a second
235
+ * opinion about a decision `set_model` and the fallback already made.
236
+ *
237
+ * ABSENT on the two arms with no catalog identity (the reserved test namespace, a refused
238
+ * session): a stated tag is then simply unresolvable, and the consumer says so.
239
+ */
240
+ resolveAuxiliaryModel?: (tag: string, opts?: {
241
+ authRef?: CredentialRef;
242
+ currentModelKey?: string;
243
+ }) => AuxiliaryModelResolution;
244
+ /**
245
+ * Resolves a TOOL's secret from an arbitrary ref -- see `tool-secret.ts`. Present on EVERY arm: it
246
+ * depends on the credential store, not on the session having a model.
247
+ */
248
+ resolveToolSecret: ToolSecretResolver;
249
+ /**
250
+ * Builds a `Provider` for any resolved model against THAT TARGET's material (Ruling E-1), the
251
+ * session's renderer and the session's chain.
252
+ *
253
+ * Exposed because R6-17's per-child provider needs the identical construction — a child built
254
+ * through a second construction path would get a different context (and, per
255
+ * `createProviderContext`'s own header, could silently lose the stall watchdog).
256
+ */
257
+ buildProvider(resolved: ResolvedModel, opts?: BuildProviderOptions): Provider;
258
+ /** Ruling E-1: WHICH credential and connection `buildProvider` would use for this target, and why. Pure -- no store is consulted. */
259
+ describeTargetMaterial(resolved: ResolvedModel, opts?: BuildProviderOptions): TargetMaterial;
260
+ /** The provider this session is configured for (`config.provider.providerId`, else the resolved model's). Undefined only for a session with neither. */
261
+ sessionProviderId(): string | undefined;
262
+ /**
263
+ * P6 fix wave (Ruling E-2): THE SWITCH SEAM -- `EngineOptions.resolveModelSwitch`. R6-K resolution
264
+ * under the session provider, `buildProvider` under Ruling E-1, the resolved identity, and the two
265
+ * continuity endpoints `classifySwitch` compares. Present on every arm: a session that started
266
+ * unresolvable can be handed a model that resolves and recover.
267
+ */
268
+ resolveModelSwitch: ResolveModelSwitch;
269
+ /** P6 fix wave (Ruling E-3): `fallbackModel`'s candidates as catalog keys, in order, domain-checked at init. Empty for the reserved namespace and for a refused session. */
270
+ fallbackModelKeys: string[];
271
+ /** P6 fix wave (Ruling E-4, R6-H): prices one generation for the model it ran on, from the catalog's `pricing` evidence. `undefined` for an unpriced row. */
272
+ priceUsage(modelKey: string, usage: ProviderUsage): PricedUsage | undefined;
273
+ /** The catalog facts for a `modelUsage` row of ANY resolvable model, priced or not (dist-session fixes C1). `undefined` for a key the catalog cannot resolve. */
274
+ usageRowFacts(modelKey: string): UsageRowFacts | undefined;
275
+ /** P6 fix wave (Ruling E-5, R6-14): the resolved classifier model's key, for the session pin. Present exactly when `classifier` is. */
276
+ classifierIdentity?: {
277
+ modelKey: string;
278
+ };
279
+ /** R6-I: the `supportedModels()` rows for this session. */
280
+ supportedModels(): ModelInfo[];
281
+ /** R6-I / capture (d): the initialize-response account surface. Never `system/init` — the pin has no account field there. */
282
+ accountInfo(): AccountInfo;
283
+ }
284
+ /** What a caller may pass to `buildProvider`. `authRef` is the target ROUTE's own credential (a classifier's `autoClassifier.authRef`, an advisor's `advisor.authRef`). */
285
+ export interface BuildProviderOptions {
286
+ authRef?: CredentialRef;
287
+ }
288
+ /**
289
+ * Ruling E-1: the credential and connection a provider built for `resolved` is given.
290
+ *
291
+ * `source` records which step of the rule answered:
292
+ * - `route` an explicit `authRef` on the target's own route;
293
+ * - `session` the target IS the session's provider, so the session's own material;
294
+ * - `provider-record` the target provider's OWN keychain record (`<providerId>:default`, R6-10's
295
+ * one-record-per-provider/account), whose existence the built provider
296
+ * verifies on its first generation and refuses (typed) when absent.
297
+ *
298
+ * `crossProvider` is the fact every consumer keys on: a cross-provider target's `connection` is its
299
+ * own generated endpoint -- never the session's user `baseUrl`/headers.
300
+ */
301
+ export interface TargetMaterial {
302
+ authRef: CredentialRef;
303
+ connection?: ProviderConnectionConfig;
304
+ source: "route" | "session" | "provider-record";
305
+ crossProvider: boolean;
306
+ }
307
+ /** The account id a target provider's OWN keychain record is looked up under when a route names no ref (Ruling E-1 step 2). Disclosed in WS-13 §6. */
308
+ export declare const DEFAULT_PROVIDER_ACCOUNT_ID = "default";
309
+ /**
310
+ * The production credential store: Keychain, then env, then file, then inline.
311
+ *
312
+ * COMPOSED, not chosen: a `CredentialRef` names its own kind, every member answers `null` (or a
313
+ * typed `unsupported` the composite skips) for a ref it does not own, so the order is about which
314
+ * member gets asked first and not about precedence between competing answers.
315
+ *
316
+ * The Keychain member is FIRST and is constructed unconditionally, which is safe because
317
+ * `keychain-store.ts` resolves `Bun.secrets` LAZILY — a session with no keychain ref never touches
318
+ * it, and a runtime without it reports a typed failure at the point of use rather than at import.
319
+ */
320
+ export declare function createProductionCredentialStore(config: RuntimeConfig, env: Record<string, string | undefined>, home: string): CredentialStore;
321
+ /**
322
+ * The connection profile for one resolved provider.
323
+ *
324
+ * THE RULE, and the fixture `production-wiring.test.ts` pins it in both directions:
325
+ *
326
+ * - The operator's own `connection.baseUrl` always wins, verbatim, and is a USER endpoint.
327
+ * - Otherwise the catalog's `defaultEndpoints.api` is copied in ONLY when the adapter has no
328
+ * vendor default of its own to fall back to — which is exactly the adapters that serve MORE THAN
329
+ * ONE provider (`winter.local-openai`'s twelve local runners, `winter.openai-chat-completions`'s
330
+ * deepseek and openrouter). One adapter, many vendors, no single default.
331
+ * - Otherwise nothing is set, so the adapter uses its own reviewed endpoint and
332
+ * `applyPrivilegedHeaders` still has something to gate.
333
+ *
334
+ * "Serves more than one provider" is deliberately computed from the catalog rather than hard-coded,
335
+ * and the fixture asserts BOTH directions (`google`/`bedrock` get no baseUrl; `deepseek` and a
336
+ * local runner do). `anthropic` (P6.5) and `openai` (WS-23, when `xai` joined it on
337
+ * `winter.openai-responses`) each crossed from the first group to the second, and the fixture failed
338
+ * loudly both times; since P7a the copy is stamped `"reviewed"`, so crossing no longer demotes the
339
+ * endpoint (it pins that too).
340
+ *
341
+ * P7a (WS-13b §10, closing the M-1 partial): every profile this function returns with a `baseUrl`
342
+ * now says WHERE that URL came from. The copy is `"reviewed"`; anything the operator supplied is
343
+ * `"user"`. Until the marker existed, the two were byte-identical strings and every adapter had to
344
+ * read the copy as a user endpoint — which silently took 156 rows off the privileged-header path
345
+ * in production while adapter fixtures, passing a generated base URL directly, kept passing.
346
+ */
347
+ export declare function connectionForProvider(config: RuntimeConfig, catalog: WinterCatalog, provider: WinterProviderDescriptor): ProviderConnectionConfig | undefined;
348
+ /**
349
+ * Ruling E-1: a CROSS-PROVIDER target's connection. The session's user `connection` is NOT consulted
350
+ * -- a user `baseUrl` and its headers belong to the session's own provider -- so the target reaches
351
+ * its own generated endpoint (copied into the profile for a multi-provider adapter, per the rule
352
+ * above; left to the adapter's reviewed default otherwise).
353
+ *
354
+ * P7a: for a `requiresUserEndpoint` provider this ALWAYS refuses. Such a target has no endpoint of
355
+ * its own and, by this function's own rule, may not borrow the session's -- so there is nothing to
356
+ * reach and the refusal is the honest answer, not an omission. A classifier, advisor or R6-17 child
357
+ * on `azure-ai` is exactly that shape.
358
+ */
359
+ export declare function generatedConnectionForProvider(catalog: WinterCatalog, provider: WinterProviderDescriptor): ProviderConnectionConfig | undefined;
360
+ /**
361
+ * Builds the session's provider, identity, classifier and account surface.
362
+ *
363
+ * NEVER THROWS for an unresolvable session model (R6-9, as reversed in review round 1): the refusal
364
+ * is DEFERRED -- this returns a wiring whose `provider.generate()` rethrows the typed
365
+ * `WinterProviderResolutionError`, so the session still starts, `system/init` is emitted (with no
366
+ * `winter_provider`), and the first generation lands on R6-F's pinned result shape before `query()`
367
+ * throws. `resolutionError` carries the reason so an entrypoint can also report it on stderr.
368
+ */
369
+ /**
370
+ * P7a (D19 / R-7a-8) -- THE KEYCHAIN BLOCK'S SINGLE SOURCE.
371
+ *
372
+ * A FUNCTION, and exported, because the answer is needed in two places -- the credential store this
373
+ * session opens (`buildCredentialStore`) and the `service` a cross-provider record's `authRef`
374
+ * carries (`describeTargetMaterial`) -- and the two naming different services would write a
375
+ * credential where nothing will look for it.
376
+ *
377
+ * `brand.keychainService` is the source. `config.keychainService` is the DEPRECATED standalone
378
+ * alias, and the wrapper emits it only when the session actually chose a service (branded, or the
379
+ * option set) -- so a branded host that set `brand.keychainService` and nothing else leaves the
380
+ * top-level key ABSENT, and a reader of that key alone silently opened WINTER's own service for a
381
+ * reuser whose whole profile said otherwise. The two surfaces AGREE by construction whenever both
382
+ * are present (`query()` folds the deprecated option INTO the profile before resolving), so
383
+ * preferring the profile can never contradict a host that used the old field.
384
+ *
385
+ * `undefined` means "the session chose none" -- `createKeychainCredentialStore`'s own default
386
+ * applies, and the `authRef` carries no `service` key at all (which is what keeps an unbranded
387
+ * session's `authRef` byte-identical to before P7a).
388
+ */
389
+ export declare function resolveSessionKeychainService(config: RuntimeConfig): string | undefined;
390
+ /** WS-23 (reasoning-state): the cross-family decoration caps -- declared beside the fit estimate that accounts for them (provider-runtime `continuity/fit.ts`, where the rationale is). */
391
+ export { DECORATION_CHAR_BUDGET, MAX_DECORATION_CHARS };
392
+ export declare function buildSessionProvider(opts: SessionProviderOptions): SessionProviderWiring;
393
+ /**
394
+ * R6-7 / Lane C wiring item 2: the RESUMED continuation chain, loaded once before the run starts.
395
+ *
396
+ * WHY IT IS LOADED HERE AND NOT INSIDE THE ENGINE. `attachContinuationChain` (engine.ts) folds each
397
+ * record's `origin` onto the in-memory message it belongs to, which is what the domain check reads —
398
+ * but the renderer's OTHER input is the chain itself, and that is where the `summary` records live.
399
+ * R6-8 forbids a foreign summary from ever entering `assistant.message.content`, so the sidecar is
400
+ * its only home; a renderer handed an empty chain therefore renders a resumed cross-family history
401
+ * with no decoration at all, which is indistinguishable from a session that had nothing to carry.
402
+ *
403
+ * `entryUuids` is the set of assistant entries that ACTUALLY EXIST in the rebuilt history —
404
+ * `buildContinuationChain`'s own rule is that a record without its entry is ignored (and
405
+ * garbage-collectable), so passing the record's own anchors back in would defeat the check.
406
+ *
407
+ * An unreadable sidecar yields an EMPTY chain rather than a throw: `attachContinuationChain` already
408
+ * emits the `sidecar_unreadable` continuity warning for exactly this case, and a session must not
409
+ * fail to start because its optional continuation state could not be read.
410
+ */
411
+ export declare function loadResumedChain(store: {
412
+ loadProviderState?(): Promise<ProviderStateRecord[]>;
413
+ } | undefined, messages: ReadonlyArray<{
414
+ uuid?: string;
415
+ }>): Promise<ContinuationChain>;
416
+ /**
417
+ * A `Provider` that never streams, for the auxiliary generations R6-G names.
418
+ *
419
+ * `ProviderRequest.sink` is what makes a generation's `stream_event`s reach the host, and capture (F)
420
+ * found the pinned runtime forwarding events for only the FORWARDED generations — the compaction
421
+ * summariser, the classifier, the advisor and `countTokens` are all suppressed. The engine already
422
+ * builds those requests without a sink; this wrapper is the belt-and-braces half for a provider
423
+ * handed to one of them directly (the advisor backend below), so a future caller that copies a
424
+ * request wholesale cannot accidentally re-enable streaming for an auxiliary call.
425
+ */
426
+ export declare function withoutStreaming(provider: Provider): Provider;
@@ -0,0 +1,120 @@
1
+ import type { WinterCatalog } from "@yanlinglabs/winter-provider-catalog";
2
+ import type { ActiveSlotSet, ModelSlotSetting } from "@yanlinglabs/winter-agent-sdk";
3
+ /**
4
+ * The marker the Agent descriptor's static description carries, and the block it lives in.
5
+ *
6
+ * DECLARED HERE rather than in `tools/descriptors/agent.ts` on purpose: the engine has to strip the
7
+ * block when no active slot set is wired, and importing the descriptor module for a string would
8
+ * run its `stub(...)` registration as a side effect of loading the engine. This module has no side
9
+ * effects at all, so both ends can name the same constant.
10
+ */
11
+ export declare const AGENT_MODEL_SLOTS_MARKER = "{{MODEL_SLOTS}}";
12
+ export declare const AGENT_MODEL_SLOTS_BLOCK = "\n\nModel options for this session:\n{{MODEL_SLOTS}}";
13
+ /**
14
+ * The WS-06 canonical name of the one tool whose schema is rendered per family.
15
+ *
16
+ * Declared beside the marker for the same reason: the engine needs to recognise the descriptor and
17
+ * cannot import the descriptor (or the executor) module for a string without taking its
18
+ * registration side effects. `descriptors/agent.ts` and `tools/impl/agent.ts` both read it from
19
+ * here, so the name has one producer rather than three spellings that could drift.
20
+ */
21
+ export declare const AGENT_TOOL_CANONICAL_NAME = "Agent";
22
+ export interface ActiveSlotSetInput {
23
+ catalog: WinterCatalog;
24
+ currentModelKey: string | undefined;
25
+ customSlots: readonly ModelSlotSetting[] | undefined;
26
+ }
27
+ /**
28
+ * The slots this session offers (WS-13c §3).
29
+ *
30
+ * TOTAL BY CONSTRUCTION — it never throws. It is called on every turn to render the Agent tool, and
31
+ * a session whose model failed to resolve (or one running a scripted double, or one on an
32
+ * `allowUnlisted` pass-through with no catalog row) still renders tools. An exception here would
33
+ * take down the tool advertisement itself, which is a strictly worse answer than an honest
34
+ * `own-model` set naming the model the session is actually on.
35
+ */
36
+ export declare function computeActiveSlotSet(input: ActiveSlotSetInput): ActiveSlotSet;
37
+ /**
38
+ * The two things the Agent tool renders from the active set (WS-13c §3): the `model` property's
39
+ * `enum` (slot names in order) and one description line per slot, appended to the tool description
40
+ * as `<name> — <canonicalModelId>: <description> (<reason>)`.
41
+ *
42
+ * The tool SHAPE never changes — only these two.
43
+ */
44
+ export declare function renderAgentModelSchema(active: ActiveSlotSet): {
45
+ enum: string[];
46
+ descriptionLines: string[];
47
+ };
48
+ /**
49
+ * WS-13c §4 step 2, as three states rather than two (R-6c-27).
50
+ *
51
+ * `CredentialStore.get` is asynchronous (a Keychain read) while this whole resolver is synchronous,
52
+ * so a caller genuinely cannot always answer. Collapsing that to `true` made a COLD subscription row
53
+ * win §4 step 3-i over a WARM token row the user actually has — an openai-API-key-only session's
54
+ * first `Agent(model: "astra")` chose `codex-oauth`, and `set_model` reported success and only failed
55
+ * at the next generation. Collapsing it to `false` is worse: it writes "no credential configured"
56
+ * into a `wouldServe` line about a provider that may well be configured, which is a false statement
57
+ * about the user's setup rather than a missing one.
58
+ *
59
+ * So: `absent` filters the row out and names the reason; `unknown` keeps it, but orders it AFTER
60
+ * every `present` row in the same §4 tier.
61
+ */
62
+ export type CredentialPresence = "present" | "absent" | "unknown";
63
+ export interface SlotProviderResolutionInput {
64
+ catalog: WinterCatalog;
65
+ active: ActiveSlotSet;
66
+ requested: string;
67
+ hasCredential: (providerId: string) => CredentialPresence;
68
+ providerEnabled: (providerId: string) => boolean;
69
+ preferredProviders: readonly string[];
70
+ /**
71
+ * LANE A ADDITION to the spine's pinned input (optional, so every pinned call site still compiles).
72
+ *
73
+ * `ActiveSlotSet`/`SlotView` are the PUBLIC, host-facing shapes and carry no `provider` field, so a
74
+ * custom slot's pin (`modelSlots[].provider`, WS-13c §4 step 4) has nowhere to ride into this
75
+ * function. Without it a pinned slot would resolve to whatever step 3 ordered first — a silent
76
+ * substitution of one provider for another, which is the single thing §4 step 4 exists to prevent.
77
+ * Matched BY NAME (a validated set has unique names), never by index.
78
+ */
79
+ customSlots?: readonly ModelSlotSetting[];
80
+ }
81
+ export type SlotProviderResolution = {
82
+ ok: true;
83
+ modelKey: string;
84
+ providerId: string;
85
+ canonicalModelId: string;
86
+ slot: {
87
+ family: string;
88
+ name: string;
89
+ source: ActiveSlotSet["source"];
90
+ };
91
+ /**
92
+ * LANE A ADDITION: TRUE when `requested` was a slot NAME.
93
+ *
94
+ * A full catalog key or a canonical id passes through (§3: "`AgentInput.model` is slot names
95
+ * only" governs what the MODEL is offered; a host-side `AgentDefinition.model`,
96
+ * `WINTER_SUBAGENT_MODEL` and the inherited `config.model` are full identifiers and reach the
97
+ * same resolver). `slot` still carries the active family/source so the pinned shape stays
98
+ * total, so a consumer that RECORDS the slot on a child must gate on this flag — otherwise
99
+ * every pre-P6.6 spawn, whose model is the parent's own `config.model`, grows a `slot` record
100
+ * naming a slot nobody asked for (WS-13c §3: "the slot the request named, IF it named one").
101
+ */
102
+ viaSlotName: boolean;
103
+ } | {
104
+ ok: false;
105
+ code: "slot-unservable" | "ambiguous-slot-name" | "unknown-slot";
106
+ message: string;
107
+ wouldServe: Array<{
108
+ key: string;
109
+ providerId: string;
110
+ why: string;
111
+ }>;
112
+ };
113
+ /**
114
+ * Slot name -> provider + model key (WS-13c §4).
115
+ *
116
+ * NEVER A SUBSTITUTION (WS-13 §9): a failure is typed and carries `wouldServe` — the rows that would
117
+ * have served it and why each did not (no credential / disabled / pinned provider absent) — because
118
+ * "it did not work" and "you have no OpenAI key" are different problems for the user.
119
+ */
120
+ export declare function resolveSlotToProvider(input: SlotProviderResolutionInput): SlotProviderResolution;