@jini-ai/agent-runtime 0.3.10 → 0.4.1

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 (200) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/README.md +34 -17
  3. package/dist/acp-model-probe.d.ts +6 -4
  4. package/dist/acp-model-probe.js +3 -3
  5. package/dist/agent-protocol/acp/account-failure.d.ts +4 -2
  6. package/dist/agent-protocol/acp/account-failure.js +1 -1
  7. package/dist/agent-protocol/acp/json.d.ts +6 -6
  8. package/dist/agent-protocol/acp/json.js +3 -3
  9. package/dist/agent-protocol/acp/models.d.ts +10 -5
  10. package/dist/agent-protocol/acp/models.js +32 -31
  11. package/dist/agent-protocol/acp/session-params.d.ts +3 -1
  12. package/dist/agent-protocol/acp/session-params.js +2 -1
  13. package/dist/agent-protocol/acp/session.d.ts +28 -22
  14. package/dist/agent-protocol/acp/session.js +181 -147
  15. package/dist/agent-protocol/acp/text-suppression.d.ts +1 -1
  16. package/dist/agent-protocol/acp/text-suppression.js +1 -1
  17. package/dist/agent-protocol/acp/types.d.ts +3 -2
  18. package/dist/agent-protocol/acp/updates.d.ts +11 -11
  19. package/dist/agent-protocol/acp/updates.js +2 -2
  20. package/dist/agent-protocol/core/json-line-stream.d.ts +24 -8
  21. package/dist/agent-protocol/core/json-line-stream.js +8 -8
  22. package/dist/agent-protocol/pi-rpc/events.d.ts +5 -1
  23. package/dist/agent-protocol/pi-rpc/events.js +36 -36
  24. package/dist/agent-protocol/pi-rpc/internal.d.ts +4 -1
  25. package/dist/agent-protocol/pi-rpc/models.d.ts +3 -1
  26. package/dist/agent-protocol/pi-rpc/models.js +1 -1
  27. package/dist/agent-protocol/pi-rpc/session.d.ts +1 -1
  28. package/dist/agent-protocol/pi-rpc/session.js +33 -32
  29. package/dist/amr-model-cache.d.ts +12 -4
  30. package/dist/amr-model-cache.js +17 -21
  31. package/dist/amr-profile-resolver.d.ts +3 -1
  32. package/dist/anthropic-live-models.js +0 -0
  33. package/dist/artifact-taxonomy.d.ts +6 -2
  34. package/dist/auth.d.ts +52 -15
  35. package/dist/auth.js +36 -36
  36. package/dist/claude-code-models.js +2 -2
  37. package/dist/claude-stream.d.ts +22 -3
  38. package/dist/claude-stream.js +24 -8
  39. package/dist/copilot-stream.d.ts +7 -3
  40. package/dist/copilot-stream.js +3 -3
  41. package/dist/defs/aider.d.ts +8 -1
  42. package/dist/defs/aider.js +2 -2
  43. package/dist/defs/amp.d.ts +8 -1
  44. package/dist/defs/amp.js +2 -2
  45. package/dist/defs/amr.d.ts +22 -6
  46. package/dist/defs/amr.js +23 -23
  47. package/dist/defs/antigravity.d.ts +15 -4
  48. package/dist/defs/antigravity.js +9 -8
  49. package/dist/defs/auggie.d.ts +4 -1
  50. package/dist/defs/auggie.js +1 -1
  51. package/dist/defs/claude.d.ts +12 -2
  52. package/dist/defs/claude.js +5 -5
  53. package/dist/defs/cline.d.ts +4 -1
  54. package/dist/defs/cline.js +1 -1
  55. package/dist/defs/codebuddy.d.ts +8 -1
  56. package/dist/defs/codebuddy.js +2 -2
  57. package/dist/defs/codex.d.ts +18 -4
  58. package/dist/defs/codex.js +7 -7
  59. package/dist/defs/copilot.d.ts +8 -1
  60. package/dist/defs/copilot.js +2 -2
  61. package/dist/defs/crush.d.ts +8 -1
  62. package/dist/defs/crush.js +1 -1
  63. package/dist/defs/cursor-agent.d.ts +14 -3
  64. package/dist/defs/cursor-agent.js +5 -5
  65. package/dist/defs/deepseek.d.ts +8 -1
  66. package/dist/defs/deepseek.js +2 -2
  67. package/dist/defs/devin.d.ts +12 -2
  68. package/dist/defs/devin.js +3 -3
  69. package/dist/defs/droid.d.ts +8 -1
  70. package/dist/defs/droid.js +1 -1
  71. package/dist/defs/gemini.d.ts +8 -1
  72. package/dist/defs/gemini.js +1 -1
  73. package/dist/defs/goose.d.ts +4 -1
  74. package/dist/defs/goose.js +1 -1
  75. package/dist/defs/grok-build.d.ts +11 -2
  76. package/dist/defs/grok-build.js +3 -3
  77. package/dist/defs/hermes.d.ts +4 -1
  78. package/dist/defs/hermes.js +2 -2
  79. package/dist/defs/kilo.d.ts +4 -1
  80. package/dist/defs/kilo.js +2 -2
  81. package/dist/defs/kimi.d.ts +4 -1
  82. package/dist/defs/kimi.js +2 -2
  83. package/dist/defs/kiro.d.ts +4 -1
  84. package/dist/defs/kiro.js +2 -2
  85. package/dist/defs/mimo.d.ts +8 -1
  86. package/dist/defs/mimo.js +2 -2
  87. package/dist/defs/opencode.d.ts +9 -2
  88. package/dist/defs/opencode.js +2 -2
  89. package/dist/defs/pi.d.ts +12 -2
  90. package/dist/defs/pi.js +9 -9
  91. package/dist/defs/qoder.d.ts +8 -1
  92. package/dist/defs/qoder.js +2 -2
  93. package/dist/defs/qwen.d.ts +8 -1
  94. package/dist/defs/qwen.js +2 -2
  95. package/dist/defs/reasonix.d.ts +4 -1
  96. package/dist/defs/reasonix.js +3 -3
  97. package/dist/defs/shared.d.ts +4 -2
  98. package/dist/defs/shared.js +2 -2
  99. package/dist/defs/trae-cli.d.ts +12 -2
  100. package/dist/defs/trae-cli.js +3 -3
  101. package/dist/defs/vibe.d.ts +4 -1
  102. package/dist/defs/vibe.js +2 -2
  103. package/dist/detection.d.ts +19 -4
  104. package/dist/detection.js +33 -33
  105. package/dist/diagnostics.d.ts +14 -3
  106. package/dist/diagnostics.js +5 -5
  107. package/dist/env.d.ts +16 -4
  108. package/dist/env.js +7 -7
  109. package/dist/executables.d.ts +24 -8
  110. package/dist/executables.js +13 -13
  111. package/dist/index.d.ts +228 -4
  112. package/dist/index.js +230 -6
  113. package/dist/invocation.d.ts +6 -1
  114. package/dist/invocation.js +2 -2
  115. package/dist/json-event-stream.d.ts +7 -2
  116. package/dist/json-event-stream.js +3 -3
  117. package/dist/launch.d.ts +12 -2
  118. package/dist/launch.js +3 -3
  119. package/dist/log-file.d.ts +4 -1
  120. package/dist/log-file.js +2 -2
  121. package/dist/mcp.d.ts +6 -3
  122. package/dist/mcp.js +1 -1
  123. package/dist/metadata.d.ts +7 -3
  124. package/dist/metadata.js +1 -1
  125. package/dist/mmd-routes.d.ts +22 -6
  126. package/dist/mmd-routes.js +14 -14
  127. package/dist/model-catalog-cache.d.ts +50 -0
  128. package/dist/model-catalog-cache.js +61 -0
  129. package/dist/model-loading-state.d.ts +10 -0
  130. package/dist/model-loading-state.js +23 -0
  131. package/dist/model-registry.d.ts +28 -7
  132. package/dist/model-registry.js +11 -8
  133. package/dist/models.d.ts +31 -6
  134. package/dist/models.js +6 -6
  135. package/dist/opencode-log.d.ts +12 -4
  136. package/dist/opencode-log.js +8 -8
  137. package/dist/paths.d.ts +6 -2
  138. package/dist/paths.js +3 -3
  139. package/dist/pi-models.d.ts +3 -1
  140. package/dist/pi-models.js +2 -2
  141. package/dist/prompt-budget.d.ts +17 -4
  142. package/dist/prompt-budget.js +3 -3
  143. package/dist/prompt-file.d.ts +5 -1
  144. package/dist/prompt-file.js +1 -1
  145. package/dist/providers/aihubmix.d.ts +34 -9
  146. package/dist/providers/aihubmix.js +26 -26
  147. package/dist/providers/anthropic-messages.d.ts +77 -20
  148. package/dist/providers/anthropic-messages.js +53 -50
  149. package/dist/providers/azure-chat.d.ts +21 -7
  150. package/dist/providers/azure-chat.js +18 -16
  151. package/dist/providers/connection-guard.d.ts +45 -31
  152. package/dist/providers/connection-guard.js +40 -143
  153. package/dist/providers/connection-test.d.ts +1 -1
  154. package/dist/providers/connection-test.js +13 -30
  155. package/dist/providers/elevenlabs.d.ts +7 -2
  156. package/dist/providers/elevenlabs.js +4 -4
  157. package/dist/providers/google-messages.d.ts +44 -10
  158. package/dist/providers/google-messages.js +36 -34
  159. package/dist/providers/google-schema.d.ts +26 -0
  160. package/dist/providers/google-schema.js +253 -0
  161. package/dist/providers/google.d.ts +21 -6
  162. package/dist/providers/google.js +10 -10
  163. package/dist/providers/index.d.ts +3 -2
  164. package/dist/providers/index.js +3 -2
  165. package/dist/providers/model-catalog.d.ts +1 -1
  166. package/dist/providers/model-catalog.js +14 -27
  167. package/dist/providers/oauth-callback-server.d.ts +1 -1
  168. package/dist/providers/oauth-callback-server.js +3 -2
  169. package/dist/providers/oauth-credentials.d.ts +7 -1
  170. package/dist/providers/oauth-credentials.js +5 -5
  171. package/dist/providers/oauth-provider.d.ts +2 -2
  172. package/dist/providers/oauth-provider.js +20 -25
  173. package/dist/providers/oauth-tokens.d.ts +26 -6
  174. package/dist/providers/oauth-tokens.js +9 -9
  175. package/dist/providers/ollama-chat.d.ts +66 -31
  176. package/dist/providers/ollama-chat.js +64 -61
  177. package/dist/providers/openai-chat.d.ts +77 -22
  178. package/dist/providers/openai-chat.js +71 -67
  179. package/dist/providers/pkce.d.ts +33 -20
  180. package/dist/providers/pkce.js +75 -146
  181. package/dist/providers/sse-decode.d.ts +3 -1
  182. package/dist/providers/sse-decode.js +1 -1
  183. package/dist/providers/token-params.d.ts +16 -5
  184. package/dist/providers/token-params.js +6 -6
  185. package/dist/providers/tool-turn-types.d.ts +94 -0
  186. package/dist/providers/tool-turn-types.js +2 -0
  187. package/dist/providers/tool-turn.d.ts +10 -0
  188. package/dist/providers/tool-turn.js +258 -0
  189. package/dist/qoder-stream.d.ts +7 -3
  190. package/dist/qoder-stream.js +3 -3
  191. package/dist/registry.d.ts +6 -2
  192. package/dist/registry.js +4 -4
  193. package/dist/resolution.d.ts +5 -1
  194. package/dist/resolution.js +3 -3
  195. package/dist/role-marker-guard.d.ts +9 -5
  196. package/dist/role-marker-guard.js +5 -5
  197. package/dist/terminal-launch.d.ts +6 -1
  198. package/dist/terminal-launch.js +2 -2
  199. package/dist/types.d.ts +22 -6
  200. package/package.json +43 -4
@@ -6,7 +6,7 @@
6
6
  * verbatim.
7
7
  */
8
8
  /** Strips any trailing `/v1`/`/v1beta` API-version segment and trailing slashes from a configured base URL. */
9
- export function googleGenerativeLanguageBaseUrl(baseUrl) {
9
+ export function googleGenerativeLanguageBaseUrl({ baseUrl }) {
10
10
  const url = new URL(baseUrl);
11
11
  url.search = '';
12
12
  url.hash = '';
@@ -17,25 +17,25 @@ export function googleGenerativeLanguageBaseUrl(baseUrl) {
17
17
  return url.toString().replace(/\/+$/, '');
18
18
  }
19
19
  /** Strips the `models/` prefix Google's API sometimes includes in a model id. */
20
- export function normalizeGoogleModelId(model) {
20
+ export function normalizeGoogleModelId({ model }) {
21
21
  const trimmed = model.trim();
22
22
  return trimmed.startsWith('models/') ? trimmed.slice('models/'.length) : trimmed;
23
23
  }
24
24
  /** URL-encodes a normalized model id for use as a path segment. */
25
- export function googleModelPathSegment(model) {
26
- return encodeURIComponent(normalizeGoogleModelId(model));
25
+ export function googleModelPathSegment({ model }) {
26
+ return encodeURIComponent(normalizeGoogleModelId({ model: model }));
27
27
  }
28
28
  /** Builds the non-streaming `generateContent` endpoint URL for a model. */
29
- export function googleGenerateContentUrl(baseUrl, model) {
30
- return `${googleGenerativeLanguageBaseUrl(baseUrl)}/v1beta/models/${googleModelPathSegment(model)}:generateContent`;
29
+ export function googleGenerateContentUrl({ baseUrl, model }) {
30
+ return `${googleGenerativeLanguageBaseUrl({ baseUrl: baseUrl })}/v1beta/models/${googleModelPathSegment({ model: model })}:generateContent`;
31
31
  }
32
32
  /** Builds the SSE-streaming `streamGenerateContent` endpoint URL for a model. */
33
- export function googleStreamGenerateContentUrl(baseUrl, model) {
34
- return `${googleGenerativeLanguageBaseUrl(baseUrl)}/v1beta/models/${googleModelPathSegment(model)}:streamGenerateContent?alt=sse`;
33
+ export function googleStreamGenerateContentUrl({ baseUrl, model }) {
34
+ return `${googleGenerativeLanguageBaseUrl({ baseUrl: baseUrl })}/v1beta/models/${googleModelPathSegment({ model: model })}:streamGenerateContent?alt=sse`;
35
35
  }
36
36
  /** Builds the model-catalog listing endpoint URL, with the API key attached as a query param. */
37
- export function googleProviderModelsUrl(baseUrl, apiKey) {
38
- const url = new URL(`${googleGenerativeLanguageBaseUrl(baseUrl)}/v1beta/models`);
37
+ export function googleProviderModelsUrl({ baseUrl, apiKey }) {
38
+ const url = new URL(`${googleGenerativeLanguageBaseUrl({ baseUrl: baseUrl })}/v1beta/models`);
39
39
  url.searchParams.set('key', apiKey);
40
40
  return url.toString();
41
41
  }
@@ -2,7 +2,7 @@
2
2
  * @module providers
3
3
  *
4
4
  * Generic LLM-provider integration material ported from OD's
5
- * `apps/daemon/src/integrations/` (13 files). See `source-map.md` for the
5
+ * `apps/daemon/src/integrations/` (13 files). See `archived provenance ledger` for the
6
6
  * full per-file provenance and the MIXED-classification split: OD's own
7
7
  * AMR/vela provider adapter (`vela*.ts`, 4 files) is a specific provider's
8
8
  * own daemon-coupled implementation, not generic material, and was left
@@ -15,7 +15,7 @@
15
15
  * `chat.ts` (this task did not have direct access to that file for the
16
16
  * 2026-07-21 pass; the 2026-07-22 pass did read the real OD source for
17
17
  * Azure's api-version default — see `azure-chat.ts`'s header) — see each
18
- * module's own header and `source-map.md`'s dated sections for the full
18
+ * module's own header and `archived provenance ledger`'s dated sections for the full
19
19
  * rationale.
20
20
  */
21
21
  export * from './types.js';
@@ -37,4 +37,5 @@ export * from './oauth-provider.js';
37
37
  export * from './oauth-callback-server.js';
38
38
  export * from './oauth-tokens.js';
39
39
  export * from './oauth-credentials.js';
40
+ export * from './tool-turn.js';
40
41
  //# sourceMappingURL=index.d.ts.map
@@ -2,7 +2,7 @@
2
2
  * @module providers
3
3
  *
4
4
  * Generic LLM-provider integration material ported from OD's
5
- * `apps/daemon/src/integrations/` (13 files). See `source-map.md` for the
5
+ * `apps/daemon/src/integrations/` (13 files). See `archived provenance ledger` for the
6
6
  * full per-file provenance and the MIXED-classification split: OD's own
7
7
  * AMR/vela provider adapter (`vela*.ts`, 4 files) is a specific provider's
8
8
  * own daemon-coupled implementation, not generic material, and was left
@@ -15,7 +15,7 @@
15
15
  * `chat.ts` (this task did not have direct access to that file for the
16
16
  * 2026-07-21 pass; the 2026-07-22 pass did read the real OD source for
17
17
  * Azure's api-version default — see `azure-chat.ts`'s header) — see each
18
- * module's own header and `source-map.md`'s dated sections for the full
18
+ * module's own header and `archived provenance ledger`'s dated sections for the full
19
19
  * rationale.
20
20
  */
21
21
  export * from './types.js';
@@ -37,4 +37,5 @@ export * from './oauth-provider.js';
37
37
  export * from './oauth-callback-server.js';
38
38
  export * from './oauth-tokens.js';
39
39
  export * from './oauth-credentials.js';
40
+ export * from './tool-turn.js';
40
41
  //# sourceMappingURL=index.js.map
@@ -28,5 +28,5 @@ export type ProviderModelsInput = ProviderModelsRequest & {
28
28
  * "unsupported" response for Azure), and normalizes every provider's
29
29
  * response envelope into a de-duplicated, alphabetized `{ id, label }[]`.
30
30
  */
31
- export declare function listProviderModels(input: ProviderModelsInput): Promise<ProviderModelsResponse>;
31
+ export declare function listProviderModels(requiredArgs: Pick<ProviderModelsInput, "protocol" | "baseUrl" | "apiKey">, optionalArgs?: Omit<ProviderModelsInput, "protocol" | "baseUrl" | "apiKey">): Promise<ProviderModelsResponse>;
32
32
  //# sourceMappingURL=model-catalog.d.ts.map
@@ -1,19 +1,5 @@
1
- /**
2
- * @module providers/model-catalog
3
- *
4
- * Live model-catalog discovery for BYOK providers (OpenAI-compatible,
5
- * Anthropic, Google, AIHubMix, SenseAudio, plus static seeds for Bedrock and
6
- * an explicit "unsupported" response for Azure). Ported from OD's
7
- * `integrations/provider-models.ts` (`listProviderModels`) with its
8
- * upstream contracts-package type imports repointed at this package's own
9
- * vendored `types.ts`, and its `../connectionTest.js` SSRF-guard /
10
- * secret-redaction imports repointed at this package's own vendored
11
- * `connection-guard.ts` (see that module's doc comment for what was and
12
- * wasn't pulled from the 2,600-line origin file). Logic is otherwise
13
- * unchanged — product-neutral as found (a bare BYOK-protocol model lister,
14
- * no OD-branded strings).
15
- */
16
- import { defaultDnsLookup, redactSecrets, validateBaseUrlResolved } from './connection-guard.js';
1
+ import { redactSecrets } from '@jini-ai/core';
2
+ import { defaultDnsLookup, validateBaseUrlResolved } from './connection-guard.js';
17
3
  import { aihubmixCatalogUrl, aihubmixHeaders, parseAIHubMixCatalog } from './aihubmix.js';
18
4
  import { googleProviderModelsUrl, normalizeGoogleModelId } from './google.js';
19
5
  const PROVIDER_MODELS_TIMEOUT_MS = 12_000;
@@ -164,11 +150,11 @@ function extractAnthropicModels(data) {
164
150
  }
165
151
  function googleModelId(rawName, rawBaseModelId) {
166
152
  if (typeof rawBaseModelId === 'string' && rawBaseModelId.trim()) {
167
- return normalizeGoogleModelId(rawBaseModelId);
153
+ return normalizeGoogleModelId({ model: rawBaseModelId });
168
154
  }
169
155
  if (typeof rawName !== 'string')
170
156
  return '';
171
- return normalizeGoogleModelId(rawName);
157
+ return normalizeGoogleModelId({ model: rawName });
172
158
  }
173
159
  function supportsGoogleGenerateContent(item) {
174
160
  const methods = item
@@ -201,7 +187,7 @@ function providerModelsUrl(protocol, baseUrl, apiKey) {
201
187
  if (protocol === 'aihubmix') {
202
188
  // AIHubMix exposes its chat catalogue on a dedicated endpoint
203
189
  // (GET /api/v1/models?type=llm), not the OpenAI /v1/models route.
204
- return aihubmixCatalogUrl(baseUrl, 'llm');
190
+ return aihubmixCatalogUrl({ baseUrl: baseUrl, type: 'llm' });
205
191
  }
206
192
  if (protocol === 'openai' || protocol === 'senseaudio') {
207
193
  return appendVersionedApiPath(baseUrl, '/models');
@@ -212,7 +198,7 @@ function providerModelsUrl(protocol, baseUrl, apiKey) {
212
198
  return url.toString();
213
199
  }
214
200
  if (protocol === 'google') {
215
- return googleProviderModelsUrl(baseUrl, apiKey);
201
+ return googleProviderModelsUrl({ baseUrl: baseUrl, apiKey: apiKey });
216
202
  }
217
203
  throw new Error(`Unsupported protocol: ${protocol}`);
218
204
  }
@@ -224,7 +210,7 @@ function providerModelsHeaders(protocol, apiKey) {
224
210
  // The catalogue is public — only attach Bearer auth (+ APP-Code) when the
225
211
  // caller actually supplied a key. An empty `Bearer ` would be rejected by
226
212
  // some gateways, so send no headers when the key is blank.
227
- return apiKey.trim() ? aihubmixHeaders(apiKey) : {};
213
+ return apiKey.trim() ? aihubmixHeaders({ apiKey: apiKey }) : {};
228
214
  }
229
215
  if (protocol === 'anthropic') {
230
216
  return {
@@ -242,7 +228,7 @@ function extractModels(protocol, data) {
242
228
  // (e.g. gpt-image-2 -> "image_generation,llm") would otherwise leak in. Those
243
229
  // belong to the dedicated image/video/audio pickers.
244
230
  if (protocol === 'aihubmix')
245
- return parseAIHubMixCatalog(data, { chatOnly: true });
231
+ return parseAIHubMixCatalog({ data: data }, { chatOnly: true });
246
232
  if (protocol === 'openai' || protocol === 'senseaudio')
247
233
  return extractOpenAiModels(data);
248
234
  if (protocol === 'anthropic')
@@ -256,7 +242,8 @@ function extractModels(protocol, data) {
256
242
  * "unsupported" response for Azure), and normalizes every provider's
257
243
  * response envelope into a de-duplicated, alphabetized `{ id, label }[]`.
258
244
  */
259
- export async function listProviderModels(input) {
245
+ export async function listProviderModels(requiredArgs, optionalArgs = {}) {
246
+ const input = { ...optionalArgs, ...requiredArgs };
260
247
  const start = Date.now();
261
248
  if (input.protocol === 'azure') {
262
249
  return {
@@ -266,7 +253,7 @@ export async function listProviderModels(input) {
266
253
  detail: 'Azure OpenAI deployment discovery is not supported from the inference endpoint.',
267
254
  };
268
255
  }
269
- const validated = await validateBaseUrlResolved(input.baseUrl, input.dnsLookup ?? defaultDnsLookup);
256
+ const validated = await validateBaseUrlResolved({ baseUrl: input.baseUrl, lookup: input.dnsLookup ?? defaultDnsLookup });
270
257
  if (validated.error || !validated.parsed) {
271
258
  return {
272
259
  ok: false,
@@ -362,7 +349,7 @@ export async function listProviderModels(input) {
362
349
  kind: statusToKind(response.status),
363
350
  latencyMs,
364
351
  status: response.status,
365
- detail: redactSecrets(detail, [input.apiKey]),
352
+ detail: redactSecrets({ input: detail }, { exactSecrets: [input.apiKey] }),
366
353
  };
367
354
  }
368
355
  if (parseError) {
@@ -371,7 +358,7 @@ export async function listProviderModels(input) {
371
358
  kind: 'unknown',
372
359
  latencyMs,
373
360
  status: response.status,
374
- detail: redactSecrets(parseError, [input.apiKey]),
361
+ detail: redactSecrets({ input: parseError }, { exactSecrets: [input.apiKey] }),
375
362
  };
376
363
  }
377
364
  // Safe: `url` above only resolves for the five protocols
@@ -403,7 +390,7 @@ export async function listProviderModels(input) {
403
390
  ok: false,
404
391
  kind,
405
392
  latencyMs,
406
- detail: redactSecrets(message, [input.apiKey]),
393
+ detail: redactSecrets({ input: message }, { exactSecrets: [input.apiKey] }),
407
394
  };
408
395
  }
409
396
  finally {
@@ -31,5 +31,5 @@ export interface OAuthCallbackListener {
31
31
  * via `onCallback`. The listener self-closes after the first matching
32
32
  * callback OR after `timeoutMs` (default 30 min), whichever comes first.
33
33
  */
34
- export declare function startOAuthCallbackListener(input: StartOAuthCallbackListenerInput): Promise<OAuthCallbackListener>;
34
+ export declare function startOAuthCallbackListener(requiredArgs: Pick<StartOAuthCallbackListenerInput, "host" | "port" | "path" | "expectedState" | "onCallback">, optionalArgs?: Omit<StartOAuthCallbackListenerInput, "host" | "port" | "path" | "expectedState" | "onCallback">): Promise<OAuthCallbackListener>;
35
35
  //# sourceMappingURL=oauth-callback-server.d.ts.map
@@ -9,7 +9,7 @@
9
9
  * Ported from OD's `integrations/xai-oauth-server.ts`, de-branded: the
10
10
  * origin hardcoded xAI's fixed callback port/host/path as module constants
11
11
  * and had the origin product's own name baked into the result-page HTML
12
- * (see `source-map.md` for the exact original strings). Both are now
12
+ * (see `archived provenance ledger` for the exact original strings). Both are now
13
13
  * caller-supplied — `host`/`port`/
14
14
  * `path` are required input fields instead of defaulted constants (a
15
15
  * provider whose OAuth client_id is locked to a specific redirect URI, like
@@ -27,7 +27,8 @@ const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 min
27
27
  * via `onCallback`. The listener self-closes after the first matching
28
28
  * callback OR after `timeoutMs` (default 30 min), whichever comes first.
29
29
  */
30
- export async function startOAuthCallbackListener(input) {
30
+ export async function startOAuthCallbackListener(requiredArgs, optionalArgs = {}) {
31
+ const input = { ...optionalArgs, ...requiredArgs };
31
32
  const { host, port, path: callbackPath } = input;
32
33
  const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
33
34
  let consumed = false;
@@ -25,5 +25,11 @@ export interface ResolvedOAuthCredential {
25
25
  * the refresh call fails. Callers should treat null as "no OAuth available,
26
26
  * fall back to API key / re-login UI".
27
27
  */
28
- export declare function resolveOAuthBearer(config: OAuthPkceProviderConfig, tokenFileName: string, dataDir: string, fetchImpl?: typeof fetch): Promise<ResolvedOAuthCredential | null>;
28
+ export declare function resolveOAuthBearer({ config, tokenFileName, dataDir }: {
29
+ config: OAuthPkceProviderConfig;
30
+ tokenFileName: string;
31
+ dataDir: string;
32
+ }, { fetchImpl }?: {
33
+ fetchImpl?: typeof fetch;
34
+ }): Promise<ResolvedOAuthCredential | null>;
29
35
  //# sourceMappingURL=oauth-credentials.d.ts.map
@@ -21,11 +21,11 @@ import { getStoredOAuthToken, isOAuthTokenExpired, setStoredOAuthToken, } from '
21
21
  * the refresh call fails. Callers should treat null as "no OAuth available,
22
22
  * fall back to API key / re-login UI".
23
23
  */
24
- export async function resolveOAuthBearer(config, tokenFileName, dataDir, fetchImpl) {
25
- const stored = await getStoredOAuthToken(dataDir, tokenFileName);
24
+ export async function resolveOAuthBearer({ config, tokenFileName, dataDir }, { fetchImpl } = {}) {
25
+ const stored = await getStoredOAuthToken({ dataDir: dataDir, fileName: tokenFileName });
26
26
  if (!stored)
27
27
  return null;
28
- if (!isOAuthTokenExpired(stored)) {
28
+ if (!isOAuthTokenExpired({ token: stored })) {
29
29
  return { accessToken: stored.accessToken, source: 'stored' };
30
30
  }
31
31
  // Within skew window — try a refresh. If there's no refresh_token (some
@@ -34,7 +34,7 @@ export async function resolveOAuthBearer(config, tokenFileName, dataDir, fetchIm
34
34
  if (!stored.refreshToken)
35
35
  return null;
36
36
  try {
37
- const fresh = await refreshOAuthPkceToken({
37
+ const fresh = await (({ config, refreshToken, ...optionalArgs }) => refreshOAuthPkceToken({ config, refreshToken }, optionalArgs))({
38
38
  config,
39
39
  refreshToken: stored.refreshToken,
40
40
  ...(fetchImpl ? { fetchImpl } : {}),
@@ -57,7 +57,7 @@ export async function resolveOAuthBearer(config, tokenFileName, dataDir, fetchIm
57
57
  }
58
58
  if (fresh.scope)
59
59
  next.scope = fresh.scope;
60
- await setStoredOAuthToken(dataDir, tokenFileName, next);
60
+ await setStoredOAuthToken({ dataDir: dataDir, fileName: tokenFileName, token: next });
61
61
  return { accessToken: next.accessToken, source: 'refreshed' };
62
62
  }
63
63
  catch {
@@ -61,7 +61,7 @@ export interface CompleteOAuthPkceInput {
61
61
  * exchanges `code` for tokens. Throws if `state` is unknown, expired,
62
62
  * already consumed, or was issued for a different provider.
63
63
  */
64
- export declare function completeOAuthPkce(input: CompleteOAuthPkceInput): Promise<OAuthTokenResponse>;
64
+ export declare function completeOAuthPkce(requiredArgs: Pick<CompleteOAuthPkceInput, "config" | "pending" | "state" | "code">, optionalArgs?: Omit<CompleteOAuthPkceInput, "config" | "pending" | "state" | "code">): Promise<OAuthTokenResponse>;
65
65
  export interface RefreshOAuthPkceInput {
66
66
  config: OAuthPkceProviderConfig;
67
67
  refreshToken: string;
@@ -72,7 +72,7 @@ export interface RefreshOAuthPkceInput {
72
72
  * client_id that originally received it (RFC 6749 §6); since the same fixed
73
73
  * client_id is always used, it doesn't need to be persisted per-token.
74
74
  */
75
- export declare function refreshOAuthPkceToken(input: RefreshOAuthPkceInput): Promise<OAuthTokenResponse>;
75
+ export declare function refreshOAuthPkceToken(requiredArgs: Pick<RefreshOAuthPkceInput, "config" | "refreshToken">, optionalArgs?: Omit<RefreshOAuthPkceInput, "config" | "refreshToken">): Promise<OAuthTokenResponse>;
76
76
  /** Stable provider id used to key an xAI token in any per-provider cache. */
77
77
  export declare const XAI_OAUTH_PROVIDER_ID = "xai";
78
78
  export declare const XAI_OAUTH_REDIRECT_HOST = "127.0.0.1";
@@ -39,16 +39,9 @@ function authServerMetadata(config) {
39
39
  export function beginOAuthPkce(input) {
40
40
  const { config, pending, redirectUri } = input;
41
41
  const codeVerifier = generateCodeVerifier();
42
- const codeChallenge = deriveCodeChallenge(codeVerifier);
42
+ const codeChallenge = deriveCodeChallenge({ verifier: codeVerifier });
43
43
  const state = generateState();
44
- const authorizeUrl = buildAuthorizeUrl({
45
- authServer: authServerMetadata(config),
46
- clientId: config.clientId,
47
- redirectUri,
48
- state,
49
- codeChallenge,
50
- scope: config.scope,
51
- });
44
+ const authorizeUrl = buildAuthorizeUrl({ authServer: authServerMetadata(config), clientId: config.clientId, redirectUri, state, codeChallenge }, { scope: config.scope });
52
45
  const pendingState = {
53
46
  serverId: config.providerId,
54
47
  authServerIssuer: config.issuer,
@@ -59,7 +52,7 @@ export function beginOAuthPkce(input) {
59
52
  scope: config.scope,
60
53
  createdAt: Date.now(),
61
54
  };
62
- pending.put(state, pendingState);
55
+ pending.put({ state: state, value: pendingState });
63
56
  return { authorizeUrl, state };
64
57
  }
65
58
  /**
@@ -68,33 +61,35 @@ export function beginOAuthPkce(input) {
68
61
  * exchanges `code` for tokens. Throws if `state` is unknown, expired,
69
62
  * already consumed, or was issued for a different provider.
70
63
  */
71
- export async function completeOAuthPkce(input) {
72
- const consumed = input.pending.consume(input.state);
64
+ export async function completeOAuthPkce(requiredArgs, optionalArgs = {}) {
65
+ const input = { ...optionalArgs, ...requiredArgs };
66
+ const consumed = input.pending.consume({ state: input.state });
73
67
  if (!consumed) {
74
68
  throw new Error(`${input.config.providerId} OAuth state not found or expired`);
75
69
  }
76
70
  if (consumed.serverId !== input.config.providerId) {
77
71
  throw new Error(`${input.config.providerId} OAuth state mismatch: expected serverId=${input.config.providerId}, got ${consumed.serverId}`);
78
72
  }
79
- return exchangeCodeForToken({
80
- tokenEndpoint: consumed.tokenEndpoint,
81
- clientId: consumed.clientId,
82
- redirectUri: consumed.redirectUri,
83
- code: input.code,
84
- codeVerifier: consumed.codeVerifier,
85
- }, input.fetchImpl ?? fetch);
73
+ return exchangeCodeForToken({ input: {
74
+ tokenEndpoint: consumed.tokenEndpoint,
75
+ clientId: consumed.clientId,
76
+ redirectUri: consumed.redirectUri,
77
+ code: input.code,
78
+ codeVerifier: consumed.codeVerifier,
79
+ } }, { fetchImpl: input.fetchImpl ?? fetch });
86
80
  }
87
81
  /**
88
82
  * Refreshes an existing access token. The refresh_token is bound to the
89
83
  * client_id that originally received it (RFC 6749 §6); since the same fixed
90
84
  * client_id is always used, it doesn't need to be persisted per-token.
91
85
  */
92
- export async function refreshOAuthPkceToken(input) {
93
- return refreshAccessToken({
94
- tokenEndpoint: input.config.tokenEndpoint,
95
- clientId: input.config.clientId,
96
- refreshToken: input.refreshToken,
97
- }, input.fetchImpl ?? fetch);
86
+ export async function refreshOAuthPkceToken(requiredArgs, optionalArgs = {}) {
87
+ const input = { ...optionalArgs, ...requiredArgs };
88
+ return refreshAccessToken({ input: {
89
+ tokenEndpoint: input.config.tokenEndpoint,
90
+ clientId: input.config.clientId,
91
+ refreshToken: input.refreshToken,
92
+ } }, { fetchImpl: input.fetchImpl ?? fetch });
98
93
  }
99
94
  // ---------------------------------------------------------------------------
100
95
  // Concrete preset: the one OAuth+PKCE provider the origin actually shipped.
@@ -22,14 +22,34 @@ export interface OAuthTokenFile {
22
22
  token?: StoredOAuthToken;
23
23
  }
24
24
  /** Coerces a freeform JSON blob into the typed shape, dropping anything that doesn't deserialize cleanly. Used both at read time and as a defensive pass when third-party tooling has hand-edited the file. */
25
- export declare function sanitizeOAuthTokenFile(raw: unknown): OAuthTokenFile;
26
- export declare function readOAuthTokenFile(dataDir: string, fileName: string): Promise<OAuthTokenFile>;
25
+ export declare function sanitizeOAuthTokenFile({ raw }: {
26
+ raw: unknown;
27
+ }): OAuthTokenFile;
28
+ export declare function readOAuthTokenFile({ dataDir, fileName }: {
29
+ dataDir: string;
30
+ fileName: string;
31
+ }): Promise<OAuthTokenFile>;
27
32
  /** Gets the current stored OAuth token for `fileName`, or null when none is stored (or the persisted entry is malformed). */
28
- export declare function getStoredOAuthToken(dataDir: string, fileName: string): Promise<StoredOAuthToken | null>;
33
+ export declare function getStoredOAuthToken({ dataDir, fileName }: {
34
+ dataDir: string;
35
+ fileName: string;
36
+ }): Promise<StoredOAuthToken | null>;
29
37
  /** Atomically replaces the stored OAuth token for `fileName`. */
30
- export declare function setStoredOAuthToken(dataDir: string, fileName: string, token: StoredOAuthToken): Promise<void>;
38
+ export declare function setStoredOAuthToken({ dataDir, fileName, token }: {
39
+ dataDir: string;
40
+ fileName: string;
41
+ token: StoredOAuthToken;
42
+ }): Promise<void>;
31
43
  /** Atomically deletes the stored OAuth token for `fileName`. No-op when absent. */
32
- export declare function clearStoredOAuthToken(dataDir: string, fileName: string): Promise<void>;
44
+ export declare function clearStoredOAuthToken({ dataDir, fileName }: {
45
+ dataDir: string;
46
+ fileName: string;
47
+ }): Promise<void>;
33
48
  /** True when the stored token is past its `expiresAt` (or within `skew` milliseconds of expiring). Returns false when no `expiresAt` is recorded — some providers issue non-expiring tokens. */
34
- export declare function isOAuthTokenExpired(token: StoredOAuthToken, now?: number, skew?: number): boolean;
49
+ export declare function isOAuthTokenExpired({ token }: {
50
+ token: StoredOAuthToken;
51
+ }, { now, skew }?: {
52
+ now?: number;
53
+ skew?: number;
54
+ }): boolean;
35
55
  //# sourceMappingURL=oauth-tokens.d.ts.map
@@ -22,7 +22,7 @@ function isPlainObject(v) {
22
22
  return Boolean(v) && typeof v === 'object' && !Array.isArray(v);
23
23
  }
24
24
  /** Coerces a freeform JSON blob into the typed shape, dropping anything that doesn't deserialize cleanly. Used both at read time and as a defensive pass when third-party tooling has hand-edited the file. */
25
- export function sanitizeOAuthTokenFile(raw) {
25
+ export function sanitizeOAuthTokenFile({ raw }) {
26
26
  if (!isPlainObject(raw))
27
27
  return {};
28
28
  const tok = sanitizeToken(raw.token);
@@ -58,10 +58,10 @@ function sanitizeToken(raw) {
58
58
  out.expiresAt = expiresAt;
59
59
  return out;
60
60
  }
61
- export async function readOAuthTokenFile(dataDir, fileName) {
61
+ export async function readOAuthTokenFile({ dataDir, fileName }) {
62
62
  try {
63
63
  const raw = await readFile(tokenFilePath(dataDir, fileName), 'utf8');
64
- return sanitizeOAuthTokenFile(JSON.parse(raw));
64
+ return sanitizeOAuthTokenFile({ raw: JSON.parse(raw) });
65
65
  }
66
66
  catch (err) {
67
67
  const e = err;
@@ -108,27 +108,27 @@ async function writeTokenFile(dataDir, fileName, next) {
108
108
  return next;
109
109
  }
110
110
  /** Gets the current stored OAuth token for `fileName`, or null when none is stored (or the persisted entry is malformed). */
111
- export async function getStoredOAuthToken(dataDir, fileName) {
112
- const file = await readOAuthTokenFile(dataDir, fileName);
111
+ export async function getStoredOAuthToken({ dataDir, fileName }) {
112
+ const file = await readOAuthTokenFile({ dataDir: dataDir, fileName: fileName });
113
113
  return file.token ?? null;
114
114
  }
115
115
  /** Atomically replaces the stored OAuth token for `fileName`. */
116
- export async function setStoredOAuthToken(dataDir, fileName, token) {
116
+ export async function setStoredOAuthToken({ dataDir, fileName, token }) {
117
117
  await withLock(`${dataDir}\0${fileName}`, async () => {
118
118
  await writeTokenFile(dataDir, fileName, { token });
119
119
  });
120
120
  }
121
121
  /** Atomically deletes the stored OAuth token for `fileName`. No-op when absent. */
122
- export async function clearStoredOAuthToken(dataDir, fileName) {
122
+ export async function clearStoredOAuthToken({ dataDir, fileName }) {
123
123
  await withLock(`${dataDir}\0${fileName}`, async () => {
124
- const file = await readOAuthTokenFile(dataDir, fileName);
124
+ const file = await readOAuthTokenFile({ dataDir: dataDir, fileName: fileName });
125
125
  if (!file.token)
126
126
  return;
127
127
  await writeTokenFile(dataDir, fileName, {});
128
128
  });
129
129
  }
130
130
  /** True when the stored token is past its `expiresAt` (or within `skew` milliseconds of expiring). Returns false when no `expiresAt` is recorded — some providers issue non-expiring tokens. */
131
- export function isOAuthTokenExpired(token, now = Date.now(), skew = 120_000) {
131
+ export function isOAuthTokenExpired({ token }, { now = Date.now(), skew = 120_000 } = {}) {
132
132
  if (typeof token.expiresAt !== 'number')
133
133
  return false;
134
134
  return token.expiresAt - skew <= now;