@cogenta/agents 0.2.1 → 0.5.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 (242) hide show
  1. package/dist/agents/builtins.d.ts +51 -0
  2. package/dist/agents/builtins.d.ts.map +1 -0
  3. package/dist/agents/builtins.js +190 -0
  4. package/dist/agents/builtins.js.map +1 -0
  5. package/dist/agents/orchestrator.d.ts +98 -0
  6. package/dist/agents/orchestrator.d.ts.map +1 -0
  7. package/dist/agents/orchestrator.js +286 -0
  8. package/dist/agents/orchestrator.js.map +1 -0
  9. package/dist/agents/store.d.ts +71 -0
  10. package/dist/agents/store.d.ts.map +1 -0
  11. package/dist/agents/store.js +211 -0
  12. package/dist/agents/store.js.map +1 -0
  13. package/dist/agents/types.d.ts +10 -0
  14. package/dist/agents/types.d.ts.map +1 -1
  15. package/dist/assist/agent-identity.d.ts +44 -0
  16. package/dist/assist/agent-identity.d.ts.map +1 -0
  17. package/dist/assist/agent-identity.js +136 -0
  18. package/dist/assist/agent-identity.js.map +1 -0
  19. package/dist/assist/chat.d.ts +2 -0
  20. package/dist/assist/chat.d.ts.map +1 -1
  21. package/dist/assist/chat.js +14 -5
  22. package/dist/assist/chat.js.map +1 -1
  23. package/dist/assist/classify.d.ts +3 -2
  24. package/dist/assist/classify.d.ts.map +1 -1
  25. package/dist/assist/classify.js +30 -11
  26. package/dist/assist/classify.js.map +1 -1
  27. package/dist/assist/faq.d.ts +3 -2
  28. package/dist/assist/faq.d.ts.map +1 -1
  29. package/dist/assist/faq.js +31 -13
  30. package/dist/assist/faq.js.map +1 -1
  31. package/dist/assist/runtime.d.ts +8 -2
  32. package/dist/assist/runtime.d.ts.map +1 -1
  33. package/dist/assist/runtime.js +2 -2
  34. package/dist/assist/runtime.js.map +1 -1
  35. package/dist/assist/toolset.d.ts +10 -0
  36. package/dist/assist/toolset.d.ts.map +1 -1
  37. package/dist/assist/toolset.js +36 -8
  38. package/dist/assist/toolset.js.map +1 -1
  39. package/dist/assist/usage.d.ts +58 -0
  40. package/dist/assist/usage.d.ts.map +1 -0
  41. package/dist/assist/usage.js +53 -0
  42. package/dist/assist/usage.js.map +1 -0
  43. package/dist/assist/writing.d.ts +10 -9
  44. package/dist/assist/writing.d.ts.map +1 -1
  45. package/dist/assist/writing.js +126 -58
  46. package/dist/assist/writing.js.map +1 -1
  47. package/dist/audit/with-audit.d.ts +13 -0
  48. package/dist/audit/with-audit.d.ts.map +1 -1
  49. package/dist/audit/with-audit.js +6 -0
  50. package/dist/audit/with-audit.js.map +1 -1
  51. package/dist/autonomy/levels.d.ts +37 -0
  52. package/dist/autonomy/levels.d.ts.map +1 -0
  53. package/dist/autonomy/levels.js +51 -0
  54. package/dist/autonomy/levels.js.map +1 -0
  55. package/dist/conversations/store.d.ts +62 -0
  56. package/dist/conversations/store.d.ts.map +1 -0
  57. package/dist/conversations/store.js +0 -0
  58. package/dist/conversations/store.js.map +1 -0
  59. package/dist/identity/context.d.ts +8 -0
  60. package/dist/identity/context.d.ts.map +1 -1
  61. package/dist/identity/context.js +19 -4
  62. package/dist/identity/context.js.map +1 -1
  63. package/dist/identity/markdown.d.ts +38 -0
  64. package/dist/identity/markdown.d.ts.map +1 -0
  65. package/dist/identity/markdown.js +85 -0
  66. package/dist/identity/markdown.js.map +1 -0
  67. package/dist/index.d.ts +62 -5
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +33 -3
  70. package/dist/index.js.map +1 -1
  71. package/dist/progress/job-store.d.ts +41 -0
  72. package/dist/progress/job-store.d.ts.map +1 -0
  73. package/dist/progress/job-store.js +44 -0
  74. package/dist/progress/job-store.js.map +1 -0
  75. package/dist/progress/types.d.ts +21 -0
  76. package/dist/progress/types.d.ts.map +1 -0
  77. package/dist/progress/types.js +3 -0
  78. package/dist/progress/types.js.map +1 -0
  79. package/dist/prompts/render.d.ts +23 -0
  80. package/dist/prompts/render.d.ts.map +1 -0
  81. package/dist/prompts/render.js +35 -0
  82. package/dist/prompts/render.js.map +1 -0
  83. package/dist/prompts/seeds.d.ts +34 -0
  84. package/dist/prompts/seeds.d.ts.map +1 -0
  85. package/dist/prompts/seeds.js +166 -0
  86. package/dist/prompts/seeds.js.map +1 -0
  87. package/dist/prompts/store.d.ts +8 -0
  88. package/dist/prompts/store.d.ts.map +1 -0
  89. package/dist/prompts/store.js +153 -0
  90. package/dist/prompts/store.js.map +1 -0
  91. package/dist/prompts/types.d.ts +51 -0
  92. package/dist/prompts/types.d.ts.map +1 -0
  93. package/dist/prompts/types.js +24 -0
  94. package/dist/prompts/types.js.map +1 -0
  95. package/dist/providers/anthropic.d.ts +26 -3
  96. package/dist/providers/anthropic.d.ts.map +1 -1
  97. package/dist/providers/anthropic.js +60 -12
  98. package/dist/providers/anthropic.js.map +1 -1
  99. package/dist/providers/catalog.d.ts +41 -0
  100. package/dist/providers/catalog.d.ts.map +1 -0
  101. package/dist/providers/catalog.js +85 -0
  102. package/dist/providers/catalog.js.map +1 -0
  103. package/dist/providers/content-parts.d.ts +12 -0
  104. package/dist/providers/content-parts.d.ts.map +1 -0
  105. package/dist/providers/content-parts.js +18 -0
  106. package/dist/providers/content-parts.js.map +1 -0
  107. package/dist/providers/defaults.d.ts +44 -0
  108. package/dist/providers/defaults.d.ts.map +1 -0
  109. package/dist/providers/defaults.js +72 -0
  110. package/dist/providers/defaults.js.map +1 -0
  111. package/dist/providers/google.d.ts +20 -3
  112. package/dist/providers/google.d.ts.map +1 -1
  113. package/dist/providers/google.js +53 -12
  114. package/dist/providers/google.js.map +1 -1
  115. package/dist/providers/openai.d.ts +36 -4
  116. package/dist/providers/openai.d.ts.map +1 -1
  117. package/dist/providers/openai.js +113 -21
  118. package/dist/providers/openai.js.map +1 -1
  119. package/dist/providers/registry.d.ts +38 -21
  120. package/dist/providers/registry.d.ts.map +1 -1
  121. package/dist/providers/registry.js +64 -8
  122. package/dist/providers/registry.js.map +1 -1
  123. package/dist/providers/request-signal.d.ts +18 -0
  124. package/dist/providers/request-signal.d.ts.map +1 -0
  125. package/dist/providers/request-signal.js +21 -0
  126. package/dist/providers/request-signal.js.map +1 -0
  127. package/dist/providers/resolve.d.ts +13 -0
  128. package/dist/providers/resolve.d.ts.map +1 -0
  129. package/dist/providers/resolve.js +30 -0
  130. package/dist/providers/resolve.js.map +1 -0
  131. package/dist/providers/store.d.ts +70 -0
  132. package/dist/providers/store.d.ts.map +1 -0
  133. package/dist/providers/store.js +308 -0
  134. package/dist/providers/store.js.map +1 -0
  135. package/dist/providers/tool-names.d.ts +9 -0
  136. package/dist/providers/tool-names.d.ts.map +1 -0
  137. package/dist/providers/tool-names.js +56 -0
  138. package/dist/providers/tool-names.js.map +1 -0
  139. package/dist/providers/types.d.ts +87 -3
  140. package/dist/providers/types.d.ts.map +1 -1
  141. package/dist/rag/reference-documents/ingest.d.ts +22 -0
  142. package/dist/rag/reference-documents/ingest.d.ts.map +1 -0
  143. package/dist/rag/reference-documents/ingest.js +69 -0
  144. package/dist/rag/reference-documents/ingest.js.map +1 -0
  145. package/dist/rag/reference-documents/store.d.ts +23 -0
  146. package/dist/rag/reference-documents/store.d.ts.map +1 -0
  147. package/dist/rag/reference-documents/store.js +140 -0
  148. package/dist/rag/reference-documents/store.js.map +1 -0
  149. package/dist/rag/reference-documents/types.d.ts +52 -0
  150. package/dist/rag/reference-documents/types.d.ts.map +1 -0
  151. package/dist/rag/reference-documents/types.js +32 -0
  152. package/dist/rag/reference-documents/types.js.map +1 -0
  153. package/dist/runtime/loop.d.ts +29 -7
  154. package/dist/runtime/loop.d.ts.map +1 -1
  155. package/dist/runtime/loop.js +209 -44
  156. package/dist/runtime/loop.js.map +1 -1
  157. package/dist/runtime/retry.d.ts +2 -0
  158. package/dist/runtime/retry.d.ts.map +1 -1
  159. package/dist/runtime/retry.js +1 -0
  160. package/dist/runtime/retry.js.map +1 -1
  161. package/dist/runtime/types.d.ts +14 -3
  162. package/dist/runtime/types.d.ts.map +1 -1
  163. package/dist/site-plan/analyse-brief.d.ts +8 -0
  164. package/dist/site-plan/analyse-brief.d.ts.map +1 -1
  165. package/dist/site-plan/analyse-brief.js +17 -8
  166. package/dist/site-plan/analyse-brief.js.map +1 -1
  167. package/dist/site-plan/approval.d.ts +2 -2
  168. package/dist/site-plan/approval.d.ts.map +1 -1
  169. package/dist/site-plan/approval.js +34 -4
  170. package/dist/site-plan/approval.js.map +1 -1
  171. package/dist/site-plan/content-model.d.ts +14 -0
  172. package/dist/site-plan/content-model.d.ts.map +1 -1
  173. package/dist/site-plan/content-model.js +51 -9
  174. package/dist/site-plan/content-model.js.map +1 -1
  175. package/dist/site-plan/demo-content.d.ts.map +1 -1
  176. package/dist/site-plan/demo-content.js +1 -4
  177. package/dist/site-plan/demo-content.js.map +1 -1
  178. package/dist/site-plan/propose-plan.d.ts +10 -0
  179. package/dist/site-plan/propose-plan.d.ts.map +1 -1
  180. package/dist/site-plan/propose-plan.js +25 -1
  181. package/dist/site-plan/propose-plan.js.map +1 -1
  182. package/dist/site-plan/site-context.d.ts +81 -0
  183. package/dist/site-plan/site-context.d.ts.map +1 -0
  184. package/dist/site-plan/site-context.js +76 -0
  185. package/dist/site-plan/site-context.js.map +1 -0
  186. package/dist/site-plan/skin-candidates.d.ts +13 -1
  187. package/dist/site-plan/skin-candidates.d.ts.map +1 -1
  188. package/dist/site-plan/skin-candidates.js +15 -0
  189. package/dist/site-plan/skin-candidates.js.map +1 -1
  190. package/dist/site-plan/structural-gaps.d.ts +32 -0
  191. package/dist/site-plan/structural-gaps.d.ts.map +1 -0
  192. package/dist/site-plan/structural-gaps.js +77 -0
  193. package/dist/site-plan/structural-gaps.js.map +1 -0
  194. package/dist/site-plan/types.d.ts +7 -0
  195. package/dist/site-plan/types.d.ts.map +1 -1
  196. package/dist/skills/frontmatter.d.ts +19 -1
  197. package/dist/skills/frontmatter.d.ts.map +1 -1
  198. package/dist/skills/frontmatter.js +29 -5
  199. package/dist/skills/frontmatter.js.map +1 -1
  200. package/dist/skills/library.d.ts +133 -0
  201. package/dist/skills/library.d.ts.map +1 -0
  202. package/dist/skills/library.js +332 -0
  203. package/dist/skills/library.js.map +1 -0
  204. package/dist/skills/types.d.ts +8 -1
  205. package/dist/skills/types.d.ts.map +1 -1
  206. package/dist/skin/generate.d.ts +22 -1
  207. package/dist/skin/generate.d.ts.map +1 -1
  208. package/dist/skin/generate.js +60 -5
  209. package/dist/skin/generate.js.map +1 -1
  210. package/dist/theme-creator/propose-theme.d.ts +83 -0
  211. package/dist/theme-creator/propose-theme.d.ts.map +1 -0
  212. package/dist/theme-creator/propose-theme.js +234 -0
  213. package/dist/theme-creator/propose-theme.js.map +1 -0
  214. package/dist/tools/core/agent-delegate.d.ts +8 -5
  215. package/dist/tools/core/agent-delegate.d.ts.map +1 -1
  216. package/dist/tools/core/agent-delegate.js +16 -6
  217. package/dist/tools/core/agent-delegate.js.map +1 -1
  218. package/dist/tools/core/content-browse.d.ts +74 -0
  219. package/dist/tools/core/content-browse.d.ts.map +1 -0
  220. package/dist/tools/core/content-browse.js +63 -0
  221. package/dist/tools/core/content-browse.js.map +1 -0
  222. package/dist/tools/core/content-schema.d.ts +86 -0
  223. package/dist/tools/core/content-schema.d.ts.map +1 -0
  224. package/dist/tools/core/content-schema.js +83 -0
  225. package/dist/tools/core/content-schema.js.map +1 -0
  226. package/dist/tools/core/deps-scan.d.ts +25 -0
  227. package/dist/tools/core/deps-scan.d.ts.map +1 -0
  228. package/dist/tools/core/deps-scan.js +85 -0
  229. package/dist/tools/core/deps-scan.js.map +1 -0
  230. package/dist/tools/core/media.d.ts +18 -2
  231. package/dist/tools/core/media.d.ts.map +1 -1
  232. package/dist/tools/core/media.js +8 -2
  233. package/dist/tools/core/media.js.map +1 -1
  234. package/dist/tools/core/not-found-log.d.ts +44 -0
  235. package/dist/tools/core/not-found-log.d.ts.map +1 -0
  236. package/dist/tools/core/not-found-log.js +32 -0
  237. package/dist/tools/core/not-found-log.js.map +1 -0
  238. package/dist/tools/core/redirects.d.ts +51 -0
  239. package/dist/tools/core/redirects.d.ts.map +1 -0
  240. package/dist/tools/core/redirects.js +50 -0
  241. package/dist/tools/core/redirects.js.map +1 -0
  242. package/package.json +6 -4
@@ -1,4 +1,7 @@
1
1
  import { CogentaError } from '@cogenta/core';
2
+ import { textOnlyContent } from './content-parts.js';
3
+ import { requestSignalWithTimeout } from './request-signal.js';
4
+ import { createToolNameDecoder, encodeToolName } from './tool-names.js';
2
5
  const DEFAULT_BASE_URL = 'https://api.openai.com/v1/chat/completions';
3
6
  const STOP_REASON = {
4
7
  stop: 'end_turn',
@@ -6,6 +9,25 @@ const STOP_REASON = {
6
9
  length: 'max_tokens',
7
10
  content_filter: 'stop_sequence',
8
11
  };
12
+ /**
13
+ * A plain string is passed through unchanged (byte-for-byte identical wire
14
+ * shape to before this adapter supported images); an array of
15
+ * `ChatContentPart` becomes OpenAI's multimodal content-part array, with
16
+ * each image re-encoded as a `data:` URL — the only form the Chat
17
+ * Completions API accepts for an inline image.
18
+ */
19
+ function toOpenAiContent(content) {
20
+ if (content === undefined)
21
+ return null;
22
+ if (typeof content === 'string')
23
+ return content;
24
+ return content.map((part) => part.type === 'text'
25
+ ? { type: 'text', text: part.text }
26
+ : {
27
+ type: 'image_url',
28
+ image_url: { url: `data:${part.mediaType};base64,${part.data}` },
29
+ });
30
+ }
9
31
  function toOpenAiMessage(message) {
10
32
  if (message.role === 'tool') {
11
33
  if (message.toolCallId === undefined) {
@@ -15,25 +37,34 @@ function toOpenAiMessage(message) {
15
37
  hint: "Set toolCallId to the id the model's tool call carried.",
16
38
  });
17
39
  }
18
- return { role: 'tool', content: message.content ?? '', tool_call_id: message.toolCallId };
40
+ return {
41
+ role: 'tool',
42
+ content: textOnlyContent(message.content) ?? '',
43
+ tool_call_id: message.toolCallId,
44
+ };
19
45
  }
20
46
  const toolCalls = message.toolCalls ?? [];
21
47
  return {
22
48
  role: message.role,
23
- content: message.content ?? null,
49
+ content: toOpenAiContent(message.content),
24
50
  ...(toolCalls.length === 0
25
51
  ? {}
26
52
  : {
27
53
  tool_calls: toolCalls.map((call) => ({
28
54
  id: call.id,
29
55
  type: 'function',
30
- function: { name: call.name, arguments: JSON.stringify(call.input) },
56
+ function: { name: encodeToolName(call.name), arguments: JSON.stringify(call.input) },
31
57
  })),
32
58
  }),
33
59
  };
34
60
  }
35
- /** Pure — no network. */
36
- export function buildOpenAiRequest(request) {
61
+ /**
62
+ * Pure — no network. `fallbackMaxTokens` is the client's own resolved
63
+ * `maxOutputTokens` (the admin's per-provider value, or the site-wide
64
+ * default) — applied only when `request.maxTokens` itself is absent.
65
+ * Required, not defaulted — see `buildAnthropicRequest`'s own doc comment.
66
+ */
67
+ export function buildOpenAiRequest(request, fallbackMaxTokens) {
37
68
  const messages = [];
38
69
  if (request.system !== undefined) {
39
70
  messages.push({ role: 'system', content: request.system });
@@ -41,7 +72,7 @@ export function buildOpenAiRequest(request) {
41
72
  messages.push(...request.messages.map(toOpenAiMessage));
42
73
  return {
43
74
  model: request.model,
44
- max_tokens: request.maxTokens,
75
+ max_tokens: request.maxTokens ?? fallbackMaxTokens,
45
76
  messages,
46
77
  ...(request.tools === undefined
47
78
  ? {}
@@ -49,7 +80,7 @@ export function buildOpenAiRequest(request) {
49
80
  tools: request.tools.map((tool) => ({
50
81
  type: 'function',
51
82
  function: {
52
- name: tool.name,
83
+ name: encodeToolName(tool.name),
53
84
  description: tool.description,
54
85
  parameters: tool.inputSchema,
55
86
  },
@@ -59,18 +90,18 @@ export function buildOpenAiRequest(request) {
59
90
  };
60
91
  }
61
92
  /** Pure — no network. */
62
- export function parseOpenAiResponse(body) {
93
+ export function parseOpenAiResponse(body, decodeToolName = (wire) => wire) {
63
94
  const choice = body.choices[0];
64
95
  if (choice === undefined) {
65
96
  throw new CogentaError({
66
97
  code: 'PROVIDER_RESPONSE_INVALID',
67
- message: 'OpenAI returned no choices.',
98
+ message: 'The OpenAI-compatible endpoint returned no choices.',
68
99
  hint: 'Retry the request; this is not something the caller can fix by itself.',
69
100
  });
70
101
  }
71
102
  const toolCalls = (choice.message.tool_calls ?? []).map((call) => ({
72
103
  id: call.id,
73
- name: call.function.name,
104
+ name: decodeToolName(call.function.name),
74
105
  input: parseArguments(call.function.arguments),
75
106
  }));
76
107
  return {
@@ -90,53 +121,114 @@ function parseArguments(raw) {
90
121
  catch (cause) {
91
122
  throw new CogentaError({
92
123
  code: 'PROVIDER_RESPONSE_INVALID',
93
- message: "OpenAI's tool call arguments were not valid JSON.",
124
+ message: "The endpoint's tool call arguments were not valid JSON.",
94
125
  hint: 'This is a vendor-side malformed response; retry the request.',
95
126
  cause,
96
127
  });
97
128
  }
98
129
  }
130
+ const MAX_REASON_LENGTH = 300;
131
+ /**
132
+ * The human-readable part of an OpenAI-shaped error body
133
+ * (`{ error: { message } }`), or the first line of a non-JSON body, capped
134
+ * so a vendor's HTML error page never becomes the message. `undefined` when
135
+ * there is nothing legible to show.
136
+ */
137
+ async function readErrorReason(response) {
138
+ const text = await response.text().catch(() => '');
139
+ if (text.trim() === '')
140
+ return undefined;
141
+ let reason = text;
142
+ try {
143
+ const parsed = JSON.parse(text);
144
+ if (typeof parsed === 'object' && parsed !== null && 'error' in parsed) {
145
+ const error = parsed.error;
146
+ if (typeof error === 'string')
147
+ reason = error;
148
+ else if (typeof error === 'object' && error !== null && 'message' in error) {
149
+ const message = error.message;
150
+ if (typeof message === 'string')
151
+ reason = message;
152
+ }
153
+ }
154
+ }
155
+ catch {
156
+ // Not JSON — keep the raw text.
157
+ }
158
+ const firstLine = reason.split('\n')[0]?.trim() ?? '';
159
+ if (firstLine === '')
160
+ return undefined;
161
+ return firstLine.length > MAX_REASON_LENGTH
162
+ ? `${firstLine.slice(0, MAX_REASON_LENGTH)}…`
163
+ : firstLine;
164
+ }
99
165
  /** API key injected at the runtime boundary — never in a prompt or tool input (rule R7). */
100
166
  export function createOpenAiClient(config) {
101
167
  const doFetch = config.fetchImpl ?? fetch;
102
168
  const url = config.baseUrl ?? DEFAULT_BASE_URL;
169
+ const name = config.name ?? 'openai';
170
+ const maxOutputTokens = config.maxOutputTokens ?? config.defaults.maxOutputTokens;
171
+ const requestTimeoutMs = config.requestTimeoutMs ?? config.defaults.requestTimeoutMs;
172
+ const maxCorrectionAttempts = config.maxCorrectionAttempts ?? config.defaults.maxCorrectionAttempts;
103
173
  return {
104
- name: 'openai',
174
+ name,
105
175
  model: config.model,
176
+ supportsVision: true,
177
+ maxOutputTokens,
178
+ requestTimeoutMs,
179
+ maxCorrectionAttempts,
106
180
  async chat(request, options) {
181
+ const signal = requestSignalWithTimeout(options?.signal, requestTimeoutMs);
107
182
  const response = await doFetch(url, {
108
183
  method: 'POST',
109
184
  headers: {
110
185
  'content-type': 'application/json',
111
186
  authorization: `Bearer ${config.apiKey}`,
112
187
  },
113
- body: JSON.stringify(buildOpenAiRequest(request)),
114
- ...(options?.signal === undefined ? {} : { signal: options.signal }),
188
+ body: JSON.stringify(buildOpenAiRequest(request, maxOutputTokens)),
189
+ signal,
115
190
  }).catch((cause) => {
191
+ if (signal.aborted && options?.signal?.aborted !== true) {
192
+ throw new CogentaError({
193
+ code: 'PROVIDER_REQUEST_FAILED',
194
+ message: `"${name}" did not answer in time.`,
195
+ hint: 'The vendor may be slow or unreachable right now; retry, or check its status page.',
196
+ cause,
197
+ });
198
+ }
116
199
  throw new CogentaError({
117
200
  code: 'PROVIDER_REQUEST_FAILED',
118
- message: 'The request to OpenAI could not be sent.',
119
- hint: 'Check network connectivity and COGENTA_OPENAI_API_KEY.',
201
+ message: `The request to "${name}" could not be sent.`,
202
+ hint: "Check network connectivity and this provider's saved API key.",
120
203
  cause,
121
204
  });
122
205
  });
123
206
  if (response.status === 429) {
124
207
  throw new CogentaError({
125
208
  code: 'PROVIDER_RATE_LIMITED',
126
- message: 'OpenAI rate-limited this request.',
209
+ message: `"${name}" rate-limited this request.`,
127
210
  hint: 'Retry with backoff, or lower callsPerHour for this agent.',
128
211
  });
129
212
  }
130
213
  if (!response.ok) {
214
+ // The vendor's own error text is the only thing that tells a 400
215
+ // ("model does not exist", "unsupported parameter") from a 401 —
216
+ // dropping it left an operator staring at a bare status code with
217
+ // nothing to act on. It never carries the key; it is safe to quote.
218
+ const reason = await readErrorReason(response);
131
219
  throw new CogentaError({
132
220
  code: 'PROVIDER_REQUEST_FAILED',
133
- message: `OpenAI returned status ${response.status}.`,
134
- hint: 'Check the request and COGENTA_OPENAI_API_KEY.',
135
- details: { status: response.status },
221
+ message: reason === undefined
222
+ ? `"${name}" returned status ${response.status}.`
223
+ : `"${name}" returned status ${response.status}: ${reason}`,
224
+ hint: response.status === 400
225
+ ? "Check the model name saved for this provider — it must be one this endpoint actually serves — then the request. The provider's own message above usually names the field."
226
+ : "Check the request and this provider's saved API key.",
227
+ details: { status: response.status, ...(reason === undefined ? {} : { reason }) },
136
228
  });
137
229
  }
138
230
  const body = (await response.json());
139
- return parseOpenAiResponse(body);
231
+ return parseOpenAiResponse(body, createToolNameDecoder(request));
140
232
  },
141
233
  };
142
234
  }
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -1,31 +1,48 @@
1
+ import type { ProviderTuningDefaults } from './defaults.js';
1
2
  import type { ProviderClient } from './types.js';
2
- export declare const PROVIDER_NAMES: readonly ['anthropic', 'openai', 'google'];
3
- export type ProviderName = (typeof PROVIDER_NAMES)[number];
4
- export interface ProviderRegistryConfig {
5
- readonly anthropic?: {
6
- readonly apiKey: string;
7
- readonly model: string;
8
- readonly baseUrl?: string;
9
- };
10
- readonly openai?: {
11
- readonly apiKey: string;
12
- readonly model: string;
13
- readonly baseUrl?: string;
14
- };
15
- readonly google?: {
16
- readonly apiKey: string;
17
- readonly model: string;
18
- readonly baseUrl?: string;
19
- };
3
+ /**
4
+ * Fiche 56: `provider` used to be a closed 3-literal union
5
+ * (`'anthropic' | 'openai' | 'google'`) — every fourth vendor (OpenRouter,
6
+ * DeepSeek, Qwen, GLM, a self-hosted OpenAI-compatible endpoint) needed a
7
+ * code change to even be expressible. It is now a plain string, validated at
8
+ * the write boundary (`store.ts`'s `upsert` and the `/api/providers` router),
9
+ * not by a type. `@cogenta/core`'s own `llmSchema.provider` was already a
10
+ * free string before this fiche — this only catches the registry up to a
11
+ * looseness the config schema already had.
12
+ */
13
+ export type ProviderName = string;
14
+ export interface ProviderEntryConfig {
15
+ readonly apiKey: string;
16
+ readonly model: string;
17
+ /**
18
+ * Overrides `catalog.ts`'s `defaultBaseUrl` for a known provider (e.g. a
19
+ * self-hosted proxy in front of OpenAI), or — for a provider id absent
20
+ * from the catalog entirely — is what makes it resolvable at all: an
21
+ * unknown id with no `baseUrl` cannot be turned into a client (see
22
+ * `buildClient` below).
23
+ */
24
+ readonly baseUrl?: string;
25
+ /** See `ProviderClient.maxOutputTokens` — the admin's value for this provider, or absent to fall back to the registry's own `defaults`. */
26
+ readonly maxOutputTokens?: number;
27
+ /** See `ProviderClient.requestTimeoutMs`. */
28
+ readonly requestTimeoutMs?: number;
29
+ /** See `ProviderClient.maxCorrectionAttempts`. */
30
+ readonly maxCorrectionAttempts?: number;
20
31
  }
32
+ export type ProviderRegistryConfig = Readonly<Record<string, ProviderEntryConfig>>;
21
33
  /**
22
34
  * One client per configured vendor — a site with no LLM provider configured
23
35
  * simply has an empty registry, which is exactly what rule R2 requires ("le
24
36
  * CMS fonctionne sans IA"): nothing here fails to construct, `get()` is what
25
37
  * refuses, and only once an agent actually tries to run.
38
+ *
39
+ * `defaults` is the site-wide tuning floor (`resolveProviderTuningDefaults`,
40
+ * `assistant.*` site settings) every entry's own per-provider override falls
41
+ * back to — required, so no adapter this registry builds can ever fall back
42
+ * to a hardcoded constant instead.
26
43
  */
27
- export declare function createProviderRegistry(config: ProviderRegistryConfig): {
28
- readonly get: (name: ProviderName) => ProviderClient;
29
- readonly has: (name: ProviderName) => boolean;
44
+ export declare function createProviderRegistry(config: ProviderRegistryConfig, defaults: ProviderTuningDefaults): {
45
+ readonly get: (name: string) => ProviderClient;
46
+ readonly has: (name: string) => boolean;
30
47
  };
31
48
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,eAAO,MAAM,cAAc,YAAI,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAA;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE;QACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChG,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACjG;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG;IACtE,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,cAAc,CAAA;IACpD,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAA;CAC9C,CAqBA"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAG3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAA;AAEjC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,2IAA2I;IAC3I,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,kDAAkD;IAClD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CACxC;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAA;AA+DlF;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,EAC9B,QAAQ,EAAE,sBAAsB,GAC/B;IACD,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,CAAA;IAC9C,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CACxC,CAoBA"}
@@ -1,22 +1,78 @@
1
1
  import { CogentaError } from '@cogenta/core';
2
2
  import { createAnthropicClient } from './anthropic.js';
3
+ import { findProviderCatalogEntry } from './catalog.js';
3
4
  import { createGoogleClient } from './google.js';
4
5
  import { createOpenAiClient } from './openai.js';
5
- export const PROVIDER_NAMES = ['anthropic', 'openai', 'google'];
6
+ /**
7
+ * One provider entry → one client. A catalog id picks the adapter
8
+ * (`wireFormat`); a name the catalog does not know is only usable if the
9
+ * entry carries its own `baseUrl` — that is what "custom OpenAI-compatible
10
+ * endpoint" means structurally, not a separate `custom: true` flag to keep
11
+ * in sync with this lookup.
12
+ */
13
+ function buildClient(name, entry, defaults) {
14
+ const catalogEntry = findProviderCatalogEntry(name);
15
+ const tuning = {
16
+ ...(entry.maxOutputTokens === undefined ? {} : { maxOutputTokens: entry.maxOutputTokens }),
17
+ ...(entry.requestTimeoutMs === undefined ? {} : { requestTimeoutMs: entry.requestTimeoutMs }),
18
+ ...(entry.maxCorrectionAttempts === undefined
19
+ ? {}
20
+ : { maxCorrectionAttempts: entry.maxCorrectionAttempts }),
21
+ };
22
+ if (catalogEntry?.wireFormat === 'anthropic') {
23
+ return createAnthropicClient({
24
+ apiKey: entry.apiKey,
25
+ model: entry.model,
26
+ ...(entry.baseUrl === undefined ? {} : { baseUrl: entry.baseUrl }),
27
+ ...tuning,
28
+ defaults,
29
+ });
30
+ }
31
+ if (catalogEntry?.wireFormat === 'google') {
32
+ return createGoogleClient({
33
+ apiKey: entry.apiKey,
34
+ model: entry.model,
35
+ ...(entry.baseUrl === undefined ? {} : { baseUrl: entry.baseUrl }),
36
+ ...tuning,
37
+ defaults,
38
+ });
39
+ }
40
+ // `wireFormat: 'openai-compatible'` (OpenAI itself, OpenRouter, DeepSeek,
41
+ // Qwen, GLM) and any id absent from the catalog share this one branch —
42
+ // exactly the "zero new network code" the fiche asks for.
43
+ const baseUrl = entry.baseUrl ?? catalogEntry?.defaultBaseUrl;
44
+ if (baseUrl === undefined) {
45
+ throw new CogentaError({
46
+ code: 'PROVIDER_CUSTOM_BASE_URL_REQUIRED',
47
+ message: `"${name}" is not a built-in provider and has no "baseUrl" configured.`,
48
+ hint: 'Set a baseUrl for a custom OpenAI-compatible endpoint, or use a catalog provider id.',
49
+ });
50
+ }
51
+ return createOpenAiClient({
52
+ apiKey: entry.apiKey,
53
+ model: entry.model,
54
+ baseUrl,
55
+ name,
56
+ ...tuning,
57
+ defaults,
58
+ });
59
+ }
6
60
  /**
7
61
  * One client per configured vendor — a site with no LLM provider configured
8
62
  * simply has an empty registry, which is exactly what rule R2 requires ("le
9
63
  * CMS fonctionne sans IA"): nothing here fails to construct, `get()` is what
10
64
  * refuses, and only once an agent actually tries to run.
65
+ *
66
+ * `defaults` is the site-wide tuning floor (`resolveProviderTuningDefaults`,
67
+ * `assistant.*` site settings) every entry's own per-provider override falls
68
+ * back to — required, so no adapter this registry builds can ever fall back
69
+ * to a hardcoded constant instead.
11
70
  */
12
- export function createProviderRegistry(config) {
71
+ export function createProviderRegistry(config, defaults) {
13
72
  const clients = new Map();
14
- if (config.anthropic !== undefined)
15
- clients.set('anthropic', createAnthropicClient(config.anthropic));
16
- if (config.openai !== undefined)
17
- clients.set('openai', createOpenAiClient(config.openai));
18
- if (config.google !== undefined)
19
- clients.set('google', createGoogleClient(config.google));
73
+ for (const [name, entry] of Object.entries(config)) {
74
+ clients.set(name, buildClient(name, entry, defaults));
75
+ }
20
76
  return {
21
77
  has: (name) => clients.has(name),
22
78
  get(name) {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAGhD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAA;AAaxE;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA8B;IAInE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgC,CAAA;IACvD,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAChC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IACzF,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IAEzF,OAAO;QACL,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QAChC,GAAG,CAAC,IAAI;YACN,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,IAAI,YAAY,CAAC;oBACrB,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE,sBAAsB,IAAI,gCAAgC;oBACnE,IAAI,EAAE,sEAAsE;iBAC7E,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The caller's own signal (if any) combined with a timeout floor, so a
3
+ * cancellation the run loop already wants (budget exceeded, kill switch)
4
+ * still works exactly as before, and an otherwise-uncancelled call still
5
+ * gives up eventually.
6
+ *
7
+ * `timeoutMs` is required — every real caller (the three provider adapters)
8
+ * always resolves a concrete `requestTimeoutMs` before calling this
9
+ * (`ProviderClient.requestTimeoutMs`, itself always a number: the admin's
10
+ * per-provider override or the site-wide `assistant.defaultRequestTimeoutSeconds`
11
+ * floor, `SITE_SETTINGS_REGISTRY` in `@cogenta/schema`). This function used
12
+ * to default it to a `DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS` constant — fiche
13
+ * feedback: that hid a real site behaviour (what happens when a call to a
14
+ * stalled vendor never returns — reproduced live once, see the changeset
15
+ * history) behind a number nothing but this file's own comment ever named.
16
+ */
17
+ export declare function requestSignalWithTimeout(callerSignal: AbortSignal | undefined, timeoutMs: number): AbortSignal;
18
+ //# sourceMappingURL=request-signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-signal.d.ts","sourceRoot":"","sources":["../../src/providers/request-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,WAAW,GAAG,SAAS,EACrC,SAAS,EAAE,MAAM,GAChB,WAAW,CAGb"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The caller's own signal (if any) combined with a timeout floor, so a
3
+ * cancellation the run loop already wants (budget exceeded, kill switch)
4
+ * still works exactly as before, and an otherwise-uncancelled call still
5
+ * gives up eventually.
6
+ *
7
+ * `timeoutMs` is required — every real caller (the three provider adapters)
8
+ * always resolves a concrete `requestTimeoutMs` before calling this
9
+ * (`ProviderClient.requestTimeoutMs`, itself always a number: the admin's
10
+ * per-provider override or the site-wide `assistant.defaultRequestTimeoutSeconds`
11
+ * floor, `SITE_SETTINGS_REGISTRY` in `@cogenta/schema`). This function used
12
+ * to default it to a `DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS` constant — fiche
13
+ * feedback: that hid a real site behaviour (what happens when a call to a
14
+ * stalled vendor never returns — reproduced live once, see the changeset
15
+ * history) behind a number nothing but this file's own comment ever named.
16
+ */
17
+ export function requestSignalWithTimeout(callerSignal, timeoutMs) {
18
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
19
+ return callerSignal === undefined ? timeoutSignal : AbortSignal.any([callerSignal, timeoutSignal]);
20
+ }
21
+ //# sourceMappingURL=request-signal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-signal.js","sourceRoot":"","sources":["../../src/providers/request-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,wBAAwB,CACtC,YAAqC,EACrC,SAAiB;IAEjB,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACpD,OAAO,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAA;AACpG,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ProviderRegistryConfig } from './registry.js';
2
+ import type { ProviderConfigStore } from './store.js';
3
+ /**
4
+ * Turns the persisted, encrypted `ProviderConfigStore` into the plaintext
5
+ * shape `createProviderRegistry` needs — the one place a key is decrypted
6
+ * for actual use (R7: never logged, never returned from this function's
7
+ * caller over the wire). A provider with no saved key, or saved but
8
+ * disabled, is simply absent from the result — exactly R2's "no provider
9
+ * configured" state `createProviderRegistry`'s own doc comment already
10
+ * describes.
11
+ */
12
+ export declare function resolveProviderRegistryConfig(store: ProviderConfigStore): Promise<ProviderRegistryConfig>;
13
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/providers/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAErD;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,sBAAsB,CAAC,CA4BjC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Turns the persisted, encrypted `ProviderConfigStore` into the plaintext
3
+ * shape `createProviderRegistry` needs — the one place a key is decrypted
4
+ * for actual use (R7: never logged, never returned from this function's
5
+ * caller over the wire). A provider with no saved key, or saved but
6
+ * disabled, is simply absent from the result — exactly R2's "no provider
7
+ * configured" state `createProviderRegistry`'s own doc comment already
8
+ * describes.
9
+ */
10
+ export async function resolveProviderRegistryConfig(store) {
11
+ const configs = await store.list();
12
+ const config = {};
13
+ for (const entry of configs) {
14
+ if (!entry.enabled)
15
+ continue;
16
+ const apiKey = await store.decryptKey(entry.provider);
17
+ config[entry.provider] = {
18
+ apiKey,
19
+ model: entry.model,
20
+ ...(entry.baseUrl === undefined ? {} : { baseUrl: entry.baseUrl }),
21
+ ...(entry.maxOutputTokens === undefined ? {} : { maxOutputTokens: entry.maxOutputTokens }),
22
+ ...(entry.requestTimeoutMs === undefined ? {} : { requestTimeoutMs: entry.requestTimeoutMs }),
23
+ ...(entry.maxCorrectionAttempts === undefined
24
+ ? {}
25
+ : { maxCorrectionAttempts: entry.maxCorrectionAttempts }),
26
+ };
27
+ }
28
+ return config;
29
+ }
30
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/providers/resolve.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,KAA0B;IAE1B,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAA;IAClC,MAAM,MAAM,GAUR,EAAE,CAAA;IACN,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,SAAQ;QAC5B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QACrD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG;YACvB,MAAM;YACN,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;YAClE,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1F,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;YAC7F,GAAG,CAAC,KAAK,CAAC,qBAAqB,KAAK,SAAS;gBAC3C,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,qBAAqB,EAAE,KAAK,CAAC,qBAAqB,EAAE,CAAC;SAC5D,CAAA;IACH,CAAC;IACD,OAAO,MAAgC,CAAA;AACzC,CAAC"}
@@ -0,0 +1,70 @@
1
+ import type { ProviderName } from './registry.js';
2
+ export interface StoredProviderConfig {
3
+ readonly provider: ProviderName;
4
+ readonly enabled: boolean;
5
+ readonly model: string;
6
+ readonly baseUrl?: string;
7
+ /** Last 4 characters of the real key, for the admin to confirm which key is saved without ever re-displaying it in full. */
8
+ readonly maskedKey: string;
9
+ readonly updatedAt: string;
10
+ /**
11
+ * The completion budget (`ProviderClient.maxOutputTokens`), request retry
12
+ * count (`maxCorrectionAttempts`) and HTTP/agent-loop timeout
13
+ * (`requestTimeoutMs`, milliseconds) this provider's client resolves to.
14
+ * Absent means "use the built-in fallback" (`resolve.ts`) — every one of
15
+ * these was, before this admin surface existed, a number hardcoded per
16
+ * call site with no way for an admin to say "this particular model needs
17
+ * more room to think" (the exact bug a real reasoning-model run
18
+ * reproduced: DeepSeek's `deepseek-v4-flash` silently truncated to an
19
+ * empty response at a too-low hardcoded ceiling).
20
+ */
21
+ readonly maxOutputTokens?: number;
22
+ readonly requestTimeoutMs?: number;
23
+ readonly maxCorrectionAttempts?: number;
24
+ }
25
+ export interface ProviderConfigInput {
26
+ readonly provider: ProviderName;
27
+ readonly apiKey: string;
28
+ readonly model: string;
29
+ readonly baseUrl?: string;
30
+ readonly enabled?: boolean;
31
+ readonly maxOutputTokens?: number;
32
+ readonly requestTimeoutMs?: number;
33
+ readonly maxCorrectionAttempts?: number;
34
+ }
35
+ export interface ProviderConfigStore {
36
+ list(): Promise<readonly StoredProviderConfig[]>;
37
+ get(provider: ProviderName): Promise<StoredProviderConfig | undefined>;
38
+ /** Encrypts and persists `apiKey`; creates or overwrites this provider's one record. */
39
+ upsert(input: ProviderConfigInput): Promise<StoredProviderConfig>;
40
+ setEnabled(provider: ProviderName, enabled: boolean): Promise<StoredProviderConfig>;
41
+ /**
42
+ * Changes `model`/`baseUrl`/tuning without touching the saved key — so an
43
+ * admin can adjust any of these, including *after* the first save,
44
+ * without being made to re-paste an API key they may no longer have
45
+ * handy. `undefined` on a tuning field leaves it as saved; `null`
46
+ * explicitly clears it back to "use the built-in default" (the one thing
47
+ * a plain optional field can't express — leaving it out of the patch and
48
+ * clearing it back to unset need distinct wire shapes). Throws
49
+ * `PROVIDER_NOT_CONFIGURED` if this provider has no saved key yet.
50
+ */
51
+ updateSettings(provider: ProviderName, patch: {
52
+ readonly model?: string;
53
+ readonly baseUrl?: string;
54
+ readonly maxOutputTokens?: number | null;
55
+ readonly requestTimeoutMs?: number | null;
56
+ readonly maxCorrectionAttempts?: number | null;
57
+ }): Promise<StoredProviderConfig>;
58
+ remove(provider: ProviderName): Promise<void>;
59
+ /** The one place the real key is ever decrypted — never exposed on `StoredProviderConfig` itself. Throws `PROVIDER_NOT_CONFIGURED` if this provider has no saved key. */
60
+ decryptKey(provider: ProviderName): Promise<string>;
61
+ }
62
+ export interface FileProviderConfigStoreOptions {
63
+ readonly dir: string;
64
+ /** `COGENTA_AUTH_SIGNING_KEY` — the encryption key is derived from it, never stored itself. */
65
+ readonly signingKey: string;
66
+ readonly now?: () => Date;
67
+ }
68
+ /** One `<provider>.json` record per configured provider, under `options.dir` — the same one-file-per-record shape every other file store in this package uses (R1: no external service). */
69
+ export declare function createFileProviderConfigStore(options: FileProviderConfigStoreOptions): ProviderConfigStore;
70
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/providers/store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAqEjD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,4HAA4H;IAC5H,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CACxC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CACxC;AA+BD,MAAM,WAAW,mBAAmB;IAClC,IAAI,IAAI,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC,CAAA;IAChD,GAAG,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAA;IACtE,wFAAwF;IACxF,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACjE,UAAU,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACnF;;;;;;;;;OASG;IACH,cAAc,CACZ,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE;QACL,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACxC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACzC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC/C,GACA,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAChC,MAAM,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,yKAAyK;IACzK,UAAU,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACpD;AAqDD,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,4LAA4L;AAC5L,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,8BAA8B,GACtC,mBAAmB,CAmMrB"}