@stigmer/runner 3.10.0 → 3.11.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 (260) hide show
  1. package/README.md +12 -1
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/activities/call-llm.js +9 -10
  4. package/dist/activities/call-llm.js.map +1 -1
  5. package/dist/activities/classify-tool-approvals.d.ts +2 -1
  6. package/dist/activities/classify-tool-approvals.js +28 -2
  7. package/dist/activities/classify-tool-approvals.js.map +1 -1
  8. package/dist/activities/discover-mcp-server.d.ts +32 -0
  9. package/dist/activities/discover-mcp-server.js +162 -27
  10. package/dist/activities/discover-mcp-server.js.map +1 -1
  11. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +8 -0
  12. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +1 -1
  13. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
  14. package/dist/activities/execute-cursor/approval-state.d.ts +28 -2
  15. package/dist/activities/execute-cursor/approval-state.js +7 -1
  16. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  17. package/dist/activities/execute-cursor/attachment-resolver.d.ts +14 -0
  18. package/dist/activities/execute-cursor/attachment-resolver.js +18 -4
  19. package/dist/activities/execute-cursor/attachment-resolver.js.map +1 -1
  20. package/dist/activities/execute-cursor/blueprint-resolver.d.ts +1 -9
  21. package/dist/activities/execute-cursor/blueprint-resolver.js +6 -22
  22. package/dist/activities/execute-cursor/blueprint-resolver.js.map +1 -1
  23. package/dist/activities/execute-cursor/env-resolver.js +3 -1
  24. package/dist/activities/execute-cursor/env-resolver.js.map +1 -1
  25. package/dist/activities/execute-cursor/error-classifier.d.ts +40 -3
  26. package/dist/activities/execute-cursor/error-classifier.js +81 -3
  27. package/dist/activities/execute-cursor/error-classifier.js.map +1 -1
  28. package/dist/activities/execute-cursor/extract-structured-output.d.ts +29 -0
  29. package/dist/activities/execute-cursor/extract-structured-output.js +58 -0
  30. package/dist/activities/execute-cursor/extract-structured-output.js.map +1 -0
  31. package/dist/activities/execute-cursor/hook-script.d.ts +14 -3
  32. package/dist/activities/execute-cursor/hook-script.js +72 -10
  33. package/dist/activities/execute-cursor/hook-script.js.map +1 -1
  34. package/dist/activities/execute-cursor/index.d.ts +5 -1
  35. package/dist/activities/execute-cursor/index.js +51 -57
  36. package/dist/activities/execute-cursor/index.js.map +1 -1
  37. package/dist/activities/execute-cursor/mcp-resolver.d.ts +24 -1
  38. package/dist/activities/execute-cursor/mcp-resolver.js +5 -2
  39. package/dist/activities/execute-cursor/mcp-resolver.js.map +1 -1
  40. package/dist/activities/execute-cursor/prompt-builder.d.ts +18 -4
  41. package/dist/activities/execute-cursor/prompt-builder.js +12 -7
  42. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  43. package/dist/activities/execute-cursor/turn-stream.js +4 -1
  44. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  45. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +18 -1
  46. package/dist/activities/execute-deep-agent/attachment-injector.js +68 -23
  47. package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
  48. package/dist/activities/execute-deep-agent/environment.js +3 -1
  49. package/dist/activities/execute-deep-agent/environment.js.map +1 -1
  50. package/dist/activities/execute-deep-agent/index.js +15 -0
  51. package/dist/activities/execute-deep-agent/index.js.map +1 -1
  52. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +7 -7
  53. package/dist/activities/execute-deep-agent/prompt-builder.js +8 -2
  54. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  55. package/dist/activities/execute-deep-agent/setup.d.ts +10 -0
  56. package/dist/activities/execute-deep-agent/setup.js +55 -23
  57. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  58. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +18 -1
  59. package/dist/activities/execute-deep-agent/subagent-transformer.js +8 -1
  60. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  61. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +11 -4
  62. package/dist/activities/execute-deep-agent/subagent-wiring.js +13 -4
  63. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  64. package/dist/activities/hydrate-workflow-execution.js +3 -1
  65. package/dist/activities/hydrate-workflow-execution.js.map +1 -1
  66. package/dist/activities/workflow-event-activities.d.ts +28 -10
  67. package/dist/activities/workflow-event-activities.js +87 -58
  68. package/dist/activities/workflow-event-activities.js.map +1 -1
  69. package/dist/claimcheck/payload-codec.js +21 -1
  70. package/dist/claimcheck/payload-codec.js.map +1 -1
  71. package/dist/client/stigmer-client.d.ts +9 -4
  72. package/dist/client/stigmer-client.js +28 -15
  73. package/dist/client/stigmer-client.js.map +1 -1
  74. package/dist/encryption/config.d.ts +32 -0
  75. package/dist/encryption/config.js +68 -0
  76. package/dist/encryption/config.js.map +1 -0
  77. package/dist/encryption/index.d.ts +3 -0
  78. package/dist/encryption/index.js +3 -0
  79. package/dist/encryption/index.js.map +1 -0
  80. package/dist/encryption/payload-codec.d.ts +41 -0
  81. package/dist/encryption/payload-codec.js +130 -0
  82. package/dist/encryption/payload-codec.js.map +1 -0
  83. package/dist/payload-codecs.d.ts +16 -0
  84. package/dist/payload-codecs.js +38 -0
  85. package/dist/payload-codecs.js.map +1 -0
  86. package/dist/preflight.d.ts +31 -0
  87. package/dist/preflight.js +43 -0
  88. package/dist/preflight.js.map +1 -1
  89. package/dist/runner-manager.js +5 -15
  90. package/dist/runner-manager.js.map +1 -1
  91. package/dist/runner.js +5 -16
  92. package/dist/runner.js.map +1 -1
  93. package/dist/shared/approval-policy.d.ts +9 -3
  94. package/dist/shared/approval-policy.js +15 -6
  95. package/dist/shared/approval-policy.js.map +1 -1
  96. package/dist/shared/attachment-naming.d.ts +53 -0
  97. package/dist/shared/attachment-naming.js +59 -0
  98. package/dist/shared/attachment-naming.js.map +1 -0
  99. package/dist/shared/caller-identity.d.ts +23 -2
  100. package/dist/shared/caller-identity.js +36 -5
  101. package/dist/shared/caller-identity.js.map +1 -1
  102. package/dist/shared/channel-attachment.js +1 -0
  103. package/dist/shared/channel-attachment.js.map +1 -1
  104. package/dist/shared/checkpointer/http-saver.d.ts +42 -1
  105. package/dist/shared/checkpointer/http-saver.js +96 -8
  106. package/dist/shared/checkpointer/http-saver.js.map +1 -1
  107. package/dist/shared/conversation-attachment.js +1 -0
  108. package/dist/shared/conversation-attachment.js.map +1 -1
  109. package/dist/shared/datastore-attachment.d.ts +50 -7
  110. package/dist/shared/datastore-attachment.js +93 -11
  111. package/dist/shared/datastore-attachment.js.map +1 -1
  112. package/dist/shared/http-retry.d.ts +43 -0
  113. package/dist/shared/http-retry.js +50 -0
  114. package/dist/shared/http-retry.js.map +1 -0
  115. package/dist/shared/llm-backend.d.ts +275 -0
  116. package/dist/shared/llm-backend.js +425 -0
  117. package/dist/shared/llm-backend.js.map +1 -0
  118. package/dist/shared/llm-proxy.d.ts +8 -0
  119. package/dist/shared/llm-proxy.js +15 -0
  120. package/dist/shared/llm-proxy.js.map +1 -1
  121. package/dist/shared/mcp-enabled-tools.d.ts +57 -0
  122. package/dist/shared/mcp-enabled-tools.js +86 -0
  123. package/dist/shared/mcp-enabled-tools.js.map +1 -0
  124. package/dist/shared/mcp-manager.d.ts +3 -1
  125. package/dist/shared/mcp-manager.js +17 -4
  126. package/dist/shared/mcp-manager.js.map +1 -1
  127. package/dist/shared/mcp-resolver.d.ts +39 -2
  128. package/dist/shared/mcp-resolver.js +38 -2
  129. package/dist/shared/mcp-resolver.js.map +1 -1
  130. package/dist/shared/model-client.d.ts +12 -5
  131. package/dist/shared/model-client.js +138 -18
  132. package/dist/shared/model-client.js.map +1 -1
  133. package/dist/shared/model-error.js +198 -5
  134. package/dist/shared/model-error.js.map +1 -1
  135. package/dist/shared/plan-mode-permissions.d.ts +26 -0
  136. package/dist/shared/plan-mode-permissions.js +28 -0
  137. package/dist/shared/plan-mode-permissions.js.map +1 -0
  138. package/dist/worker.d.ts +2 -1
  139. package/dist/worker.js +2 -4
  140. package/dist/worker.js.map +1 -1
  141. package/dist/workflow-engine/types.d.ts +18 -0
  142. package/dist/workflow-engine/types.js.map +1 -1
  143. package/dist/workflows/call-agent-orchestrator.d.ts +9 -0
  144. package/dist/workflows/call-agent-orchestrator.js +1 -0
  145. package/dist/workflows/call-agent-orchestrator.js.map +1 -1
  146. package/dist/workflows/connect-mcp-server.js +7 -0
  147. package/dist/workflows/connect-mcp-server.js.map +1 -1
  148. package/dist/workflows/engine-core.js +23 -2
  149. package/dist/workflows/engine-core.js.map +1 -1
  150. package/dist/workflows/execute-from-execution.d.ts +1 -1
  151. package/dist/workflows/execute-from-execution.js +11 -1
  152. package/dist/workflows/execute-from-execution.js.map +1 -1
  153. package/package.json +8 -2
  154. package/src/__tests__/claimcheck-codec.test.ts +36 -0
  155. package/src/__tests__/encryption-codec.test.ts +234 -0
  156. package/src/__tests__/fixtures/encrypted-payload-fixture.json +15 -0
  157. package/src/__tests__/history-encryption-e2e.test.ts +243 -0
  158. package/src/__tests__/preflight.test.ts +50 -2
  159. package/src/activities/__tests__/call-llm.test.ts +75 -0
  160. package/src/activities/__tests__/classify-tool-approvals.test.ts +117 -1
  161. package/src/activities/__tests__/discover-mcp-server.hang.test.ts +103 -0
  162. package/src/activities/__tests__/discover-mcp-server.test.ts +203 -0
  163. package/src/activities/__tests__/workflow-event-activities.test.ts +107 -8
  164. package/src/activities/call-llm.ts +9 -16
  165. package/src/activities/classify-tool-approvals.ts +34 -4
  166. package/src/activities/discover-mcp-server.ts +190 -32
  167. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +9 -0
  168. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +14 -0
  169. package/src/activities/execute-cursor/__tests__/attachment-resolver.test.ts +53 -0
  170. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +40 -14
  171. package/src/activities/execute-cursor/__tests__/error-classifier-extraction.test.ts +208 -0
  172. package/src/activities/execute-cursor/__tests__/extract-structured-output.test.ts +120 -0
  173. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +93 -0
  174. package/src/activities/execute-cursor/__tests__/mcp-resolver.test.ts +125 -0
  175. package/src/activities/execute-cursor/__tests__/prompt-builder-delegation.test.ts +1 -1
  176. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +13 -0
  177. package/src/activities/execute-cursor/approval-state.ts +30 -1
  178. package/src/activities/execute-cursor/attachment-resolver.ts +31 -3
  179. package/src/activities/execute-cursor/blueprint-resolver.ts +7 -27
  180. package/src/activities/execute-cursor/env-resolver.ts +3 -1
  181. package/src/activities/execute-cursor/error-classifier.ts +91 -4
  182. package/src/activities/execute-cursor/extract-structured-output.ts +72 -0
  183. package/src/activities/execute-cursor/hook-script.ts +74 -10
  184. package/src/activities/execute-cursor/index.ts +55 -71
  185. package/src/activities/execute-cursor/mcp-resolver.ts +36 -2
  186. package/src/activities/execute-cursor/prompt-builder.ts +34 -9
  187. package/src/activities/execute-cursor/turn-stream.ts +5 -2
  188. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +110 -8
  189. package/src/activities/execute-deep-agent/__tests__/datastore-degradation.test.ts +104 -0
  190. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +2 -0
  191. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
  192. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
  193. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +34 -5
  194. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
  195. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +173 -0
  196. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +12 -7
  197. package/src/activities/execute-deep-agent/attachment-injector.ts +94 -30
  198. package/src/activities/execute-deep-agent/environment.ts +3 -1
  199. package/src/activities/execute-deep-agent/index.ts +20 -0
  200. package/src/activities/execute-deep-agent/prompt-builder.ts +20 -10
  201. package/src/activities/execute-deep-agent/setup.ts +76 -28
  202. package/src/activities/execute-deep-agent/subagent-transformer.ts +23 -1
  203. package/src/activities/execute-deep-agent/subagent-wiring.ts +14 -4
  204. package/src/activities/hydrate-workflow-execution.ts +3 -1
  205. package/src/activities/workflow-event-activities.ts +96 -69
  206. package/src/claimcheck/payload-codec.ts +33 -1
  207. package/src/client/__tests__/stigmer-client.test.ts +8 -8
  208. package/src/client/stigmer-client.ts +32 -18
  209. package/src/encryption/config.ts +91 -0
  210. package/src/encryption/index.ts +3 -0
  211. package/src/encryption/payload-codec.ts +152 -0
  212. package/src/payload-codecs.ts +56 -0
  213. package/src/preflight.ts +45 -0
  214. package/src/runner-manager.ts +6 -24
  215. package/src/runner.ts +6 -25
  216. package/src/shared/__tests__/approval-policy.test.ts +82 -39
  217. package/src/shared/__tests__/attachment-naming.test.ts +159 -0
  218. package/src/shared/__tests__/bedrock-adapter.test.ts +213 -0
  219. package/src/shared/__tests__/bedrock-seam.test.ts +390 -0
  220. package/src/shared/__tests__/caller-identity.test.ts +25 -0
  221. package/src/shared/__tests__/channel-attachment.test.ts +1 -1
  222. package/src/shared/__tests__/connect-backfill.test.ts +1 -0
  223. package/src/shared/__tests__/conversation-attachment.test.ts +1 -1
  224. package/src/shared/__tests__/datastore-attachment.test.ts +129 -1
  225. package/src/shared/__tests__/foundry-adapter.test.ts +276 -0
  226. package/src/shared/__tests__/foundry-seam.test.ts +482 -0
  227. package/src/shared/__tests__/http-retry.test.ts +67 -0
  228. package/src/shared/__tests__/llm-backend.test.ts +616 -0
  229. package/src/shared/__tests__/mcp-enabled-tools.test.ts +86 -0
  230. package/src/shared/__tests__/mcp-manager.test.ts +84 -2
  231. package/src/shared/__tests__/mcp-resolver.test.ts +146 -3
  232. package/src/shared/__tests__/model-client.test.ts +154 -0
  233. package/src/shared/__tests__/model-error.test.ts +289 -1
  234. package/src/shared/__tests__/synthesized-attachment.test.ts +1 -0
  235. package/src/shared/__tests__/vertex-adapter.test.ts +169 -0
  236. package/src/shared/__tests__/vertex-seam.test.ts +295 -0
  237. package/src/shared/approval-policy.ts +14 -7
  238. package/src/shared/attachment-naming.ts +78 -0
  239. package/src/shared/caller-identity.ts +40 -5
  240. package/src/shared/channel-attachment.ts +1 -0
  241. package/src/shared/checkpointer/__tests__/http-saver.test.ts +196 -1
  242. package/src/shared/checkpointer/http-saver.ts +117 -9
  243. package/src/shared/conversation-attachment.ts +1 -0
  244. package/src/shared/datastore-attachment.ts +106 -11
  245. package/src/shared/http-retry.ts +50 -0
  246. package/src/shared/llm-backend.ts +544 -0
  247. package/src/shared/llm-proxy.ts +15 -0
  248. package/src/shared/mcp-enabled-tools.ts +105 -0
  249. package/src/shared/mcp-manager.ts +21 -4
  250. package/src/shared/mcp-resolver.ts +73 -2
  251. package/src/shared/model-client.ts +161 -19
  252. package/src/shared/model-error.ts +222 -4
  253. package/src/shared/plan-mode-permissions.ts +30 -0
  254. package/src/worker.ts +4 -5
  255. package/src/workflow-engine/types.ts +18 -0
  256. package/src/workflows/__tests__/execute-serverless-workflow.test.ts +68 -2
  257. package/src/workflows/call-agent-orchestrator.ts +10 -0
  258. package/src/workflows/connect-mcp-server.ts +7 -0
  259. package/src/workflows/engine-core.ts +23 -2
  260. package/src/workflows/execute-from-execution.ts +12 -2
@@ -22,8 +22,12 @@
22
22
  * OSS callers resolve as the local principal (T05 R2).
23
23
  *
24
24
  * Approval-free by construction (DD-001 SD-3): empty toolApprovals +
25
- * pinnedToolApprovals mean mergeApprovalPolicies emits no entries for
26
- * this server — zero classifier involvement. `discoveredCapabilitiesEmpty`
25
+ * pinnedToolApprovals + toolApprovalOverrides mean mergeApprovalPolicies
26
+ * emits no entries for this server — zero classifier involvement, and no
27
+ * proto surface can target it (the attachment has no McpServerUsage, and
28
+ * since issue #349 an agent's overrides are scoped to their own usage's
29
+ * server, so a same-named override elsewhere cannot reach this one).
30
+ * `discoveredCapabilitiesEmpty`
27
31
  * is false and the attachment has no McpServerUsage, so the connect
28
32
  * backfill (whose destructiveHint tightener would force-gate
29
33
  * delete_record — silently skipped on channels under UNATTENDED mode)
@@ -48,9 +52,48 @@ export declare const RECORDS_ROUTE = "/records";
48
52
  */
49
53
  export declare function synthesizeDatastoreAttachment(datastoreUsages: DatastoreUsage[], options: SynthesizedAttachmentOptions): ResolvedMcpServer | undefined;
50
54
  /**
51
- * The `<available_datastores>` prompt section (DD-005 SD-5, the
52
- * skills-section precedent): names the attached datastores and points
53
- * the model at describe_datastore first. Shared by both harnesses so
54
- * the section text cannot drift (the sender-identity precedent).
55
+ * The five record tools the records roster always serves (DD-005; the
56
+ * mcp-server's records roster registers all five unconditionally for the
57
+ * agent audience — only the `org` argument shape varies by audience, see
58
+ * mcp-server/src/domains/records/tools.ts). Because the roster never
59
+ * legitimately narrows, any of these missing from the connected toolset
60
+ * means the store is degraded (issue #325) — the prompt section and the
61
+ * reconciliation both derive from this one list so they cannot drift.
55
62
  */
56
- export declare function formatDatastoresSection(datastoreUsages: DatastoreUsage[]): string;
63
+ export declare const EXPECTED_RECORD_TOOLS: readonly ["describe_datastore", "find_records", "insert_record", "update_record", "delete_record"];
64
+ /**
65
+ * Reconcile the record tools actually connected against the roster
66
+ * contract (issue #325). Returns the expected tools absent from
67
+ * `actualToolNames` — empty means healthy. Names are bare tool names
68
+ * exactly as reported by tools/list (the mcp-enabled-tools identity
69
+ * space); extraneous names are ignored.
70
+ */
71
+ export declare function missingRecordTools(actualToolNames: Iterable<string>): string[];
72
+ /**
73
+ * The operator-facing degradation notice (issue #325): pushed as a
74
+ * MESSAGE_SYSTEM row on the execution status so "declared N datastores,
75
+ * X/5 record tools connected" is visible without reading a transcript.
76
+ * Lives HERE with the rest of the datastore-attachment wording — the
77
+ * harness only threads it.
78
+ */
79
+ export declare function formatDatastoreDegradationNotice(declaredCount: number, missing: readonly string[]): string;
80
+ /**
81
+ * The datastores prompt section (DD-005 SD-5, the skills-section
82
+ * precedent). Shared by both harnesses so the section text cannot drift
83
+ * (the sender-identity precedent). Two honest renderings (issue #325):
84
+ *
85
+ * - Healthy (`missingToolNames` empty or omitted — the Cursor harness
86
+ * always calls it this way: the Cursor SDK connects MCP itself, so
87
+ * that harness can never observe the live roster):
88
+ * `<available_datastores>` names the attached datastores, points the
89
+ * model at describe_datastore first, and carries a standing
90
+ * failure-disclosure instruction — the only mechanism that covers
91
+ * tools which connected but fail at call time (the WhatsApp-pilot
92
+ * outage shape).
93
+ * - Degraded (deep-agent only, from missingRecordTools against the
94
+ * connected roster): `<unavailable_datastores>` instead — the section
95
+ * must not promise tools the agent does not have. Names the declared
96
+ * datastores, states which record tools are missing, and instructs
97
+ * plain disclosure over improvisation.
98
+ */
99
+ export declare function formatDatastoresSection(datastoreUsages: DatastoreUsage[], missingToolNames?: readonly string[]): string;
@@ -22,8 +22,12 @@
22
22
  * OSS callers resolve as the local principal (T05 R2).
23
23
  *
24
24
  * Approval-free by construction (DD-001 SD-3): empty toolApprovals +
25
- * pinnedToolApprovals mean mergeApprovalPolicies emits no entries for
26
- * this server — zero classifier involvement. `discoveredCapabilitiesEmpty`
25
+ * pinnedToolApprovals + toolApprovalOverrides mean mergeApprovalPolicies
26
+ * emits no entries for this server — zero classifier involvement, and no
27
+ * proto surface can target it (the attachment has no McpServerUsage, and
28
+ * since issue #349 an agent's overrides are scoped to their own usage's
29
+ * server, so a same-named override elsewhere cannot reach this one).
30
+ * `discoveredCapabilitiesEmpty`
27
31
  * is false and the attachment has no McpServerUsage, so the connect
28
32
  * backfill (whose destructiveHint tightener would force-gate
29
33
  * delete_record — silently skipped on channels under UNATTENDED mode)
@@ -53,6 +57,7 @@ export function synthesizeDatastoreAttachment(datastoreUsages, options) {
53
57
  slug: DATASTORE_ATTACHMENT_SLUG,
54
58
  toolApprovals: [],
55
59
  pinnedToolApprovals: [],
60
+ toolApprovalOverrides: [],
56
61
  discoveredCapabilitiesEmpty: false,
57
62
  };
58
63
  if (options.bridgeEndpoint !== null && options.bridgeEndpoint !== "") {
@@ -77,25 +82,102 @@ export function synthesizeDatastoreAttachment(datastoreUsages, options) {
77
82
  };
78
83
  }
79
84
  /**
80
- * The `<available_datastores>` prompt section (DD-005 SD-5, the
81
- * skills-section precedent): names the attached datastores and points
82
- * the model at describe_datastore first. Shared by both harnesses so
83
- * the section text cannot drift (the sender-identity precedent).
85
+ * The five record tools the records roster always serves (DD-005; the
86
+ * mcp-server's records roster registers all five unconditionally for the
87
+ * agent audience — only the `org` argument shape varies by audience, see
88
+ * mcp-server/src/domains/records/tools.ts). Because the roster never
89
+ * legitimately narrows, any of these missing from the connected toolset
90
+ * means the store is degraded (issue #325) — the prompt section and the
91
+ * reconciliation both derive from this one list so they cannot drift.
84
92
  */
85
- export function formatDatastoresSection(datastoreUsages) {
86
- const slugs = datastoreUsages
93
+ export const EXPECTED_RECORD_TOOLS = [
94
+ "describe_datastore",
95
+ "find_records",
96
+ "insert_record",
97
+ "update_record",
98
+ "delete_record",
99
+ ];
100
+ /**
101
+ * Reconcile the record tools actually connected against the roster
102
+ * contract (issue #325). Returns the expected tools absent from
103
+ * `actualToolNames` — empty means healthy. Names are bare tool names
104
+ * exactly as reported by tools/list (the mcp-enabled-tools identity
105
+ * space); extraneous names are ignored.
106
+ */
107
+ export function missingRecordTools(actualToolNames) {
108
+ const present = new Set(actualToolNames);
109
+ return EXPECTED_RECORD_TOOLS.filter((name) => !present.has(name));
110
+ }
111
+ /**
112
+ * The operator-facing degradation notice (issue #325): pushed as a
113
+ * MESSAGE_SYSTEM row on the execution status so "declared N datastores,
114
+ * X/5 record tools connected" is visible without reading a transcript.
115
+ * Lives HERE with the rest of the datastore-attachment wording — the
116
+ * harness only threads it.
117
+ */
118
+ export function formatDatastoreDegradationNotice(declaredCount, missing) {
119
+ const connected = EXPECTED_RECORD_TOOLS.length - missing.length;
120
+ return (`Datastore record tools unavailable this turn: declared ` +
121
+ `${declaredCount} datastore(s), ${connected}/${EXPECTED_RECORD_TOOLS.length} ` +
122
+ `record tools connected (missing: ${missing.join(", ")}). The agent has ` +
123
+ `been instructed to disclose this instead of answering from memory.`);
124
+ }
125
+ /**
126
+ * The datastores prompt section (DD-005 SD-5, the skills-section
127
+ * precedent). Shared by both harnesses so the section text cannot drift
128
+ * (the sender-identity precedent). Two honest renderings (issue #325):
129
+ *
130
+ * - Healthy (`missingToolNames` empty or omitted — the Cursor harness
131
+ * always calls it this way: the Cursor SDK connects MCP itself, so
132
+ * that harness can never observe the live roster):
133
+ * `<available_datastores>` names the attached datastores, points the
134
+ * model at describe_datastore first, and carries a standing
135
+ * failure-disclosure instruction — the only mechanism that covers
136
+ * tools which connected but fail at call time (the WhatsApp-pilot
137
+ * outage shape).
138
+ * - Degraded (deep-agent only, from missingRecordTools against the
139
+ * connected roster): `<unavailable_datastores>` instead — the section
140
+ * must not promise tools the agent does not have. Names the declared
141
+ * datastores, states which record tools are missing, and instructs
142
+ * plain disclosure over improvisation.
143
+ */
144
+ export function formatDatastoresSection(datastoreUsages, missingToolNames = []) {
145
+ const entries = datastoreUsages
87
146
  .map((u) => u.datastoreRef?.slug)
88
- .filter((s) => !!s);
89
- const entries = slugs.map((slug) => `- ${slug}`);
147
+ .filter((s) => !!s)
148
+ .map((slug) => `- ${slug}`);
149
+ if (missingToolNames.length > 0) {
150
+ return [
151
+ "<unavailable_datastores>",
152
+ "This agent is configured to use the datastores listed below, but the",
153
+ "following record tools failed to connect this turn:",
154
+ missingToolNames.join(", ") + ".",
155
+ "Treat these datastores as unreachable for any operation that needs a",
156
+ "missing tool.",
157
+ "",
158
+ ...entries,
159
+ "",
160
+ "When the user's request depends on one of these datastores, tell them",
161
+ "plainly that the datastore cannot be reached right now. Never answer",
162
+ "from memory, guess, or improvise a substitute for what the datastore",
163
+ "would have returned.",
164
+ "</unavailable_datastores>",
165
+ ].join("\n");
166
+ }
90
167
  return [
91
168
  "<available_datastores>",
92
169
  "You have access to the following datastores through the record tools",
93
- "(describe_datastore, find_records, insert_record, update_record, delete_record).",
170
+ `(${EXPECTED_RECORD_TOOLS.join(", ")}).`,
94
171
  "Before your first operation against a datastore, call describe_datastore to",
95
172
  "learn its collections, field encodings, and which operations you are allowed",
96
173
  "to perform.",
97
174
  "",
98
175
  ...entries,
176
+ "",
177
+ "If any record tool is missing from your toolset or a record tool call",
178
+ "fails, the datastore is unreachable: tell the user plainly that you cannot",
179
+ "reach it right now, and do not answer from memory, guess, or improvise a",
180
+ "substitute for what it would have returned.",
99
181
  "</available_datastores>",
100
182
  ].join("\n");
101
183
  }
@@ -1 +1 @@
1
- {"version":3,"file":"datastore-attachment.js","sourceRoot":"","sources":["../../src/shared/datastore-attachment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,EAAE,UAAU,EAAqC,MAAM,6BAA6B,CAAC;AAE5F;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;AAExC;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAC3C,eAAiC,EACjC,OAAqC;IAErC,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,mEAAmE;IACnE,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,yBAAyB;QAC/B,aAAa,EAAE,EAAE;QACjB,mBAAmB,EAAE,EAAE;QACvB,2BAA2B,EAAE,KAAK;KACnC,CAAC;IAEF,IAAI,OAAO,CAAC,cAAc,KAAK,IAAI,IAAI,OAAO,CAAC,cAAc,KAAK,EAAE,EAAE,CAAC;QACrE,OAAO;YACL,GAAG,IAAI;YACP,cAAc,EAAE,MAAM;YACtB,GAAG,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,aAAa;YAC/D,OAAO,EAAE,OAAO,CAAC,UAAU,KAAK,IAAI,IAAI,OAAO,CAAC,UAAU,KAAK,EAAE;gBAC/D,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,UAAU,EAAE,EAAE;gBACnD,CAAC,CAAC,SAAS;SACd,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG,IAAI;QACP,cAAc,EAAE,OAAO;QACvB,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,CAAC,YAAY,CAAC;QACpB,GAAG,EAAE;YACH,kBAAkB,EAAE,SAAS;YAC7B,sBAAsB,EAAE,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC;SAC5D;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAiC;IACvE,MAAM,KAAK,GAAG,eAAe;SAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC;SAChC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO;QACL,wBAAwB;QACxB,sEAAsE;QACtE,kFAAkF;QAClF,6EAA6E;QAC7E,8EAA8E;QAC9E,aAAa;QACb,EAAE;QACF,GAAG,OAAO;QACV,yBAAyB;KAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"datastore-attachment.js","sourceRoot":"","sources":["../../src/shared/datastore-attachment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * HTTP error classification for side-channel proxy retries.
3
+ *
4
+ * The runner reaches stigmer-service's Side-Channel Proxy (`/v1/proxy/...`)
5
+ * over plain `fetch` from several clients — the checkpoint saver today;
6
+ * artifact storage, the LLM proxy, and the registry endpoint are candidates
7
+ * (stigmer/stigmer#468). This module is the one place that answers "is this
8
+ * HTTP failure worth retrying?", the `fetch` twin of grpc-retry.ts: it holds
9
+ * the classification policy only, kept small and separately tested. The
10
+ * bounded-backoff loop that consumes it lives with each client (the
11
+ * grpc-retry/status.ts split).
12
+ *
13
+ * The policy is grounded in what the proxy actually emits, not HTTP folklore.
14
+ * CheckpointerProxyController returns exactly four deterministic errors —
15
+ * 400 (malformed document), 403 (FGA deny), 404 (no such checkpoint), and
16
+ * 413 (the 4 MB cap) — and never a transient status. Transient failures
17
+ * reach the runner only as 5xx (Spring's error handler, ingress 502-504),
18
+ * 408/429 (infrastructure between runner and service), or as network-level
19
+ * fetch rejections. 401/403 stay terminal deliberately: retrying cannot fix
20
+ * an expired or rejected credential.
21
+ */
22
+ /**
23
+ * True for HTTP statuses that signal a transient condition worth retrying:
24
+ * 408 (request timeout), 429 (throttled), and all 5xx. Every other status is
25
+ * deterministic — the proxy's 4xx errors mean the same request will fail the
26
+ * same way forever.
27
+ */
28
+ export declare function isRetryableHttpStatus(status: number): boolean;
29
+ /**
30
+ * True for `fetch` rejections that signal a transient transport condition:
31
+ *
32
+ * - `TypeError` — undici's network-failure shape (`fetch failed`, with the
33
+ * ECONNREFUSED/ECONNRESET/DNS cause attached). A deterministic TypeError
34
+ * (e.g. a malformed URL) also matches, which is accepted: such a bug fails
35
+ * every attempt including the first test run, and the bounded budget caps
36
+ * the wasted retries at seconds.
37
+ * - `TimeoutError` — the rejection shape of `AbortSignal.timeout()`, i.e. a
38
+ * hung connection whose attempt we bounded ourselves.
39
+ *
40
+ * A manual abort (`AbortError`) is deliberately NOT retryable: the caller
41
+ * cancelled on purpose.
42
+ */
43
+ export declare function isRetryableFetchError(err: unknown): boolean;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * HTTP error classification for side-channel proxy retries.
3
+ *
4
+ * The runner reaches stigmer-service's Side-Channel Proxy (`/v1/proxy/...`)
5
+ * over plain `fetch` from several clients — the checkpoint saver today;
6
+ * artifact storage, the LLM proxy, and the registry endpoint are candidates
7
+ * (stigmer/stigmer#468). This module is the one place that answers "is this
8
+ * HTTP failure worth retrying?", the `fetch` twin of grpc-retry.ts: it holds
9
+ * the classification policy only, kept small and separately tested. The
10
+ * bounded-backoff loop that consumes it lives with each client (the
11
+ * grpc-retry/status.ts split).
12
+ *
13
+ * The policy is grounded in what the proxy actually emits, not HTTP folklore.
14
+ * CheckpointerProxyController returns exactly four deterministic errors —
15
+ * 400 (malformed document), 403 (FGA deny), 404 (no such checkpoint), and
16
+ * 413 (the 4 MB cap) — and never a transient status. Transient failures
17
+ * reach the runner only as 5xx (Spring's error handler, ingress 502-504),
18
+ * 408/429 (infrastructure between runner and service), or as network-level
19
+ * fetch rejections. 401/403 stay terminal deliberately: retrying cannot fix
20
+ * an expired or rejected credential.
21
+ */
22
+ /**
23
+ * True for HTTP statuses that signal a transient condition worth retrying:
24
+ * 408 (request timeout), 429 (throttled), and all 5xx. Every other status is
25
+ * deterministic — the proxy's 4xx errors mean the same request will fail the
26
+ * same way forever.
27
+ */
28
+ export function isRetryableHttpStatus(status) {
29
+ return status === 408 || status === 429 || status >= 500;
30
+ }
31
+ /**
32
+ * True for `fetch` rejections that signal a transient transport condition:
33
+ *
34
+ * - `TypeError` — undici's network-failure shape (`fetch failed`, with the
35
+ * ECONNREFUSED/ECONNRESET/DNS cause attached). A deterministic TypeError
36
+ * (e.g. a malformed URL) also matches, which is accepted: such a bug fails
37
+ * every attempt including the first test run, and the bounded budget caps
38
+ * the wasted retries at seconds.
39
+ * - `TimeoutError` — the rejection shape of `AbortSignal.timeout()`, i.e. a
40
+ * hung connection whose attempt we bounded ourselves.
41
+ *
42
+ * A manual abort (`AbortError`) is deliberately NOT retryable: the caller
43
+ * cancelled on purpose.
44
+ */
45
+ export function isRetryableFetchError(err) {
46
+ if (err instanceof TypeError)
47
+ return true;
48
+ return err instanceof Error && err.name === "TimeoutError";
49
+ }
50
+ //# sourceMappingURL=http-retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-retry.js","sourceRoot":"","sources":["../../src/shared/http-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAY;IAChD,IAAI,GAAG,YAAY,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,275 @@
1
+ /**
2
+ * LLM provider-backend utilities — pure routing helpers for serving a
3
+ * provider's models through an alternative cloud backend (GCP Vertex AI,
4
+ * AWS Bedrock, Microsoft Foundry) instead of the provider's public API.
5
+ *
6
+ * Layering mirrors `llm-proxy.ts`: this module is pure string/config
7
+ * utilities with no LangChain or SDK dependency. Consumers: the runner
8
+ * factories run `preflightLlmBackends` at startup, and `model-client.ts`
9
+ * resolves the backend and translates model ids at construction time; see
10
+ * `__tests__/vertex-seam.test.ts` for the pinned seam behavior.
11
+ *
12
+ * Design decision record: stigmer-cloud
13
+ * `_projects/2026-08/20260809.01.multi-cloud-llm-provider-endpoints/`
14
+ * `design-decisions/001-provider-backends.md`.
15
+ */
16
+ import type { LlmProvider } from "./llm-proxy.js";
17
+ /** Env var selecting where Anthropic models are served. */
18
+ export declare const ANTHROPIC_BACKEND_ENV = "STIGMER_ANTHROPIC_BACKEND";
19
+ /** Env var selecting where OpenAI models are served. */
20
+ export declare const OPENAI_BACKEND_ENV = "STIGMER_OPENAI_BACKEND";
21
+ /** Operator guide for backend configuration; the single copy of this URL. */
22
+ export declare const BACKEND_DOC_URL = "https://docs.stigmer.ai/guides/runners/model-backends";
23
+ /**
24
+ * Backends implemented in this build. Anthropic's values name the serving
25
+ * SERVICE, not the cloud (`foundry` is Microsoft Foundry, the Azure
26
+ * service that hosts Claude — "azure" would collide with the unrelated
27
+ * Azure OpenAI service). The design vocabulary also reserves `azure`
28
+ * (OpenAI); until that adapter lands — contingent on OpenAI models
29
+ * entering the native catalog — selecting it is a distinct "recognized
30
+ * but not implemented" failure, never a silent fallback to the public
31
+ * API, which would quietly route traffic outside the compliance boundary
32
+ * the operator asked for.
33
+ */
34
+ export type AnthropicBackend = "public" | "vertex" | "bedrock" | "foundry";
35
+ export type OpenAiBackend = "public";
36
+ /**
37
+ * Result of parsing a backend env var. `message` is the operator-facing
38
+ * text; it names the exact var, the bad value, and what is supported, and
39
+ * is the single copy of that text (preflight, model construction, and any
40
+ * future consumer all surface this same string).
41
+ */
42
+ export type BackendParseResult<B> = {
43
+ readonly ok: true;
44
+ readonly backend: B;
45
+ } | {
46
+ readonly ok: false;
47
+ readonly message: string;
48
+ };
49
+ /** Parse `STIGMER_ANTHROPIC_BACKEND` (unset → `public`). */
50
+ export declare function parseAnthropicBackend(env?: NodeJS.ProcessEnv): BackendParseResult<AnthropicBackend>;
51
+ /** Parse `STIGMER_OPENAI_BACKEND` (unset → `public`). */
52
+ export declare function parseOpenAiBackend(env?: NodeJS.ProcessEnv): BackendParseResult<OpenAiBackend>;
53
+ /**
54
+ * Resolve the Anthropic backend for model construction, throwing the
55
+ * parser's message on an invalid value.
56
+ *
57
+ * The runner factories run {@link preflightLlmBackends} at startup, so in a
58
+ * normally-booted process this never throws — the throw is defense in depth
59
+ * for paths that construct models without the factories (tests, direct
60
+ * library use), keeping "invalid value" impossible to ride past silently.
61
+ */
62
+ export declare function resolveAnthropicBackend(env?: NodeJS.ProcessEnv): AnthropicBackend;
63
+ /**
64
+ * Static prerequisite check for the vertex backend, or null when satisfied.
65
+ *
66
+ * Region is the ONE hard requirement checkable without I/O: the Vertex SDK
67
+ * throws without it. Project id and credentials are deliberately NOT
68
+ * checked here — both are legitimately resolvable at request time from
69
+ * Application Default Credentials (workload identity, metadata server,
70
+ * gcloud login), so requiring env vars for them would reject perfectly
71
+ * valid GCP deployments. Runtime credential failures get actionable
72
+ * classification in `model-error.ts` instead.
73
+ */
74
+ export declare function checkVertexPrerequisites(env?: NodeJS.ProcessEnv): string | null;
75
+ /** Operator override map: canonical id -> exact Bedrock id, consulted first. */
76
+ export declare const BEDROCK_MODEL_MAP_ENV = "STIGMER_BEDROCK_MODEL_MAP";
77
+ /** Inference-profile geography prefix (`us`, `eu`, `global`, …), no default. */
78
+ export declare const BEDROCK_INFERENCE_PREFIX_ENV = "STIGMER_BEDROCK_INFERENCE_PREFIX";
79
+ /**
80
+ * Static prerequisite check for the bedrock backend, or null when satisfied.
81
+ *
82
+ * AWS_REGION is REQUIRED even though the Bedrock SDK would default it to
83
+ * us-east-1 (pinned by bedrock-seam.test.ts): for a deployment-controlled
84
+ * data-residency feature, silently routing model traffic to a US region on
85
+ * a missing var is exactly the failure backends exist to prevent. Same
86
+ * shape as vertex's CLOUD_ML_REGION requirement. Credentials are
87
+ * deliberately NOT checked — the AWS chain (env keys, IRSA / instance
88
+ * metadata, config files, AWS_BEARER_TOKEN_BEDROCK) legitimately resolves
89
+ * at request time; requiring env keys would reject valid deployments.
90
+ * Runtime credential failures get actionable classification in
91
+ * `model-error.ts` instead.
92
+ *
93
+ * A malformed STIGMER_BEDROCK_MODEL_MAP is also fatal here: it is
94
+ * deployment-static, and finding out at the first model call would fail
95
+ * executions a boot check could have refused.
96
+ */
97
+ export declare function checkBedrockPrerequisites(env?: NodeJS.ProcessEnv): string | null;
98
+ type ModelMapParseResult = {
99
+ readonly ok: true;
100
+ readonly map: ReadonlyMap<string, string>;
101
+ } | {
102
+ readonly ok: false;
103
+ readonly message: string;
104
+ };
105
+ /**
106
+ * Parse `STIGMER_BEDROCK_MODEL_MAP`: comma-separated `canonical=bedrockId`
107
+ * pairs, e.g. "claude-sonnet-4-6=us.anthropic.claude-sonnet-4-6-v1:0".
108
+ */
109
+ export declare function parseBedrockModelMap(env?: NodeJS.ProcessEnv): ModelMapParseResult;
110
+ /**
111
+ * Operator override map: canonical id -> Foundry deployment name, consulted
112
+ * first. Named DEPLOYMENT_MAP, not MODEL_MAP, because the target is Azure's
113
+ * term of art — the operator-chosen deployment name, not another model id.
114
+ */
115
+ export declare const FOUNDRY_DEPLOYMENT_MAP_ENV = "STIGMER_FOUNDRY_DEPLOYMENT_MAP";
116
+ /** The Foundry resource name (SDK-native; builds the endpoint host). */
117
+ export declare const FOUNDRY_RESOURCE_ENV = "ANTHROPIC_FOUNDRY_RESOURCE";
118
+ /** Full endpoint override (SDK-native; mutually exclusive with resource). */
119
+ export declare const FOUNDRY_BASE_URL_ENV = "ANTHROPIC_FOUNDRY_BASE_URL";
120
+ /**
121
+ * Parse `STIGMER_FOUNDRY_DEPLOYMENT_MAP`: comma-separated
122
+ * `canonical=deploymentName` pairs, e.g.
123
+ * "claude-sonnet-4-6=my-sonnet-deployment".
124
+ */
125
+ export declare function parseFoundryDeploymentMap(env?: NodeJS.ProcessEnv): ModelMapParseResult;
126
+ /**
127
+ * Static prerequisite check for the foundry backend, or null when satisfied.
128
+ *
129
+ * The endpoint is the ONE hard requirement checkable without I/O: the
130
+ * Foundry SDK's constructor throws without exactly one of the resource
131
+ * name or a full base URL, so both halves of its contract (missing AND
132
+ * both-set) are refused here at boot with catalog messages instead of at
133
+ * the first model call. Credentials are deliberately NOT checked —
134
+ * ANTHROPIC_FOUNDRY_API_KEY is optional by design (without it the adapter
135
+ * authenticates through Microsoft Entra ID via the Azure credential chain,
136
+ * which resolves at request time exactly like Vertex ADC and the AWS
137
+ * chain), so requiring it would reject correctly-configured keyless
138
+ * deployments. Runtime credential failures get actionable classification
139
+ * in `model-error.ts` instead.
140
+ *
141
+ * A malformed STIGMER_FOUNDRY_DEPLOYMENT_MAP is also fatal here: it is
142
+ * deployment-static, and finding out at the first model call would fail
143
+ * executions a boot check could have refused.
144
+ */
145
+ export declare function checkFoundryPrerequisites(env?: NodeJS.ProcessEnv): string | null;
146
+ /**
147
+ * Check that direct-mode (unproxied) calls to `provider` have a usable
148
+ * credential path, or return the operator message describing what is
149
+ * missing. Null means "a request can authenticate":
150
+ *
151
+ * - `anthropic`: a non-blank `ANTHROPIC_API_KEY`, or any non-public backend
152
+ * (vertex authenticates through Application Default Credentials, and
153
+ * `ChatAnthropic` waives its API-key requirement when `createClient` is
154
+ * supplied — pinned by vertex-seam.test.ts).
155
+ * - `openai`: a non-blank `OPENAI_API_KEY`. The message deliberately offers
156
+ * no backend remedy until the azure adapter ships — advertising
157
+ * STIGMER_OPENAI_BACKEND today would point the operator at a value that
158
+ * fails with "not implemented in this build".
159
+ *
160
+ * An invalid backend value also returns null: `resolveAnthropicBackend` at
161
+ * model construction owns that condition's precise catalog message, and
162
+ * reporting it here too would create a second copy that can drift.
163
+ *
164
+ * This is the single copy of the "do we have a credential?" question. The
165
+ * reaction stays with each caller, because the right one differs per site:
166
+ * `call-llm.ts` raises a non-retryable LLM_MISSING_API_KEY, tool
167
+ * classification fails closed (every tool gated), and Cursor tier-2
168
+ * extraction skips to "no structured output". Callers consult it only when
169
+ * no proxy is configured — a proxied deployment authenticates with
170
+ * STIGMER_TOKEN and holds no provider credentials at all.
171
+ */
172
+ export declare function checkDirectCredentials(provider: LlmProvider, env?: NodeJS.ProcessEnv): string | null;
173
+ export interface LlmBackendPreflight {
174
+ /** Fatal, actionable operator message; null when the config is usable. */
175
+ readonly error: string | null;
176
+ /** Non-fatal operator notices (e.g. proxy overrides backend selection). */
177
+ readonly warnings: readonly string[];
178
+ }
179
+ /**
180
+ * Validate the deployment's backend configuration once, at startup.
181
+ *
182
+ * Called by the runner factories (`createStigmerRunner` /
183
+ * `createStigmerRunnerManager`) — the construction boundary every entry
184
+ * path shares (static, pool, and manager modes in main.ts, plus in-process
185
+ * embedders of `@stigmer/runner`) — so a misconfigured deployment refuses
186
+ * to accept work instead of failing every execution mid-flight. Mirrors the
187
+ * `preflightNodeRuntime` pattern: pure check in, operator message out.
188
+ *
189
+ * Precedence rule: when `STIGMER_PROXY_ENDPOINT` is set the proxy owns
190
+ * provider routing and backend vars are inert, so they downgrade to
191
+ * warnings (never silence, but never fail a proxied fleet over an ignored
192
+ * var either). Without a proxy, invalid values and missing prerequisites
193
+ * are fatal.
194
+ */
195
+ export declare function preflightLlmBackends(env?: NodeJS.ProcessEnv): LlmBackendPreflight;
196
+ /**
197
+ * Translate a canonical Anthropic API model id into Vertex AI's form.
198
+ *
199
+ * The model registry serves two id shapes, and Vertex treats them
200
+ * differently (platform.claude.com "Model IDs and versions"):
201
+ *
202
+ * - Pre-4.6 models carry a snapshot date, and Vertex separates it with `@`
203
+ * instead of `-`: "claude-sonnet-4-5-20250929" -> "claude-sonnet-4-5@20250929".
204
+ * - 4.6-generation and later ids are dateless AND canonical on every
205
+ * platform: "claude-sonnet-4-6" is used verbatim on Vertex. Appending a
206
+ * date to them 404s — a real bug shipped by other integrations (Dify
207
+ * langgenius/dify-official-plugins#2905, Roo-Code #11625) — so dateless
208
+ * ids MUST pass through untouched.
209
+ *
210
+ * The translated id is Vertex wire detail only: it goes into the request
211
+ * URL path and must never escape the adapter into usage metrics or pricing,
212
+ * which key on the canonical id (the canonical-id invariant in the design
213
+ * decision record).
214
+ *
215
+ * Already-translated ids (`name@date`) and Bedrock-shaped ids
216
+ * (`anthropic.…-v1:0`) don't match the trailing-date pattern, so a second
217
+ * pass is a no-op by construction.
218
+ */
219
+ export declare function toVertexModelId(apiModelId: string): string;
220
+ /**
221
+ * Translate a canonical Anthropic API model id into Bedrock's form, in
222
+ * three layers (approved design, T04) — each a deployment-level knob:
223
+ *
224
+ * 1. `STIGMER_BEDROCK_MODEL_MAP` override, consulted first: the escape
225
+ * hatch for ids the deterministic rule cannot derive (Bedrock ids for
226
+ * dateless canonicals may carry AWS-side snapshot dates we cannot know).
227
+ * 2. `STIGMER_BEDROCK_INFERENCE_PREFIX` (e.g. "us", "eu", "global"),
228
+ * applied to the derived id. Newer Claude models on Bedrock are invoked
229
+ * through geography-prefixed inference profiles (AWS lists the base id's
230
+ * in-region endpoint as N/A) — but WHICH geography is a deployment
231
+ * decision (data residency), underivable from the model id, and never
232
+ * defaulted: a missing prefix yields the bare id, and if AWS rejects it
233
+ * with its "use an inference profile" error, model-error.ts translates
234
+ * that into "set ${BEDROCK_INFERENCE_PREFIX_ENV}".
235
+ * 3. Deterministic rule: `anthropic.{canonical}-v1:0` — verified against
236
+ * AWS's model catalog for the registry's dated ids (e.g.
237
+ * claude-sonnet-4-5-20250929 -> anthropic.claude-sonnet-4-5-20250929-v1:0).
238
+ *
239
+ * Like the Vertex translation, the result is wire detail only: it rides in
240
+ * the request URL and must never escape the adapter into usage metrics or
241
+ * pricing, which key on the canonical id (the canonical-id invariant).
242
+ *
243
+ * Throws the catalog message on a malformed map — defense in depth for
244
+ * paths that construct models without the factories; a normally-booted
245
+ * runner already refused to start in `checkBedrockPrerequisites`.
246
+ */
247
+ export declare function toBedrockModelId(apiModelId: string, env?: NodeJS.ProcessEnv): string;
248
+ /**
249
+ * Translate a canonical Anthropic API model id into a Microsoft Foundry
250
+ * deployment name, in two layers (approved design, T05):
251
+ *
252
+ * 1. `STIGMER_FOUNDRY_DEPLOYMENT_MAP` override, consulted first: Foundry
253
+ * routes by DEPLOYMENT NAME, and the portal lets operators name
254
+ * deployments anything ("my-sonnet-deployment"). This is the escape
255
+ * hatch for those custom names.
256
+ * 2. Deterministic rule: strip a trailing `-YYYYMMDD` snapshot date —
257
+ * Foundry's DEFAULT deployment names are the dateless Claude ids
258
+ * (claude-sonnet-4-5-20250929 -> claude-sonnet-4-5; dateless ids pass
259
+ * through unchanged). Verified against Anthropic's published Foundry
260
+ * model table: every native-catalog id maps onto a real default
261
+ * deployment name. Note this is the INVERSE of toVertexModelId, which
262
+ * keeps the date and reseparates it with `@`.
263
+ *
264
+ * Like the other translations, the result is wire detail only: it rides in
265
+ * the request body's `model` field (Foundry keeps it in the body — see
266
+ * foundry-seam.test.ts — unlike Vertex/Bedrock, which move it into the URL
267
+ * path) and must never escape the adapter into usage metrics or pricing,
268
+ * which key on the canonical id (the canonical-id invariant).
269
+ *
270
+ * Throws the catalog message on a malformed map — defense in depth for
271
+ * paths that construct models without the factories; a normally-booted
272
+ * runner already refused to start in `checkFoundryPrerequisites`.
273
+ */
274
+ export declare function toFoundryDeploymentName(apiModelId: string, env?: NodeJS.ProcessEnv): string;
275
+ export {};