@vedmalex/ai-connect 0.2.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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1266 -0
  3. package/dist/browser/index.js +6690 -0
  4. package/dist/browser/index.js.map +7 -0
  5. package/dist/bun/index.js +10073 -0
  6. package/dist/bun/index.js.map +7 -0
  7. package/dist/bun/local.js +9753 -0
  8. package/dist/bun/local.js.map +7 -0
  9. package/dist/node/index.js +10073 -0
  10. package/dist/node/index.js.map +7 -0
  11. package/dist/node/local.js +9753 -0
  12. package/dist/node/local.js.map +7 -0
  13. package/dist/types/acp-presets.d.ts +2 -0
  14. package/dist/types/acp-presets.d.ts.map +1 -0
  15. package/dist/types/acp.d.ts +39 -0
  16. package/dist/types/acp.d.ts.map +1 -0
  17. package/dist/types/browser.d.ts +5 -0
  18. package/dist/types/browser.d.ts.map +1 -0
  19. package/dist/types/bun.d.ts +2 -0
  20. package/dist/types/bun.d.ts.map +1 -0
  21. package/dist/types/catalog.d.ts +33 -0
  22. package/dist/types/catalog.d.ts.map +1 -0
  23. package/dist/types/cli-presets.d.ts +12 -0
  24. package/dist/types/cli-presets.d.ts.map +1 -0
  25. package/dist/types/cli.d.ts +20 -0
  26. package/dist/types/cli.d.ts.map +1 -0
  27. package/dist/types/client.d.ts +3 -0
  28. package/dist/types/client.d.ts.map +1 -0
  29. package/dist/types/config.d.ts +30 -0
  30. package/dist/types/config.d.ts.map +1 -0
  31. package/dist/types/default-handlers.d.ts +5 -0
  32. package/dist/types/default-handlers.d.ts.map +1 -0
  33. package/dist/types/errors.d.ts +15 -0
  34. package/dist/types/errors.d.ts.map +1 -0
  35. package/dist/types/fanout.d.ts +20 -0
  36. package/dist/types/fanout.d.ts.map +1 -0
  37. package/dist/types/files.d.ts +42 -0
  38. package/dist/types/files.d.ts.map +1 -0
  39. package/dist/types/image.d.ts +40 -0
  40. package/dist/types/image.d.ts.map +1 -0
  41. package/dist/types/index.browser.d.ts +18 -0
  42. package/dist/types/index.browser.d.ts.map +1 -0
  43. package/dist/types/index.d.ts +19 -0
  44. package/dist/types/index.d.ts.map +1 -0
  45. package/dist/types/local-handlers.d.ts +12 -0
  46. package/dist/types/local-handlers.d.ts.map +1 -0
  47. package/dist/types/local.d.ts +6 -0
  48. package/dist/types/local.d.ts.map +1 -0
  49. package/dist/types/logging.d.ts +8 -0
  50. package/dist/types/logging.d.ts.map +1 -0
  51. package/dist/types/mock-gateway.d.ts +97 -0
  52. package/dist/types/mock-gateway.d.ts.map +1 -0
  53. package/dist/types/model-reference.d.ts +85 -0
  54. package/dist/types/model-reference.d.ts.map +1 -0
  55. package/dist/types/node.d.ts +2 -0
  56. package/dist/types/node.d.ts.map +1 -0
  57. package/dist/types/probe.d.ts +71 -0
  58. package/dist/types/probe.d.ts.map +1 -0
  59. package/dist/types/router.d.ts +41 -0
  60. package/dist/types/router.d.ts.map +1 -0
  61. package/dist/types/runtime.d.ts +6 -0
  62. package/dist/types/runtime.d.ts.map +1 -0
  63. package/dist/types/server-presets.d.ts +9 -0
  64. package/dist/types/server-presets.d.ts.map +1 -0
  65. package/dist/types/server.d.ts +12 -0
  66. package/dist/types/server.d.ts.map +1 -0
  67. package/dist/types/types.d.ts +1346 -0
  68. package/dist/types/types.d.ts.map +1 -0
  69. package/package.json +94 -0
@@ -0,0 +1,1346 @@
1
+ export type ProviderId = string;
2
+ export type TransportKind = "api" | "acp" | "cli" | "server";
3
+ export type RuntimeKind = "browser" | "local";
4
+ export type RouteRuntime = "browser" | "local" | "universal";
5
+ export type OperationKind = "text" | "image" | "file";
6
+ export type ClientOperationName = "generate" | "stream" | "verify" | "discoverAcpModels" | "discoverModels" | "checkHealth" | "probeModels";
7
+ export type AcpPermissionMode = "deny-all" | "approve-reads" | "approve-all";
8
+ export type RoutingStrategy = "priority" | "round-robin" | "weighted-round-robin" | "failover";
9
+ export type RouteHealthState = "ready" | "cooling_down" | "degraded" | "unavailable";
10
+ export type AiConnectErrorCode = "rate_limit" | "quota_exhausted" | "invalid_credentials" | "auth_error" | "unsupported_capability" | "temporary_unavailable" | "local_harness_unavailable" | "validation_error" | "not_supported" | "aborted" | "timeout" | "fanout_limit";
11
+ /**
12
+ * Why a derived abort signal fired. `caller` → user/consumer cancelled (partials discarded);
13
+ * `timeout` → an operation deadline elapsed. Used by `mapAbortError` to pick the terminal code.
14
+ */
15
+ export type AbortReason = "caller" | "timeout";
16
+ export type FallbackAction = "retry" | "rotate-credential" | "rotate-account" | "fallback-model" | "fallback-transport" | "fallback-provider";
17
+ export type MessageRole = "system" | "user" | "assistant" | "tool";
18
+ export type PortableFileKind = "path" | "remote" | "data-url" | "browser-file" | "browser-blob";
19
+ export type ThinkingMode = "enabled" | "disabled" | "adaptive";
20
+ export type ThinkingEffort = "low" | "medium" | "high" | "max";
21
+ export type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
22
+ export type ImageSizePreset = "1024x1024" | "1280x720" | "720x1280" | "1216x896" | "1200x1696" | "848x1200" | "600x848" | "424x600" | "597x822" | "747x1122" | "822x1122" | "897x1479" | "1122x1797" | "1536x1024" | "1024x1536" | "auto";
23
+ export interface RouteCapabilities {
24
+ browserSafe: boolean;
25
+ localOnly: boolean;
26
+ requiresFilesystem: boolean;
27
+ requiresInstalledBinary: boolean;
28
+ requiresAuthenticatedSession: boolean;
29
+ supportsStreaming: boolean;
30
+ supportsToolSchema: boolean;
31
+ supportsToolExecution: boolean;
32
+ supportsClientToolExecution: boolean;
33
+ supportsFileUpload: boolean;
34
+ supportsFileOutput: boolean;
35
+ supportsImageInput: boolean;
36
+ supportsImageOutput: boolean;
37
+ supportsProfileVerification: boolean;
38
+ supportsCredentialRotation: boolean;
39
+ supportsAccountRotation: boolean;
40
+ }
41
+ /**
42
+ * Generalized execution-context mode (C7 / CD-10). `workspace` lets ai-connect inject its
43
+ * ambient ACP launch context (skills/rules/cwd); `clean` suppresses ALL ai-connect-injected
44
+ * ambient — only consumer messages/attachments + explicit route config (systemPrompt /
45
+ * defaultResponseFormat) reach the wire (INV-CLEAN-1).
46
+ */
47
+ export type ContextMode = "workspace" | "clean";
48
+ /**
49
+ * ACP launch context mode. Re-rooted onto {@link ContextMode} as an identity-preserving alias
50
+ * (R22): the underlying string-literal union is byte-identical, so every existing
51
+ * `=== "clean"` / `=== "workspace"` narrowing in acp.ts continues to typecheck unchanged.
52
+ */
53
+ export type AcpContextMode = ContextMode;
54
+ /**
55
+ * Per-route model-allowlist enforcement (C7). `strict` (default) → only `advertisedModels` may
56
+ * be requested; an undeclared `routeHints.model` DROPS the route (never silently billed).
57
+ * `shortlist` → `advertisedModels` is advisory; an undeclared model is passed through verbatim.
58
+ */
59
+ export type ModelAllowlistMode = "strict" | "shortlist";
60
+ /**
61
+ * How `resolveRouteRefs`/`resolveRouteSelectors` treat a selector that matches no route (C7).
62
+ * `error` (default) → throw (existing behaviour, byte-identical for current callers);
63
+ * `default` → substitute the configured default route for EACH unmatched selector (OQ-8
64
+ * per-unmatched substitution); `off` → silently drop the unmatched selector (degrade).
65
+ */
66
+ export type UnknownSelectorPolicy = "error" | "default" | "off";
67
+ export type AcpSkillsMode = "default" | "disabled";
68
+ export type CliTransportPresetId = "gemini" | "qwen" | "claude" | "openclaude" | "codex";
69
+ export type CliDiscoveryVia = "none" | "acp";
70
+ export interface AcpLaunchOptionsInput {
71
+ contextMode?: AcpContextMode;
72
+ skillsMode?: AcpSkillsMode;
73
+ }
74
+ export interface AcpLaunchOptions {
75
+ contextMode: AcpContextMode;
76
+ skillsMode: AcpSkillsMode;
77
+ }
78
+ export interface CliDiscoveryAcpOptionsInput {
79
+ providerId?: string;
80
+ transportId?: string;
81
+ auth?: {
82
+ methodId: string;
83
+ params?: Record<string, unknown>;
84
+ };
85
+ launch?: AcpLaunchOptionsInput;
86
+ }
87
+ export interface CliDiscoveryOptionsInput {
88
+ via?: CliDiscoveryVia;
89
+ acp?: CliDiscoveryAcpOptionsInput;
90
+ }
91
+ export interface CliJsonLineSelectorInput {
92
+ path: string;
93
+ wherePath?: string;
94
+ whereEquals?: string | number | boolean;
95
+ }
96
+ export interface CliJsonParserInput {
97
+ kind: "json";
98
+ textPath: string;
99
+ errorPath?: string;
100
+ usagePath?: string;
101
+ }
102
+ export interface CliJsonlParserInput {
103
+ kind: "jsonl";
104
+ text: CliJsonLineSelectorInput;
105
+ error?: CliJsonLineSelectorInput;
106
+ usage?: CliJsonLineSelectorInput;
107
+ }
108
+ export type CliTransportParserInput = CliJsonParserInput | CliJsonlParserInput;
109
+ export interface CliDiscoveryAcpOptions {
110
+ providerId?: string;
111
+ transportId?: string;
112
+ auth?: {
113
+ methodId: string;
114
+ params: Record<string, unknown>;
115
+ };
116
+ launch?: AcpLaunchOptions;
117
+ }
118
+ export interface CliDiscoveryOptions {
119
+ via: CliDiscoveryVia;
120
+ acp?: CliDiscoveryAcpOptions;
121
+ }
122
+ export interface CliTransportOptionsInput {
123
+ preset?: CliTransportPresetId;
124
+ argsTemplate?: string[];
125
+ parser?: CliTransportParserInput;
126
+ discovery?: CliDiscoveryOptionsInput;
127
+ }
128
+ export interface CliJsonLineSelector {
129
+ path: string;
130
+ wherePath?: string;
131
+ whereEquals?: string | number | boolean;
132
+ }
133
+ export interface CliJsonParser {
134
+ kind: "json";
135
+ textPath: string;
136
+ errorPath?: string;
137
+ usagePath?: string;
138
+ }
139
+ export interface CliJsonlParser {
140
+ kind: "jsonl";
141
+ text: CliJsonLineSelector;
142
+ error?: CliJsonLineSelector;
143
+ usage?: CliJsonLineSelector;
144
+ }
145
+ export type CliTransportParser = CliJsonParser | CliJsonlParser;
146
+ export interface CliTransportOptions {
147
+ preset?: CliTransportPresetId;
148
+ argsTemplate?: string[];
149
+ parser?: CliTransportParser;
150
+ discovery?: CliDiscoveryOptions;
151
+ }
152
+ export interface TransportDescriptorInput {
153
+ kind: TransportKind;
154
+ id?: string;
155
+ command?: string;
156
+ baseUrl?: string;
157
+ cli?: CliTransportOptionsInput;
158
+ auth?: {
159
+ methodId: string;
160
+ params?: Record<string, unknown>;
161
+ };
162
+ launch?: AcpLaunchOptionsInput;
163
+ }
164
+ export interface CredentialConfigInput {
165
+ id?: string;
166
+ apiKey?: string;
167
+ apiKeyEnv?: string;
168
+ apiKeyDelimiter?: string;
169
+ source?: string;
170
+ weight?: number;
171
+ metadata?: Record<string, string>;
172
+ }
173
+ export interface VerificationConfigInput {
174
+ env?: string[];
175
+ command?: string;
176
+ session?: string;
177
+ }
178
+ export interface AccountConfigInput {
179
+ id?: string;
180
+ transport: TransportKind | TransportDescriptorInput;
181
+ profile?: string;
182
+ runtime?: RouteRuntime;
183
+ /**
184
+ * Declared models. Each entry is a bare id string (back-compat) OR a `{ id, contextWindow }`
185
+ * object (C4). A bare string inherits the account-level `contextWindow`; an object overrides
186
+ * it for that model only.
187
+ */
188
+ models: ModelInput[];
189
+ /** Account-level default context window inherited by string-form `models` entries (C4). */
190
+ contextWindow?: number;
191
+ credentials?: CredentialConfigInput[];
192
+ capabilities?: Partial<RouteCapabilities>;
193
+ verify?: VerificationConfigInput;
194
+ weight?: number;
195
+ priority?: number;
196
+ enabled?: boolean;
197
+ /** Model-allowlist enforcement for this account's routes (C7; default `strict`). */
198
+ modelAllowlistMode?: ModelAllowlistMode;
199
+ /**
200
+ * Per-route default response format injected onto a candidate ONLY when the caller did not
201
+ * supply `parameters.responseFormat` (C7 / R14, idempotent on retry+fallback). Preserved even
202
+ * in `clean` context mode (CD-15 — clean suppresses ambient, not explicit config).
203
+ */
204
+ defaultResponseFormat?: GenerateResponseFormat;
205
+ /**
206
+ * Per-route system prompt injected as a leading system message ONLY when the caller authored
207
+ * no system message (C7 / R14). Preserved in `clean` mode (explicit config, not ambient).
208
+ */
209
+ systemPrompt?: string;
210
+ /** Execution-context mode for this account's routes (C7; default `workspace`). */
211
+ contextMode?: ContextMode;
212
+ }
213
+ export interface ProviderConfigInput {
214
+ accounts: AccountConfigInput[];
215
+ }
216
+ export interface OperationRoutingInput {
217
+ strategy?: RoutingStrategy;
218
+ pool?: string[];
219
+ }
220
+ export interface RoutingFallbackInput {
221
+ on?: Partial<Record<AiConnectErrorCode, FallbackAction[]>>;
222
+ cooldownMs?: Partial<Record<AiConnectErrorCode, number>>;
223
+ }
224
+ export interface RoutingRetryInput {
225
+ maxAttempts?: Partial<Record<AiConnectErrorCode, number>>;
226
+ delayMs?: Partial<Record<AiConnectErrorCode, number>>;
227
+ }
228
+ /**
229
+ * Selector-resolution policy (C7 / OQ-8). Controls how an unmatched route selector is handled
230
+ * when expanding `routeHints.pool`/operation pools. Default behaviour (omitted) is `error`,
231
+ * preserving byte-identical semantics for every existing caller.
232
+ */
233
+ export interface RouteResolutionConfigInput {
234
+ unknownSelector?: UnknownSelectorPolicy;
235
+ /**
236
+ * Route ref (any alias) substituted for each unmatched selector when
237
+ * `unknownSelector === "default"`. `defineConfig` fails fast if this does not resolve to
238
+ * exactly one route (INV-ROUTE — fail-fast on ambiguous/missing default).
239
+ */
240
+ defaultRouteId?: string;
241
+ }
242
+ export interface NormalizedRouteResolutionConfig {
243
+ unknownSelector: UnknownSelectorPolicy;
244
+ /** Resolved single route id used for `default` substitution; absent unless policy is `default`. */
245
+ defaultRouteId?: string;
246
+ }
247
+ export interface RoutingConfigInput {
248
+ strategy?: RoutingStrategy;
249
+ operations?: Partial<Record<OperationKind, string[] | OperationRoutingInput>>;
250
+ fallback?: RoutingFallbackInput;
251
+ retry?: RoutingRetryInput;
252
+ shuffleOnInit?: boolean;
253
+ resolution?: RouteResolutionConfigInput;
254
+ }
255
+ export interface AiConnectConfigInput {
256
+ providers: Record<string, ProviderConfigInput>;
257
+ routing?: RoutingConfigInput;
258
+ }
259
+ export interface PortableFile {
260
+ id: string;
261
+ kind: PortableFileKind;
262
+ name: string;
263
+ mimeType?: string;
264
+ size?: number;
265
+ source: unknown;
266
+ }
267
+ export interface RemoteFileReferenceInput {
268
+ id?: string;
269
+ providerFileId?: string;
270
+ uri?: string;
271
+ name?: string;
272
+ mimeType?: string;
273
+ size?: number;
274
+ }
275
+ export type PortableFileInput = PortableFile | RemoteFileReferenceInput | string | Blob | File;
276
+ /**
277
+ * Coarse multimodal category derived from a portable file's MIME type / name.
278
+ * `document` covers PDFs (and any other SUPPORTED_DOCUMENT_MIME_TYPES member);
279
+ * `image` covers `image/*`; `text` covers text-extractable resources; everything
280
+ * else is `other`. (C6 — UR-003/UR-012.)
281
+ */
282
+ export type PortableFileCategory = "image" | "document" | "text" | "other";
283
+ /**
284
+ * The single decode product of `materializePortableFile` (C6). One pass over a
285
+ * portable file resolves the category + MIME type and, depending on what the
286
+ * source offers, populates exactly the carriers a provider builder needs:
287
+ * `base64` (raw, no data-url prefix) and `dataUrl` for inline images/PDFs,
288
+ * `uri` for remote references, `text` for text-extractable resources, and
289
+ * `providerFileId` when a Files-API upload has already produced one. Builders
290
+ * pick the carrier their wire shape requires; no builder re-decodes.
291
+ */
292
+ export interface PortableFilePayload {
293
+ category: PortableFileCategory;
294
+ mimeType: string;
295
+ name: string;
296
+ base64?: string;
297
+ dataUrl?: string;
298
+ uri?: string;
299
+ text?: string;
300
+ providerFileId?: string;
301
+ }
302
+ export interface ToolCallInput {
303
+ id: string;
304
+ name: string;
305
+ arguments: Record<string, unknown>;
306
+ }
307
+ export interface MessageInput {
308
+ role: MessageRole;
309
+ content: string;
310
+ toolCalls?: ToolCallInput[];
311
+ toolCallId?: string;
312
+ toolName?: string;
313
+ isError?: boolean;
314
+ data?: unknown;
315
+ }
316
+ export interface GenerateToolDefinition {
317
+ type: "function";
318
+ function: {
319
+ name: string;
320
+ description?: string;
321
+ parameters?: Record<string, unknown>;
322
+ };
323
+ }
324
+ export type GenerateToolChoice = "auto" | "required" | "none" | {
325
+ type: "function";
326
+ name: string;
327
+ };
328
+ export interface ClientToolContext {
329
+ route: NormalizedRoute;
330
+ request: NormalizedGenerateRequest;
331
+ runtime: RuntimeEnvironment;
332
+ toolCall: ToolCallInput;
333
+ messages: MessageInput[];
334
+ workingDirectory?: string;
335
+ }
336
+ export type ClientToolExecutionResult = string | {
337
+ content?: string;
338
+ data?: unknown;
339
+ isError?: boolean;
340
+ };
341
+ export interface ClientToolDefinition extends GenerateToolDefinition {
342
+ execute: (args: Record<string, unknown>, context: ClientToolContext) => ClientToolExecutionResult | Promise<ClientToolExecutionResult>;
343
+ }
344
+ export type ClientToolSelection = string | ClientToolDefinition;
345
+ export type GenerateResponseFormat = {
346
+ type: "text";
347
+ } | {
348
+ type: "json_object";
349
+ } | {
350
+ type: "json_schema";
351
+ name?: string;
352
+ schema: Record<string, unknown>;
353
+ strict?: boolean;
354
+ } | {
355
+ type: "native";
356
+ value: unknown;
357
+ };
358
+ export interface SafetySetting {
359
+ category: string;
360
+ threshold: string;
361
+ }
362
+ export interface GenerateThinkingOptions {
363
+ mode?: ThinkingMode;
364
+ enabled?: boolean;
365
+ budgetTokens?: number;
366
+ effort?: ThinkingEffort;
367
+ includeThoughts?: boolean;
368
+ }
369
+ export interface GenerateParameters {
370
+ maxTokens?: number;
371
+ temperature?: number;
372
+ topP?: number;
373
+ topK?: number;
374
+ stop?: string | string[];
375
+ seed?: number;
376
+ candidateCount?: number;
377
+ presencePenalty?: number;
378
+ frequencyPenalty?: number;
379
+ responseFormat?: GenerateResponseFormat;
380
+ tools?: GenerateToolDefinition[];
381
+ toolChoice?: GenerateToolChoice;
382
+ parallelToolCalls?: boolean;
383
+ thinking?: GenerateThinkingOptions;
384
+ safetySettings?: SafetySetting[];
385
+ metadata?: Record<string, unknown>;
386
+ extra?: Record<string, unknown>;
387
+ providerOptions?: Partial<Record<ProviderId, Record<string, unknown>>>;
388
+ }
389
+ export interface RouteHints {
390
+ pool?: string[];
391
+ excludeRouteIds?: string[];
392
+ preferredProviders?: string[];
393
+ requiredCapabilities?: Partial<RouteCapabilities>;
394
+ strategy?: RoutingStrategy;
395
+ /**
396
+ * Request-level model override (CD-8 — the SINGLE request-level model knob; there is NO
397
+ * `GenerateRequest.model`). On a `strict` route an undeclared model is DROPPED (never billed,
398
+ * INV-ROUTE-1); on a `shortlist` route it is passed through verbatim on a synthetic route copy
399
+ * that PRESERVES the original `route.id` (R12 — never fragments health/cursors).
400
+ */
401
+ model?: string;
402
+ }
403
+ /**
404
+ * Client-side fan-out throttle (C9 / UR-013). All fields OPTIONAL — an unset field is unbounded
405
+ * (normalized to {@link Number.POSITIVE_INFINITY}). `maxConcurrency` caps simultaneous in-flight
406
+ * calls (semaphore + FIFO fairness); `requestsPerSecond` is a `runtime.now()`-driven token bucket
407
+ * (deterministic, never wall-clock); `maxCalls` is a hard LIFETIME ceiling — exhausting it throws
408
+ * {@link AiConnectErrorCode} `fanout_limit` BEFORE route selection (INV-FANOUT-1 / R16), so it never
409
+ * pollutes route health.
410
+ */
411
+ export interface FanoutPolicy {
412
+ maxConcurrency?: number;
413
+ requestsPerSecond?: number;
414
+ maxCalls?: number;
415
+ }
416
+ /** Normalized {@link FanoutPolicy} — every field resolved; `POSITIVE_INFINITY` means unbounded. */
417
+ export interface NormalizedFanoutPolicy {
418
+ maxConcurrency: number;
419
+ requestsPerSecond: number;
420
+ maxCalls: number;
421
+ }
422
+ /** A live fan-out limiter instance (created by `createFanoutLimiter`). */
423
+ export interface FanoutLimiter {
424
+ /**
425
+ * Acquire one slot, honoring concurrency + rate + the lifetime `maxCalls` ceiling. Resolves to a
426
+ * release function (call it exactly once, in a `finally`). Rejects with `fanout_limit` when the
427
+ * lifetime ceiling is exhausted. An optional `signal` rejects a queued waiter on abort.
428
+ */
429
+ acquire(signal?: AbortSignal): Promise<() => void>;
430
+ /** Point-in-time counters (for diagnostics / DST assertions). */
431
+ stats(): {
432
+ inFlight: number;
433
+ queued: number;
434
+ callsStarted: number;
435
+ maxConcurrency: number;
436
+ requestsPerSecond: number;
437
+ maxCalls: number;
438
+ };
439
+ }
440
+ /**
441
+ * Neutral query passed to a {@link ModelSelector} hook (C9 / UR-014). Carries the prompt surface and
442
+ * routing intent but NO secrets — the hook is consumer-supplied and may be LLM-backed (bs-search).
443
+ */
444
+ export interface ModelSelectorInput {
445
+ text: string;
446
+ messages: MessageInput[];
447
+ operation: OperationKind;
448
+ routeHints?: RouteHints;
449
+ }
450
+ /**
451
+ * One eligible candidate offered to a {@link ModelSelector} (C9). Secret-free: `routeId` identifies
452
+ * the route without exposing credentials/baseUrl. Built by the router's `candidateModels()` projector.
453
+ * `capabilities` is the client-safe {@link PublicRouteCapabilities} subset (INV-PROJ-1) — internal
454
+ * routing flags (localOnly, requiresFilesystem, the requires-/rotation flags) are NEVER exposed here.
455
+ */
456
+ export interface CandidateModel {
457
+ model: string;
458
+ provider: ProviderId;
459
+ routeId: string;
460
+ transportKind: TransportKind;
461
+ capabilities: PublicRouteCapabilities;
462
+ }
463
+ /**
464
+ * Consumer-supplied pre-routing model-selection hook (C9 / UR-014 / OQ-11). Receives the neutral
465
+ * {@link ModelSelectorInput} and the eligible {@link CandidateModel}s; returns a chosen model id (or
466
+ * `undefined` to defer to normal routing). An explicit `routeHints.model` always BEATS this hook
467
+ * (the hook is not even invoked). A thrown/rejected selector FAILS CLOSED to `validation_error` by
468
+ * default (opt `failOpen` ignores it and falls through to normal routing).
469
+ */
470
+ export type ModelSelector = (question: ModelSelectorInput, candidateModels: CandidateModel[]) => string | undefined | Promise<string | undefined>;
471
+ export interface GenerateImageOptions {
472
+ size?: ImageSizePreset | string;
473
+ rawPrompt?: boolean;
474
+ aspectRatio?: string;
475
+ quality?: string;
476
+ imageSize?: string;
477
+ style?: string;
478
+ sourceImage?: PortableFileInput;
479
+ mask?: PortableFileInput;
480
+ referenceImages?: PortableFileInput[];
481
+ }
482
+ export interface GenerateRequest {
483
+ operation?: OperationKind;
484
+ messages: MessageInput[];
485
+ attachments?: PortableFileInput[];
486
+ clientTools?: ClientToolSelection[];
487
+ parameters?: GenerateParameters;
488
+ routeHints?: RouteHints;
489
+ logContext?: Record<string, unknown>;
490
+ workingDirectory?: string;
491
+ image?: GenerateImageOptions;
492
+ /**
493
+ * Per-request fan-out throttle (C9). Merged per-field OVER the client-level default
494
+ * (`CreateClientOptions.fanout`). The per-request limiter is a request-SCOPED instance — it never
495
+ * mutates the shared client limiter (R15 / per-request-fanout-overrides-without-leaking).
496
+ */
497
+ fanout?: FanoutPolicy;
498
+ }
499
+ export interface NormalizedGenerateImageOptions extends Omit<GenerateImageOptions, "sourceImage" | "mask" | "referenceImages"> {
500
+ sourceImage?: PortableFile;
501
+ mask?: PortableFile;
502
+ referenceImages?: PortableFile[];
503
+ }
504
+ export interface NormalizedGenerateRequest extends Omit<GenerateRequest, "operation" | "attachments" | "image"> {
505
+ operation: OperationKind;
506
+ attachments: PortableFile[];
507
+ clientTools?: ClientToolDefinition[];
508
+ image?: NormalizedGenerateImageOptions;
509
+ }
510
+ export interface UsageModelBreakdown {
511
+ modelId: string;
512
+ name?: string;
513
+ inputTokens?: number;
514
+ outputTokens?: number;
515
+ totalTokens?: number;
516
+ reasoningTokens?: number;
517
+ cachedReadTokens?: number;
518
+ }
519
+ export interface UsageCostInfo {
520
+ amount: number;
521
+ currency?: string;
522
+ }
523
+ export interface UsageInfo {
524
+ inputTokens?: number;
525
+ outputTokens?: number;
526
+ reasoningTokens?: number;
527
+ totalTokens?: number;
528
+ cachedReadTokens?: number;
529
+ contextWindowUsed?: number;
530
+ contextWindowSize?: number;
531
+ durationMs?: number;
532
+ /**
533
+ * Count of successful usage-bearing model calls. Seeded as +1 per reporting
534
+ * call (only when usage is actually reported) and SUMMED by usage merges.
535
+ */
536
+ calls?: number;
537
+ cost?: UsageCostInfo;
538
+ modelUsage?: UsageModelBreakdown[];
539
+ }
540
+ export interface RouteAttempt {
541
+ routeId: string;
542
+ handlerKey: string;
543
+ errorCode: AiConnectErrorCode;
544
+ message: string;
545
+ }
546
+ export interface GenerateResult {
547
+ route: NormalizedRoute;
548
+ text?: string;
549
+ data?: unknown;
550
+ attachments: PortableFile[];
551
+ toolCalls?: ToolCallInput[];
552
+ usage?: UsageInfo;
553
+ warnings: string[];
554
+ attempts: RouteAttempt[];
555
+ }
556
+ /**
557
+ * Stream event union (CD-2). `delta` carries an incremental token (SSE/ACP producers, C9);
558
+ * `result` is the terminal success; `paused` is the terminal pause that KEEPS the accumulated
559
+ * partial. `delta` and `result` may interleave; `paused` and `result` are mutually-exclusive
560
+ * terminals. Abort, by contrast, THROWS and discards partials (it never yields `paused`).
561
+ */
562
+ export type GenerateStreamEvent = {
563
+ type: "delta";
564
+ text: string;
565
+ } | {
566
+ type: "result";
567
+ result: GenerateResult;
568
+ } | {
569
+ type: "paused";
570
+ result: GenerateResult;
571
+ };
572
+ /**
573
+ * Caller-supplied cancellation/timeout options (CD-3, CD-6). `signal` aborts (partials
574
+ * discarded → `AiConnectError('aborted')`). `pauseSignal` is a SEPARATE signal: in `stream()`
575
+ * it stops reading and yields a terminal `{type:'paused'}` keeping partials; in `generate()`
576
+ * a mid-call pause degenerates to `'aborted'` (a non-streamed call cannot retain a partial).
577
+ * `timeoutMs` overrides the per-op tier default; `<=0`/`Infinity` disables the timer.
578
+ */
579
+ export interface GenerateCallOptions {
580
+ signal?: AbortSignal;
581
+ pauseSignal?: AbortSignal;
582
+ timeoutMs?: number;
583
+ }
584
+ /** Per-operation timeout tier defaults (CD-6). */
585
+ export interface OperationTimeoutDefaults {
586
+ /** generate / stream — default 120_000. */
587
+ generateMs?: number;
588
+ /** verify / discover* / checkHealth / probeModels — default 12_000. */
589
+ probeMs?: number;
590
+ }
591
+ /**
592
+ * The derived cancellation context threaded to handlers (CD-3, CD-4). `signal` is the MERGED
593
+ * signal (caller-signal ⊕ op-timeout) — handlers forward THIS into fetch/child-kill, never the
594
+ * raw caller signal. `pauseSignal` is passed through untouched. `reason` is set exactly once
595
+ * (first-writer-wins) so the client maps the thrown code deterministically.
596
+ */
597
+ export interface AbortContext {
598
+ signal: AbortSignal;
599
+ pauseSignal?: AbortSignal;
600
+ reason?: AbortReason;
601
+ }
602
+ export interface VerificationIssue {
603
+ code: "runtime_mismatch" | "missing_env" | "missing_command" | "missing_session" | "handler_issue";
604
+ message: string;
605
+ }
606
+ export interface VerificationRouteReport {
607
+ routeId: string;
608
+ ok: boolean;
609
+ issues: VerificationIssue[];
610
+ }
611
+ export interface VerificationReport {
612
+ ok: boolean;
613
+ routes: VerificationRouteReport[];
614
+ }
615
+ /**
616
+ * Per-token / per-request pricing for a model (C4). All components OPTIONAL; a missing
617
+ * component is unknown (NOT zero). `parseModelPricing` populates this from a raw provider
618
+ * record; `detectModelFree` treats all-defined-components-=== 0 as free.
619
+ */
620
+ export interface ModelPricing {
621
+ prompt?: number;
622
+ completion?: number;
623
+ request?: number;
624
+ image?: number;
625
+ currency?: string;
626
+ }
627
+ export interface AcpModelInfo {
628
+ modelId: string;
629
+ name: string;
630
+ description?: string;
631
+ canonicalModelId?: string;
632
+ /** Discovered context-window length (tokens). Populated from the raw model record (C4). */
633
+ contextLength?: number;
634
+ /** Whether the model is free (`:free` suffix or all-defined-pricing-components === 0) (C4). */
635
+ free?: boolean;
636
+ /** Parsed pricing block, when the provider record advertised one (C4). */
637
+ pricing?: ModelPricing;
638
+ metadata?: Record<string, unknown>;
639
+ }
640
+ /**
641
+ * A curated reference-table row keyed by a normalized model key (C4). `contextLength` is the
642
+ * known context window; `free`/`pricing` are optional curated facts. See `MODEL_REFERENCE`.
643
+ */
644
+ export interface ModelReferenceEntry {
645
+ key: string;
646
+ contextLength: number;
647
+ free?: boolean;
648
+ pricing?: ModelPricing;
649
+ }
650
+ /**
651
+ * The resolved context window + the source it came from (C4 / INV-CTX-1). `source` records
652
+ * precedence: `discovered` (live) > `reference` (curated table) > `configured` (per-model
653
+ * config) > `default` (flat 8192). `cached` is `true` when the value was served from the
654
+ * client's per-(baseUrl|transportId)::model cache.
655
+ */
656
+ export interface ModelContextResolution {
657
+ contextWindow: number;
658
+ source: "discovered" | "reference" | "configured" | "default";
659
+ model: string;
660
+ cached: boolean;
661
+ }
662
+ /**
663
+ * Input accepted by `AiConnectClient.resolveModelContext` (C4). Either a bare model id, or a
664
+ * provider+model pair with an optional `baseUrl`/`transportId` that scopes the cache key.
665
+ */
666
+ export type ResolveModelContextInput = string | {
667
+ provider: ProviderId;
668
+ model: string;
669
+ baseUrl?: string;
670
+ transportId?: string;
671
+ };
672
+ /** A configured model entry — either a bare id or an id with a per-model context window (C4). */
673
+ export interface ModelConfigInput {
674
+ id: string;
675
+ contextWindow?: number;
676
+ }
677
+ /** A model declaration in account config: a bare id string OR a `{ id, contextWindow }` (C4). */
678
+ export type ModelInput = string | ModelConfigInput;
679
+ /** A normalized model declaration after `normalizeModelInput` (C4). */
680
+ export interface NormalizedModelConfig {
681
+ id: string;
682
+ contextWindow?: number;
683
+ }
684
+ /**
685
+ * Options for `AiConnectClient.resolveModelContext` (C4). `discovered` is the value learned
686
+ * from a live model-discovery response (highest precedence); `configured` is a per-model/route
687
+ * override; `defaultContextWindow` overrides the flat 8192 floor. On a cache HIT `discovered`
688
+ * is IGNORED (the cached value+source win — OQ-4 #25).
689
+ */
690
+ export interface ResolveModelContextOptions {
691
+ discovered?: number;
692
+ configured?: number;
693
+ defaultContextWindow?: number;
694
+ }
695
+ export interface AcpModelCatalog {
696
+ requestedModelId?: string;
697
+ requestedModelAdvertised?: boolean;
698
+ canonicalModelId?: string;
699
+ resolvedModelId?: string;
700
+ currentModelId?: string;
701
+ availableModels: AcpModelInfo[];
702
+ }
703
+ export interface AcpModelDiscoveryError {
704
+ code: AiConnectErrorCode | "not_supported";
705
+ message: string;
706
+ }
707
+ export interface AcpModelDiscoveryRouteReport {
708
+ routeId: string;
709
+ provider: ProviderId;
710
+ handlerKey: string;
711
+ transportKind: TransportKind;
712
+ transportId: string;
713
+ ok: boolean;
714
+ requestedModelId?: string;
715
+ requestedModelAdvertised?: boolean;
716
+ canonicalModelId?: string;
717
+ resolvedModelId?: string;
718
+ currentModelId?: string;
719
+ availableModels: AcpModelInfo[];
720
+ error?: AcpModelDiscoveryError;
721
+ }
722
+ export interface AcpModelDiscoveryReport {
723
+ ok: boolean;
724
+ routes: AcpModelDiscoveryRouteReport[];
725
+ }
726
+ export interface RuntimeEnvironment {
727
+ kind: RuntimeKind;
728
+ now?: () => number;
729
+ getEnv?: (name: string) => string | undefined;
730
+ hasCommand?: (command: string) => boolean | Promise<boolean>;
731
+ /**
732
+ * Schedule a one-shot timer; returns a cancel function. Default (when omitted) is real
733
+ * `setTimeout` + `unref()`. Seeded DST runtimes inject a fake-clock-driven timer so abort/
734
+ * timeout behaviour is deterministically replayable (D6). Consumed by `deriveAbort` (C2b)
735
+ * and the model probe (C8) — never read wall-clock directly on an observable path.
736
+ */
737
+ setTimer?: (ms: number, cb: () => void) => () => void;
738
+ }
739
+ export interface WideEventRouteSummary {
740
+ id: string;
741
+ provider: ProviderId;
742
+ transportKind: TransportKind;
743
+ transportId: string;
744
+ runtime: RouteRuntime;
745
+ accountId: string;
746
+ credentialId: string;
747
+ model: string;
748
+ handlerKey: string;
749
+ profileId: string;
750
+ baseUrl?: string;
751
+ }
752
+ export interface WideEventRequestSummary {
753
+ messageCount: number;
754
+ messageRoles: MessageRole[];
755
+ inputChars: number;
756
+ attachmentCount: number;
757
+ attachmentKinds: PortableFileKind[];
758
+ attachmentNames: string[];
759
+ candidateRouteIds: string[];
760
+ clientToolCount?: number;
761
+ clientToolNames?: string[];
762
+ routeHints?: RouteHints;
763
+ workingDirectory?: string;
764
+ imageSize?: string;
765
+ imageAspectRatio?: string;
766
+ imageQuality?: string;
767
+ imageOutputSize?: string;
768
+ imageStyle?: string;
769
+ rawImagePrompt?: boolean;
770
+ imageReferenceCount?: number;
771
+ imageHasSourceImage?: boolean;
772
+ imageHasMask?: boolean;
773
+ parameters?: WideEventParameterSummary;
774
+ }
775
+ export interface WideEventVerificationRouteSummary {
776
+ routeId: string;
777
+ ok: boolean;
778
+ issueCodes: VerificationIssue["code"][];
779
+ }
780
+ export interface WideEventVerificationSummary {
781
+ requestedRouteIds?: string[];
782
+ routesChecked: number;
783
+ routesPassed: number;
784
+ routesFailed: number;
785
+ issueCount: number;
786
+ issueCodes: VerificationIssue["code"][];
787
+ routeReports: WideEventVerificationRouteSummary[];
788
+ }
789
+ export interface WideEventAcpModelDiscoveryRouteSummary {
790
+ routeId: string;
791
+ provider: ProviderId;
792
+ ok: boolean;
793
+ transportKind: TransportKind;
794
+ transportId: string;
795
+ requestedModelId?: string;
796
+ requestedModelAdvertised?: boolean;
797
+ canonicalModelId?: string;
798
+ resolvedModelId?: string;
799
+ currentModelId?: string;
800
+ availableModelCount: number;
801
+ availableModelIds: string[];
802
+ errorCode?: AiConnectErrorCode | "not_supported";
803
+ message?: string;
804
+ }
805
+ export interface WideEventAcpModelDiscoverySummary {
806
+ requestedRouteIds?: string[];
807
+ routesChecked: number;
808
+ routesPassed: number;
809
+ routesFailed: number;
810
+ routeReports: WideEventAcpModelDiscoveryRouteSummary[];
811
+ }
812
+ export interface WideEventHealthRouteSummary {
813
+ routeId: string;
814
+ provider: ProviderId;
815
+ transportKind: TransportKind;
816
+ ok: boolean;
817
+ endpointOk: boolean;
818
+ modelOk: boolean;
819
+ endpointCode?: AiConnectErrorCode | "not_supported";
820
+ modelCode?: AiConnectErrorCode | "not_supported";
821
+ modelLatencyMs?: number;
822
+ }
823
+ export interface WideEventHealthSummary {
824
+ requestedRouteIds?: string[];
825
+ reachabilityOnly: boolean;
826
+ routesChecked: number;
827
+ routesPassed: number;
828
+ routesFailed: number;
829
+ routeReports: WideEventHealthRouteSummary[];
830
+ }
831
+ export interface WideEventProbeRouteSummary {
832
+ routeId: string;
833
+ modelId: string;
834
+ ok: boolean;
835
+ broken: boolean;
836
+ cached: boolean;
837
+ code?: AiConnectErrorCode | "not_supported";
838
+ httpStatus?: number;
839
+ latencyMs?: number;
840
+ }
841
+ export interface WideEventProbeSummary {
842
+ requestedRouteIds?: string[];
843
+ probesIssued: number;
844
+ probesOk: number;
845
+ probesBroken: number;
846
+ probesCached: number;
847
+ routeReports: WideEventProbeRouteSummary[];
848
+ }
849
+ export interface WideEventAttempt {
850
+ index: number;
851
+ route: WideEventRouteSummary;
852
+ durationMs: number;
853
+ outcome: "success" | "error";
854
+ retryCount: number;
855
+ errorCode?: AiConnectErrorCode;
856
+ message?: string;
857
+ fallbackActions?: FallbackAction[];
858
+ transport?: WideEventTransportSummary;
859
+ }
860
+ export interface WideEventParameterSummary {
861
+ keys: string[];
862
+ maxTokens?: number;
863
+ temperature?: number;
864
+ topP?: number;
865
+ topK?: number;
866
+ stopCount?: number;
867
+ seed?: number;
868
+ candidateCount?: number;
869
+ presencePenalty?: number;
870
+ frequencyPenalty?: number;
871
+ responseFormatType?: string;
872
+ toolCount?: number;
873
+ toolChoice?: string;
874
+ parallelToolCalls?: boolean;
875
+ thinkingMode?: ThinkingMode;
876
+ thinkingBudgetTokens?: number;
877
+ thinkingEffort?: ThinkingEffort;
878
+ includeThoughts?: boolean;
879
+ safetySettingsCount?: number;
880
+ metadataKeys?: string[];
881
+ extraKeys?: string[];
882
+ providerOptionKeys?: Record<string, string[]>;
883
+ }
884
+ export interface WideEventTransportPhase {
885
+ name: string;
886
+ durationMs: number;
887
+ }
888
+ export interface WideEventTransportSummary {
889
+ protocol: string;
890
+ endpoint: string;
891
+ method: string;
892
+ stream: boolean;
893
+ bodyKeys: string[];
894
+ parameterKeys: string[];
895
+ parameters?: WideEventParameterSummary;
896
+ phases?: WideEventTransportPhase[];
897
+ cache?: {
898
+ enabled: boolean;
899
+ hit: boolean;
900
+ };
901
+ }
902
+ export interface WideEventResultSummary {
903
+ warningsCount: number;
904
+ warnings: string[];
905
+ attachmentCount: number;
906
+ attachmentKinds: PortableFileKind[];
907
+ attachmentNames: string[];
908
+ outputTextChars?: number;
909
+ toolCallCount?: number;
910
+ usage?: UsageInfo;
911
+ }
912
+ export interface WideEventErrorInfo {
913
+ code: AiConnectErrorCode | "unknown";
914
+ message: string;
915
+ routeId?: string;
916
+ }
917
+ export interface WideEvent {
918
+ timestamp: string;
919
+ event: "ai_connect.operation";
920
+ requestId: string;
921
+ service: string;
922
+ library: "ai-connect";
923
+ operationName: ClientOperationName;
924
+ operation: OperationKind | "verify" | "discover_models" | "check_health" | "probe_models";
925
+ runtime: RuntimeKind;
926
+ outcome: "success" | "error";
927
+ durationMs: number;
928
+ candidates: WideEventRouteSummary[];
929
+ attempts: WideEventAttempt[];
930
+ selectedRoute?: WideEventRouteSummary;
931
+ request?: WideEventRequestSummary;
932
+ result?: WideEventResultSummary;
933
+ verification?: WideEventVerificationSummary;
934
+ modelDiscovery?: WideEventAcpModelDiscoverySummary;
935
+ acpModelDiscovery?: WideEventAcpModelDiscoverySummary;
936
+ /** Live health-check summary (C8 / CD-9), present for `checkHealth`. */
937
+ health?: WideEventHealthSummary;
938
+ /** Model-probe summary (C8 / CD-9), present for `probeModels`/`probeModelsStream`. */
939
+ probe?: WideEventProbeSummary;
940
+ error?: WideEventErrorInfo;
941
+ context?: Record<string, unknown>;
942
+ version?: string;
943
+ deploymentId?: string;
944
+ region?: string;
945
+ }
946
+ export type WideEventLogger = (event: WideEvent) => void | Promise<void>;
947
+ export interface WideEventSamplingOptions {
948
+ sampleRate?: number;
949
+ slowOperationMs?: number;
950
+ keepErrors?: boolean;
951
+ keepWarnings?: boolean;
952
+ keepOperations?: ClientOperationName[];
953
+ keepRoutes?: string[];
954
+ keepProviders?: string[];
955
+ predicate?: (event: WideEvent) => boolean | Promise<boolean>;
956
+ }
957
+ export interface LoggingOptions {
958
+ logger?: WideEventLogger;
959
+ sampling?: WideEventSamplingOptions;
960
+ service?: string;
961
+ version?: string;
962
+ deploymentId?: string;
963
+ region?: string;
964
+ baseContext?: Record<string, unknown>;
965
+ }
966
+ export interface NormalizedCredentialConfig {
967
+ id: string;
968
+ apiKey?: string;
969
+ apiKeyEnv?: string;
970
+ apiKeyDelimiter?: string;
971
+ source: string;
972
+ weight: number;
973
+ metadata: Record<string, string>;
974
+ }
975
+ export interface TransportDescriptor {
976
+ kind: TransportKind;
977
+ id: string;
978
+ command?: string;
979
+ baseUrl?: string;
980
+ cli?: CliTransportOptions;
981
+ auth?: {
982
+ methodId: string;
983
+ params: Record<string, unknown>;
984
+ };
985
+ launch?: AcpLaunchOptions;
986
+ }
987
+ export interface VerificationConfig {
988
+ env: string[];
989
+ command?: string;
990
+ session?: string;
991
+ }
992
+ export interface NormalizedAccountConfig {
993
+ id: string;
994
+ profile: string;
995
+ runtime: RouteRuntime;
996
+ transport: TransportDescriptor;
997
+ models: string[];
998
+ credentials: NormalizedCredentialConfig[];
999
+ capabilities: RouteCapabilities;
1000
+ verify: VerificationConfig;
1001
+ weight: number;
1002
+ priority: number;
1003
+ enabled: boolean;
1004
+ }
1005
+ export interface NormalizedProviderConfig {
1006
+ id: string;
1007
+ accounts: NormalizedAccountConfig[];
1008
+ }
1009
+ export interface NormalizedRoute {
1010
+ id: string;
1011
+ provider: ProviderId;
1012
+ transport: TransportDescriptor;
1013
+ profileId: string;
1014
+ accountId: string;
1015
+ credentialId: string;
1016
+ model: string;
1017
+ runtime: RouteRuntime;
1018
+ weight: number;
1019
+ priority: number;
1020
+ handlerKey: string;
1021
+ capabilities: RouteCapabilities;
1022
+ verify: VerificationConfig;
1023
+ credential: NormalizedCredentialConfig;
1024
+ /** Configured context window for this route's model (C4 owns ONLY this field). */
1025
+ contextWindow?: number;
1026
+ /** Model-allowlist enforcement mode (C7; default `strict`). */
1027
+ modelAllowlistMode: ModelAllowlistMode;
1028
+ /**
1029
+ * Models advertised by this route. In `strict` mode an undeclared `routeHints.model` drops the
1030
+ * route; in `shortlist` mode it is advisory (verbatim passthrough). Seeded from the route's own
1031
+ * `model` (C7); C9 may extend this from discovery.
1032
+ */
1033
+ advertisedModels: string[];
1034
+ /** Per-route default response format (C7); injected when the caller omits one. */
1035
+ defaultResponseFormat?: GenerateResponseFormat;
1036
+ /** Per-route system prompt (C7); injected as a leading system message when the caller omits one. */
1037
+ systemPrompt?: string;
1038
+ /** Human-friendly label for projection/diagnostics (C7); falls back to `id` in `PublicRoute`. */
1039
+ label?: string;
1040
+ /** Execution-context mode (C7; default `workspace`). */
1041
+ contextMode: ContextMode;
1042
+ }
1043
+ export interface NormalizedOperationRouting {
1044
+ strategy: RoutingStrategy;
1045
+ pool: string[];
1046
+ }
1047
+ export interface NormalizedFallbackPolicy {
1048
+ on: Record<AiConnectErrorCode, FallbackAction[]>;
1049
+ cooldownMs: Record<AiConnectErrorCode, number>;
1050
+ }
1051
+ export interface NormalizedRetryPolicy {
1052
+ maxAttempts: Record<AiConnectErrorCode, number>;
1053
+ delayMs: Record<AiConnectErrorCode, number>;
1054
+ }
1055
+ export interface NormalizedRoutingConfig {
1056
+ strategy: RoutingStrategy;
1057
+ operations: Record<OperationKind, NormalizedOperationRouting>;
1058
+ fallback: NormalizedFallbackPolicy;
1059
+ retry: NormalizedRetryPolicy;
1060
+ shuffleOnInit: boolean;
1061
+ /** Selector-resolution policy (C7); default `{ unknownSelector: "error" }`. */
1062
+ resolution: NormalizedRouteResolutionConfig;
1063
+ }
1064
+ export interface AiConnectConfig {
1065
+ providers: Record<string, NormalizedProviderConfig>;
1066
+ routes: NormalizedRoute[];
1067
+ routing: NormalizedRoutingConfig;
1068
+ }
1069
+ export interface RouteHealthSnapshot {
1070
+ state: RouteHealthState;
1071
+ failureCount: number;
1072
+ cooldownUntil?: number;
1073
+ }
1074
+ export interface ListedRoute extends NormalizedRoute {
1075
+ health: RouteHealthSnapshot;
1076
+ }
1077
+ /**
1078
+ * Secret-free subset of {@link RouteCapabilities} safe to expose to untrusted callers (C7 /
1079
+ * INV-PROJ-1). An EXPLICIT `Pick` — never derived by spreading a route — so a future capability
1080
+ * flag cannot silently leak into a public projection.
1081
+ */
1082
+ export type PublicRouteCapabilities = Pick<RouteCapabilities, "browserSafe" | "supportsStreaming" | "supportsToolSchema" | "supportsToolExecution" | "supportsClientToolExecution" | "supportsFileUpload" | "supportsFileOutput" | "supportsImageInput" | "supportsImageOutput">;
1083
+ /**
1084
+ * Client-safe projection of a route (C7 / INV-PROJ-1). Built via EXPLICIT construction in
1085
+ * `toPublicRoute` — NEVER by spreading a {@link NormalizedRoute} (which carries
1086
+ * `credential`/`baseUrl`/`apiKeyEnv`/`accountId`/`handlerKey`). Contains NO secret-bearing field;
1087
+ * `JSON.stringify(publicRoute)` must contain no configured-secret substring.
1088
+ */
1089
+ export interface PublicRoute {
1090
+ id: string;
1091
+ label: string;
1092
+ provider: ProviderId;
1093
+ transportKind: TransportKind;
1094
+ models: string[];
1095
+ defaultModel: string;
1096
+ contextWindow?: number;
1097
+ modelAllowlistMode: ModelAllowlistMode;
1098
+ defaultResponseFormat?: GenerateResponseFormat;
1099
+ systemPrompt?: string;
1100
+ capabilities: PublicRouteCapabilities;
1101
+ health: RouteHealthState;
1102
+ }
1103
+ export interface VerificationContext {
1104
+ route: NormalizedRoute;
1105
+ runtime: RuntimeEnvironment;
1106
+ }
1107
+ export interface DiscoverAcpModelsContext {
1108
+ route: NormalizedRoute;
1109
+ runtime: RuntimeEnvironment;
1110
+ /** Merged probe-tier cancellation signal (CD-3). C2a sole owner; consumers only read it. */
1111
+ abort: AbortContext;
1112
+ telemetry?: {
1113
+ captureTransport: (summary: WideEventTransportSummary) => void;
1114
+ };
1115
+ }
1116
+ export interface GenerateContext {
1117
+ route: NormalizedRoute;
1118
+ request: NormalizedGenerateRequest;
1119
+ runtime: RuntimeEnvironment;
1120
+ attempt: number;
1121
+ /** Merged cancellation signal (CD-3). Handlers forward `abort.signal` into fetch/child-kill. */
1122
+ abort: AbortContext;
1123
+ telemetry?: {
1124
+ captureTransport: (summary: WideEventTransportSummary) => void;
1125
+ };
1126
+ }
1127
+ export interface RouteHandlerGenerateResult {
1128
+ text?: string;
1129
+ data?: unknown;
1130
+ attachments?: PortableFileInput[];
1131
+ toolCalls?: ToolCallInput[];
1132
+ usage?: UsageInfo;
1133
+ warnings?: string[];
1134
+ }
1135
+ export interface RouteHandler {
1136
+ generate?: (context: GenerateContext) => Promise<RouteHandlerGenerateResult>;
1137
+ stream?: (context: GenerateContext) => AsyncIterable<GenerateStreamEvent>;
1138
+ verify?: (context: VerificationContext) => Promise<VerificationIssue[]> | VerificationIssue[];
1139
+ discoverModels?: (context: DiscoverAcpModelsContext) => Promise<AcpModelCatalog>;
1140
+ }
1141
+ export type RouteHandlerRegistry = Record<string, RouteHandler>;
1142
+ export interface AcpSessionCacheOptions {
1143
+ enabled?: boolean;
1144
+ idleTtlMs?: number;
1145
+ }
1146
+ export interface AcpClientOptions {
1147
+ cwd?: string;
1148
+ env?: Record<string, string>;
1149
+ commands?: Record<string, string>;
1150
+ launch?: AcpLaunchOptionsInput;
1151
+ permissionMode?: AcpPermissionMode;
1152
+ timeoutMs?: number;
1153
+ sessionCache?: boolean | AcpSessionCacheOptions;
1154
+ maxConcurrentConnections?: number;
1155
+ }
1156
+ export interface CliClientOptions {
1157
+ cwd?: string;
1158
+ env?: Record<string, string>;
1159
+ commands?: Record<string, string>;
1160
+ timeoutMs?: number;
1161
+ }
1162
+ export interface ServerClientOptions {
1163
+ cwd?: string;
1164
+ env?: Record<string, string>;
1165
+ commands?: Record<string, string>;
1166
+ timeoutMs?: number;
1167
+ startupTimeoutMs?: number;
1168
+ fetch?: FetchLike;
1169
+ }
1170
+ export interface CreateClientOptions {
1171
+ runtime?: RuntimeEnvironment;
1172
+ handlers?: RouteHandlerRegistry;
1173
+ clientTools?: ClientToolDefinition[];
1174
+ fetch?: FetchLike;
1175
+ acp?: AcpClientOptions;
1176
+ cli?: CliClientOptions;
1177
+ server?: ServerClientOptions;
1178
+ logging?: LoggingOptions;
1179
+ dispose?: () => Promise<void>;
1180
+ /** Per-operation timeout tier defaults (CD-6); merged into the derived abort signal. */
1181
+ timeouts?: OperationTimeoutDefaults;
1182
+ /**
1183
+ * Client-level fan-out throttle default (C9 / UR-013). A per-request `GenerateRequest.fanout`
1184
+ * merges per-field OVER this. Unset ⇒ unbounded.
1185
+ */
1186
+ fanout?: FanoutPolicy;
1187
+ /**
1188
+ * Client-scoped routing hooks (C9 / UR-014). `modelSelector` is a consumer-supplied pre-routing
1189
+ * model picker (OQ-11); `failOpen` (default `false`) flips a throwing selector from the
1190
+ * fail-closed `validation_error` default to silently falling through to normal routing.
1191
+ */
1192
+ routeHints?: {
1193
+ modelSelector?: ModelSelector;
1194
+ failOpen?: boolean;
1195
+ };
1196
+ }
1197
+ export interface VerifyTarget {
1198
+ routes?: string[];
1199
+ logContext?: Record<string, unknown>;
1200
+ }
1201
+ export interface DiscoverAcpModelsTarget {
1202
+ routes?: string[];
1203
+ logContext?: Record<string, unknown>;
1204
+ }
1205
+ export interface DiscoverModelsTarget {
1206
+ routes?: string[];
1207
+ transports?: TransportKind[];
1208
+ logContext?: Record<string, unknown>;
1209
+ }
1210
+ export type ModelInfo = AcpModelInfo;
1211
+ export type ModelCatalog = AcpModelCatalog;
1212
+ export type ModelDiscoveryError = AcpModelDiscoveryError;
1213
+ export type ModelDiscoveryRouteReport = AcpModelDiscoveryRouteReport;
1214
+ export type ModelDiscoveryReport = AcpModelDiscoveryReport;
1215
+ /**
1216
+ * Outcome of one health-check stage. `ok` is the stage verdict; `detail` is a human-readable
1217
+ * note (e.g. `'skipped: endpoint unreachable'` when Stage-1 short-circuited Stage-2). `httpStatus`
1218
+ * carries the raw status (via {@link AiConnectError} `details.httpStatus`, CD-7) when known.
1219
+ */
1220
+ export interface HealthStageResult {
1221
+ ok: boolean;
1222
+ detail: string;
1223
+ code?: AiConnectErrorCode | "not_supported";
1224
+ httpStatus?: number;
1225
+ }
1226
+ /** A model-ping stage result; `latencyMs` is the measured ping round-trip (fake-clock derived). */
1227
+ export interface HealthModelStageResult extends HealthStageResult {
1228
+ latencyMs?: number;
1229
+ }
1230
+ export interface RouteHealthReport {
1231
+ routeId: string;
1232
+ provider: ProviderId;
1233
+ handlerKey: string;
1234
+ transportKind: TransportKind;
1235
+ transportId: string;
1236
+ modelId: string;
1237
+ ok: boolean;
1238
+ endpoint: HealthStageResult;
1239
+ model: HealthModelStageResult;
1240
+ }
1241
+ export interface HealthReport {
1242
+ ok: boolean;
1243
+ routes: RouteHealthReport[];
1244
+ }
1245
+ export interface CheckHealthTarget {
1246
+ routes?: string[];
1247
+ transports?: TransportKind[];
1248
+ /** Run Stage-1 (reachability) only; skip the Stage-2 chat ping. Cheap default for hot paths. */
1249
+ reachabilityOnly?: boolean;
1250
+ timeoutMs?: number;
1251
+ signal?: AbortSignal;
1252
+ logContext?: Record<string, unknown>;
1253
+ }
1254
+ /**
1255
+ * Result of probing one route::model tuple (UR-008). `broken` is HTTP-status-driven for api
1256
+ * transports (INV-PROBE-1: `400 ≤ httpStatus < 500 ∧ httpStatus ≠ 429`); everything else
1257
+ * (429 / 5xx / status-less transport errors) is transient (`broken:false`). `cached:true`
1258
+ * marks a TTL-cache hit (no live ping issued).
1259
+ */
1260
+ export interface ProbeModelResult {
1261
+ routeId: string;
1262
+ modelId: string;
1263
+ ok: boolean;
1264
+ broken: boolean;
1265
+ detail: string;
1266
+ latencyMs?: number;
1267
+ code?: AiConnectErrorCode | "not_supported";
1268
+ httpStatus?: number;
1269
+ cached?: boolean;
1270
+ }
1271
+ export interface ProbeModelsTarget {
1272
+ routes?: string[];
1273
+ transports?: TransportKind[];
1274
+ models?: string[];
1275
+ logContext?: Record<string, unknown>;
1276
+ }
1277
+ export interface ProbeModelsOptions {
1278
+ signal?: AbortSignal;
1279
+ /** Bounded fan-out concurrency (default {@link PROBE_DEFAULT_CONCURRENCY} = 4). */
1280
+ concurrency?: number;
1281
+ /** Per-probe timeout in ms (default {@link PROBE_DEFAULT_TIMEOUT_MS} = 8000). */
1282
+ timeoutMs?: number;
1283
+ /** TTL for the per-(route::sorted-models) cache (default {@link PROBE_DEFAULT_TTL_MS} = 300000). */
1284
+ cacheTtlMs?: number;
1285
+ /** Ignore any cached entry and re-probe (still rewrites the cache). */
1286
+ forceRefresh?: boolean;
1287
+ logContext?: Record<string, unknown>;
1288
+ }
1289
+ export interface AiConnectClient {
1290
+ readonly config: AiConnectConfig;
1291
+ readonly runtime: RuntimeEnvironment;
1292
+ listRoutes(filter?: {
1293
+ operation?: OperationKind;
1294
+ }): ListedRoute[];
1295
+ /**
1296
+ * Secret-free projection of routes (C7 / INV-PROJ-1) for untrusted surfaces (UI/agent
1297
+ * discovery). Returns {@link PublicRoute}s built by explicit construction — never carries
1298
+ * credentials/baseUrl/handler keys. Stable under route-health changes except the `health`
1299
+ * field itself.
1300
+ */
1301
+ listPublicRoutes(filter?: {
1302
+ operation?: OperationKind;
1303
+ provider?: ProviderId;
1304
+ }): PublicRoute[];
1305
+ /**
1306
+ * Project the currently-eligible routes into secret-free {@link CandidateModel}s (C9 / UR-014) —
1307
+ * the same list offered to a {@link ModelSelector}. Reuses the router's `candidateModels()`
1308
+ * projector + the runtime/health filters.
1309
+ */
1310
+ listCandidateModels(filter?: {
1311
+ operation?: OperationKind;
1312
+ provider?: ProviderId;
1313
+ }): CandidateModel[];
1314
+ prepareFile(input: PortableFileInput): PortableFile;
1315
+ verify(target?: VerifyTarget, opts?: Pick<GenerateCallOptions, "signal" | "timeoutMs">): Promise<VerificationReport>;
1316
+ discoverModels(target?: DiscoverModelsTarget, opts?: Pick<GenerateCallOptions, "signal" | "timeoutMs">): Promise<ModelDiscoveryReport>;
1317
+ discoverAcpModels(target?: DiscoverAcpModelsTarget, opts?: Pick<GenerateCallOptions, "signal" | "timeoutMs">): Promise<AcpModelDiscoveryReport>;
1318
+ generate(request: GenerateRequest, opts?: GenerateCallOptions): Promise<GenerateResult>;
1319
+ stream(request: GenerateRequest, opts?: GenerateCallOptions): AsyncIterable<GenerateStreamEvent>;
1320
+ /**
1321
+ * Resolve the effective context window for a model (C4 / INV-CTX-1). Synchronous, no I/O.
1322
+ * Precedence: discovered > reference (curated table) > configured > default(8192). Results
1323
+ * are cached per-(baseUrl|transportId)::model; a cache hit returns the same value+source with
1324
+ * `cached:true` and IGNORES `options.discovered`.
1325
+ */
1326
+ resolveModelContext(input: ResolveModelContextInput, options?: ResolveModelContextOptions): ModelContextResolution;
1327
+ /**
1328
+ * Live two-stage health-check (C8 / UR-008). Stage-1 probes endpoint reachability (api GET
1329
+ * /models via `discoverModels`; acp/cli/server session via `verify`); Stage-2 issues a minimal
1330
+ * bounded chat ping (max-1-token) capturing `latencyMs`. A Stage-1 failure short-circuits
1331
+ * Stage-2 with detail `'skipped: endpoint unreachable'`. READ-ONLY re router health (INV-PROBE-1):
1332
+ * never calls `recordFailure`/`recordSuccess`.
1333
+ */
1334
+ checkHealth(target?: CheckHealthTarget): Promise<HealthReport>;
1335
+ /**
1336
+ * Probe route::model tuples for broken-vs-transient classification (C8 / UR-008 / INV-PROBE-1)
1337
+ * with a per-(route::sorted-models) TTL cache (default 5min), bounded concurrency (default 4),
1338
+ * and a per-probe timeout (default 8s) scheduled via the derived-abort `runtime.setTimer` seam.
1339
+ * Honors `opts.signal` mid-fan-out. READ-ONLY re router health.
1340
+ */
1341
+ probeModels(target?: ProbeModelsTarget, opts?: ProbeModelsOptions): Promise<ProbeModelResult[]>;
1342
+ /** Streaming variant of {@link probeModels}: yields each {@link ProbeModelResult} as it settles. */
1343
+ probeModelsStream(target?: ProbeModelsTarget, opts?: ProbeModelsOptions): AsyncIterable<ProbeModelResult>;
1344
+ dispose(): Promise<void>;
1345
+ }
1346
+ //# sourceMappingURL=types.d.ts.map