@omnicross/core 0.1.10 → 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.
- package/LICENSE +21 -21
- package/NOTICE +57 -57
- package/README.md +22 -15
- package/dist/{CompletionService-kNA17cfI.d.cts → CompletionService-BiJqftc-.d.cts} +1 -1
- package/dist/{CompletionService-C3BX0Ovy.d.ts → CompletionService-NXN_Av5W.d.ts} +1 -1
- package/dist/{ProviderProxy-QdwNV6l1.d.cts → ProviderProxy-CgIcCVwk.d.cts} +1 -1
- package/dist/{ProviderProxy--ROec6VI.d.ts → ProviderProxy-DYoY5XoT.d.ts} +1 -1
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -6
- package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -4
- package/dist/{chunk-QUSEZNYS.cjs → chunk-32SRZFFP.cjs} +4 -1
- package/dist/chunk-4JOU54M5.js +200 -0
- package/dist/{chunk-2UTGX6FM.js → chunk-4VVCXVB7.js} +1 -1
- package/dist/chunk-6DDYNS2B.cjs +384 -0
- package/dist/{chunk-HKB656B4.js → chunk-6OC3ORW6.js} +55 -287
- package/dist/{chunk-GXEZ2R3E.js → chunk-6OKXH2TW.js} +18 -7
- package/dist/{chunk-TIT74RIL.cjs → chunk-7B56AJBB.cjs} +6214 -2423
- package/dist/{chunk-YWL7YZWS.cjs → chunk-7LRTPNFL.cjs} +5 -0
- package/dist/{chunk-CCVRRJOX.js → chunk-7PIUVCKK.js} +9 -2
- package/dist/{chunk-IIRPUVPH.cjs → chunk-7ZHBN75N.cjs} +3 -1
- package/dist/{chunk-RJ5ZGNI3.js → chunk-CFSGYFOZ.js} +1 -1
- package/dist/chunk-CTKM773J.cjs +3919 -0
- package/dist/chunk-DEIUR2TH.js +3919 -0
- package/dist/{chunk-WNKWAEUR.js → chunk-EYGBM2VC.js} +3 -1
- package/dist/{chunk-NGYOO5TO.js → chunk-FJNKXOWE.js} +9 -9
- package/dist/{chunk-UWDW6PN3.cjs → chunk-FX325I5Q.cjs} +20 -9
- package/dist/chunk-G4CZIUIB.cjs +200 -0
- package/dist/chunk-HCOQQAZE.cjs +123 -0
- package/dist/{chunk-55FMGZ3L.js → chunk-HN74IGEO.js} +1 -1
- package/dist/{chunk-ZY6KU6P3.js → chunk-HOMUGKHR.js} +8 -5
- package/dist/{chunk-AOFWNWLT.cjs → chunk-IUL4VWNU.cjs} +22 -1
- package/dist/{chunk-5LNYGCIW.cjs → chunk-KIQ2HA2A.cjs} +5 -5
- package/dist/{chunk-MUHWHQVM.cjs → chunk-KQBLZMP6.cjs} +4 -3
- package/dist/chunk-LFEH7CEO.js +384 -0
- package/dist/chunk-N76KU6F5.js +123 -0
- package/dist/{chunk-CMVXX7ON.cjs → chunk-NOITAVHA.cjs} +114 -58
- package/dist/{chunk-Q27JY5RG.cjs → chunk-OIKREZVQ.cjs} +7 -4
- package/dist/{chunk-RJUONLUQ.cjs → chunk-OST5RJOJ.cjs} +1 -1
- package/dist/{chunk-6D4W22P4.js → chunk-QIIAMBTM.js} +4 -1
- package/dist/{chunk-56QD3YW6.cjs → chunk-QWNUOR7F.cjs} +11 -4
- package/dist/{chunk-S3DYFEBE.js → chunk-R4VCO2CB.js} +10 -1
- package/dist/{chunk-ZQQUD66M.cjs → chunk-SQMAEDNE.cjs} +63 -295
- package/dist/{chunk-4VZX5F4T.cjs → chunk-T6NWPIYZ.cjs} +5 -2
- package/dist/{chunk-P7EM6BND.cjs → chunk-TVYA5JSQ.cjs} +10 -10
- package/dist/{chunk-EBLFCNPY.js → chunk-U47LQXPB.js} +5 -2
- package/dist/{chunk-N7OOJI5V.js → chunk-V2UKUTJ3.js} +5 -0
- package/dist/{chunk-45FHEOKW.js → chunk-V53ZEFXC.js} +92 -36
- package/dist/{chunk-OC6DOOFX.cjs → chunk-VXRTQZF2.cjs} +5 -5
- package/dist/{chunk-FEBAQI5A.js → chunk-WSJE42SG.js} +4964 -1173
- package/dist/{chunk-RICPANBY.cjs → chunk-WX2E2G7H.cjs} +13 -4
- package/dist/{chunk-DE2SRBFZ.js → chunk-X335TJNS.js} +4 -3
- package/dist/{chunk-N2EIM2XJ.js → chunk-ZLNHPUFA.js} +22 -1
- package/dist/completion/CompletionService.cjs +29 -26
- package/dist/completion/CompletionService.d.cts +3 -2
- package/dist/completion/CompletionService.d.ts +3 -2
- package/dist/completion/CompletionService.js +28 -25
- package/dist/completion.cjs +37 -34
- package/dist/completion.d.cts +3 -2
- package/dist/completion.d.ts +3 -2
- package/dist/completion.js +36 -33
- package/dist/image-generation.cjs +52 -0
- package/dist/image-generation.d.cts +93 -0
- package/dist/image-generation.d.ts +93 -0
- package/dist/image-generation.js +52 -0
- package/dist/index.cjs +126 -31
- package/dist/index.d.cts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +142 -47
- package/dist/openai-operation.cjs +18 -0
- package/dist/openai-operation.d.cts +19 -0
- package/dist/openai-operation.d.ts +19 -0
- package/dist/openai-operation.js +18 -0
- package/dist/outbound-api/auditCapture.cjs +3 -3
- package/dist/outbound-api/auditCapture.d.cts +13 -2
- package/dist/outbound-api/auditCapture.d.ts +13 -2
- package/dist/outbound-api/auditCapture.js +2 -2
- package/dist/outbound-api/auditRedact.cjs +2 -2
- package/dist/outbound-api/auditRedact.js +1 -1
- package/dist/outbound-api/routeResolver.cjs +2 -2
- package/dist/outbound-api/routeResolver.d.cts +7 -4
- package/dist/outbound-api/routeResolver.d.ts +7 -4
- package/dist/outbound-api/routeResolver.js +1 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.cts +2 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.ts +2 -1
- package/dist/outbound-api/types.d.cts +6 -3
- package/dist/outbound-api/types.d.ts +6 -3
- package/dist/outbound-api.cjs +48 -31
- package/dist/outbound-api.d.cts +95 -9
- package/dist/outbound-api.d.ts +95 -9
- package/dist/outbound-api.js +47 -30
- package/dist/pipeline/AccountAllowanceScheduling.d.cts +18 -15
- package/dist/pipeline/AccountAllowanceScheduling.d.ts +18 -15
- package/dist/pipeline/LlmConfigProviderAuth.cjs +3 -3
- package/dist/pipeline/LlmConfigProviderAuth.js +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.cjs +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.d.cts +7 -0
- package/dist/pipeline/SubscriptionAccountHealth.d.ts +7 -0
- package/dist/pipeline/SubscriptionAccountHealth.js +1 -1
- package/dist/pipeline/executeProviderCall.cjs +2 -2
- package/dist/pipeline/executeProviderCall.d.cts +11 -6
- package/dist/pipeline/executeProviderCall.d.ts +11 -6
- package/dist/pipeline/executeProviderCall.js +1 -1
- package/dist/pipeline/upstreamFetch.cjs +2 -2
- package/dist/pipeline/upstreamFetch.d.cts +5 -0
- package/dist/pipeline/upstreamFetch.d.ts +5 -0
- package/dist/pipeline/upstreamFetch.js +1 -1
- package/dist/ports.d.cts +6 -3
- package/dist/ports.d.ts +6 -3
- package/dist/provider-proxy/ProviderProxy.cjs +29 -26
- package/dist/provider-proxy/ProviderProxy.d.cts +3 -2
- package/dist/provider-proxy/ProviderProxy.d.ts +3 -2
- package/dist/provider-proxy/ProviderProxy.js +28 -25
- package/dist/provider-proxy/identity/codexCliHeaders.cjs +4 -2
- package/dist/provider-proxy/identity/codexCliHeaders.d.cts +26 -6
- package/dist/provider-proxy/identity/codexCliHeaders.d.ts +26 -6
- package/dist/provider-proxy/identity/codexCliHeaders.js +5 -3
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +31 -26
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +21 -8
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +21 -8
- package/dist/provider-proxy/ingress/providerProxyShared.js +30 -25
- package/dist/provider-proxy/types.d.cts +14 -483
- package/dist/provider-proxy/types.d.ts +14 -483
- package/dist/provider-proxy.cjs +43 -26
- package/dist/provider-proxy.d.cts +30 -8
- package/dist/provider-proxy.d.ts +30 -8
- package/dist/provider-proxy.js +42 -25
- package/dist/{routeResolver-C0mkkZaM.d.ts → routeResolver-CTCcSHWu.d.ts} +4 -2
- package/dist/{routeResolver-CVFE8KKe.d.cts → routeResolver-rpKQLyDO.d.cts} +4 -2
- package/dist/transformer/TransformerChainExecutor.cjs +2 -2
- package/dist/transformer/TransformerChainExecutor.d.cts +2 -2
- package/dist/transformer/TransformerChainExecutor.d.ts +2 -2
- package/dist/transformer/TransformerChainExecutor.js +1 -1
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.cjs +16 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.cts +53 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.ts +53 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.js +16 -0
- package/dist/transformer/transformers/AnthropicTransformer.cjs +4 -3
- package/dist/transformer/transformers/AnthropicTransformer.js +3 -2
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +4 -4
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +3 -3
- package/dist/transformer/transformers/GeminiTransformer.cjs +4 -4
- package/dist/transformer/transformers/GeminiTransformer.js +3 -3
- package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -3
- package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -2
- package/dist/transformer/transformers/OpenAITransformer.cjs +3 -3
- package/dist/transformer/transformers/OpenAITransformer.js +2 -2
- package/dist/transformer/transformers.cjs +10 -9
- package/dist/transformer/transformers.js +13 -12
- package/dist/transformer/types.d.cts +39 -4
- package/dist/transformer/types.d.ts +39 -4
- package/dist/transformer.cjs +14 -13
- package/dist/transformer.js +14 -13
- package/dist/{types-BB8pxk_3.d.ts → types-5T223WYQ.d.ts} +183 -23
- package/dist/types-Bd72H4SB.d.ts +196 -0
- package/dist/types-CVRge76p.d.ts +1115 -0
- package/dist/types-CbglB73l.d.cts +196 -0
- package/dist/types-DsHBBk3h.d.cts +1115 -0
- package/dist/{types-C2MwkLah.d.cts → types-jjU24eYG.d.cts} +183 -23
- package/dist/usage.cjs +2 -2
- package/dist/usage.d.cts +6 -1
- package/dist/usage.d.ts +6 -1
- package/dist/usage.js +1 -1
- package/package.json +69 -64
- package/dist/chunk-FCR77GYM.cjs +0 -33
- package/dist/chunk-K5NM7VAH.js +0 -33
- /package/dist/{chunk-XXFYLL7R.js → chunk-ECZ3ZE2C.js} +0 -0
- /package/dist/{chunk-3SCOLIPT.cjs → chunk-MXI2PWIC.cjs} +0 -0
|
@@ -0,0 +1,1115 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { ThinkLevel } from '@omnicross/contracts/completion-types';
|
|
3
|
+
import { UsageCacheKeySource } from '@omnicross/contracts/usage-stats-types';
|
|
4
|
+
import { SubscriptionProviderId, OpenCodeGoTokenConfig, OpenCodeGoScenario, OpenCodeGoModelEntry } from '@omnicross/contracts/subscription-types';
|
|
5
|
+
import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
|
|
6
|
+
import { ApiKeyPoolService } from './completion/ApiKeyPoolService.js';
|
|
7
|
+
import { AuthSource } from './pipeline/AuthSource.js';
|
|
8
|
+
import { BoundAccountFallbackPolicy } from './pipeline/BoundAccountSelectionError.js';
|
|
9
|
+
import { SubscriptionAuthProfile } from './pipeline/SubscriptionAuthSource.js';
|
|
10
|
+
import { AuthStrategy } from './pipeline/SubscriptionAuthStrategy.js';
|
|
11
|
+
import { ProviderConfigSource } from './ports/provider-config-source.js';
|
|
12
|
+
import { WebSearchBackend } from './ports/web-search-backend.js';
|
|
13
|
+
import { ImageArtifactMetadata, SensitiveOpaqueImageReference, ImageReferenceMetadata, ImageReferenceId, ImageAction, ImageQuality, ImageBackground, ImageOutputFormat, ImageGenerationErrorCode, ImageUsage, ImageArtifactId, ImageCapabilities, NormalizedImageRequest, ImageProviderEvent, ImageSize, ImageGenerationPublicError } from '@omnicross/contracts/image-generation-types';
|
|
14
|
+
import { ApiFormat } from '@omnicross/contracts/llm-config';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Stable identities for the OpenAI-compatible HTTP operations Omnicross knows.
|
|
18
|
+
*
|
|
19
|
+
* Classification is deliberately closed and path-only. Adapters can vary how
|
|
20
|
+
* an extension-owned operation is implemented, but cannot claim new public
|
|
21
|
+
* paths at runtime.
|
|
22
|
+
*
|
|
23
|
+
* @module openai-operation/openAIOperation
|
|
24
|
+
*/
|
|
25
|
+
type OpenAIOperationId = 'chat.completions.create' | 'responses.create' | 'responses.compact' | 'images.generate' | 'images.edit';
|
|
26
|
+
type OpenAIPolicyFamily = 'chat' | 'responses' | 'images';
|
|
27
|
+
type OpenAIRouteFamily = OpenAIPolicyFamily;
|
|
28
|
+
type OpenAIOperationOwner = 'builtin' | 'extension';
|
|
29
|
+
type OpenAIOperationBodyKind = 'json' | 'multipart';
|
|
30
|
+
type OpenAIRequestedModelSource = 'request' | 'configured';
|
|
31
|
+
interface OpenAIOperation {
|
|
32
|
+
readonly id: OpenAIOperationId;
|
|
33
|
+
readonly policyFamily: OpenAIPolicyFamily;
|
|
34
|
+
readonly routeFamily: OpenAIRouteFamily;
|
|
35
|
+
readonly owner: OpenAIOperationOwner;
|
|
36
|
+
readonly bodyKind: OpenAIOperationBodyKind;
|
|
37
|
+
readonly requestedModelSource: OpenAIRequestedModelSource;
|
|
38
|
+
}
|
|
39
|
+
type ExtensionOpenAIOperationId = 'responses.compact' | 'images.generate' | 'images.edit';
|
|
40
|
+
declare function getOpenAIOperation(id: OpenAIOperationId): OpenAIOperation;
|
|
41
|
+
/** Classify a supported OpenAI operation under any base-path prefix. */
|
|
42
|
+
declare function classifyOpenAIOperation(method: string | undefined, url: string | undefined): OpenAIOperation | null;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Trusted in-process handler seam for extension-owned OpenAI operations.
|
|
46
|
+
*
|
|
47
|
+
* The registry owns uniqueness, request-lifetime cancellation, and the narrow
|
|
48
|
+
* local error envelope. Authentication and route selection remain outside this
|
|
49
|
+
* module and must complete before dispatch.
|
|
50
|
+
*
|
|
51
|
+
* @module openai-operation/openAIOperationRegistry
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
interface OpenAIOperationHandlerContext {
|
|
55
|
+
readonly operation: OpenAIOperation;
|
|
56
|
+
readonly request: http.IncomingMessage;
|
|
57
|
+
readonly response: http.ServerResponse;
|
|
58
|
+
readonly route: RouteContext;
|
|
59
|
+
readonly deps: ProviderProxyDeps;
|
|
60
|
+
readonly signal: AbortSignal;
|
|
61
|
+
}
|
|
62
|
+
type OpenAIOperationHandler = (context: OpenAIOperationHandlerContext) => Promise<void>;
|
|
63
|
+
type OpenAIOperationRegistrationErrorCode = 'builtin_operation' | 'duplicate_operation_handler';
|
|
64
|
+
declare class OpenAIOperationRegistrationError extends Error {
|
|
65
|
+
readonly code: OpenAIOperationRegistrationErrorCode;
|
|
66
|
+
readonly name = "OpenAIOperationRegistrationError";
|
|
67
|
+
constructor(code: OpenAIOperationRegistrationErrorCode, message: string);
|
|
68
|
+
}
|
|
69
|
+
interface OpenAIOperationErrorInit {
|
|
70
|
+
readonly status: number;
|
|
71
|
+
readonly code: string;
|
|
72
|
+
readonly message: string;
|
|
73
|
+
readonly retryable?: boolean;
|
|
74
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
75
|
+
}
|
|
76
|
+
declare class OpenAIOperationError extends Error {
|
|
77
|
+
readonly name = "OpenAIOperationError";
|
|
78
|
+
readonly status: number;
|
|
79
|
+
readonly code: string;
|
|
80
|
+
readonly retryable: boolean;
|
|
81
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
82
|
+
constructor(init: OpenAIOperationErrorInit);
|
|
83
|
+
}
|
|
84
|
+
/** Write a typed, locally-generated OpenAI-compatible error before streaming starts. */
|
|
85
|
+
declare function writeOpenAIOperationError(res: http.ServerResponse, error: OpenAIOperationError): boolean;
|
|
86
|
+
declare function unsupportedOpenAIOperation(operation: OpenAIOperation): OpenAIOperationError;
|
|
87
|
+
interface OpenAIOperationDispatchContext {
|
|
88
|
+
readonly operation: OpenAIOperation;
|
|
89
|
+
readonly request: http.IncomingMessage;
|
|
90
|
+
readonly response: http.ServerResponse;
|
|
91
|
+
readonly route: RouteContext;
|
|
92
|
+
readonly deps: ProviderProxyDeps;
|
|
93
|
+
}
|
|
94
|
+
declare class OpenAIOperationRegistry {
|
|
95
|
+
private readonly handlers;
|
|
96
|
+
register(operationId: ExtensionOpenAIOperationId, handler: OpenAIOperationHandler): () => void;
|
|
97
|
+
has(operationId: OpenAIOperationId): boolean;
|
|
98
|
+
dispatch(context: OpenAIOperationDispatchContext): Promise<boolean>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface ImageAsset extends ImageArtifactMetadata {
|
|
102
|
+
/** Every call returns a new bounded, independently readable byte stream. */
|
|
103
|
+
open(options?: {
|
|
104
|
+
readonly signal?: AbortSignal;
|
|
105
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
106
|
+
}
|
|
107
|
+
declare class InMemoryImageAsset implements ImageAsset {
|
|
108
|
+
#private;
|
|
109
|
+
readonly artifactId: ImageArtifactId;
|
|
110
|
+
readonly mimeType: `image/${string}`;
|
|
111
|
+
readonly byteLength: number;
|
|
112
|
+
readonly width: number;
|
|
113
|
+
readonly height: number;
|
|
114
|
+
readonly hasAlpha?: boolean;
|
|
115
|
+
readonly sha256?: string;
|
|
116
|
+
readonly independentlyDecodable: true;
|
|
117
|
+
constructor(bytes: Uint8Array, metadata: Omit<ImageArtifactMetadata, 'artifactId' | 'byteLength' | 'independentlyDecodable'> & {
|
|
118
|
+
readonly artifactId?: ImageArtifactId;
|
|
119
|
+
});
|
|
120
|
+
open(options?: {
|
|
121
|
+
readonly signal?: AbortSignal;
|
|
122
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
123
|
+
/** Best-effort zeroization for short-lived verified/probe artifacts. */
|
|
124
|
+
dispose(): void;
|
|
125
|
+
}
|
|
126
|
+
declare function readImageAssetBytes(asset: ImageAsset, maxBytes: number, signal?: AbortSignal): Promise<Uint8Array>;
|
|
127
|
+
interface ImageReferenceValue {
|
|
128
|
+
readonly artifact?: ImageAsset;
|
|
129
|
+
readonly providerReference?: SensitiveOpaqueImageReference;
|
|
130
|
+
}
|
|
131
|
+
interface ImageReferenceSaveInput extends ImageReferenceValue {
|
|
132
|
+
readonly tenantId: string;
|
|
133
|
+
readonly ttlMs: number;
|
|
134
|
+
readonly metadata: Omit<ImageReferenceMetadata, 'referenceId' | 'createdAt' | 'expiresAt'>;
|
|
135
|
+
}
|
|
136
|
+
interface ImageReferenceLease {
|
|
137
|
+
readonly metadata: ImageReferenceMetadata;
|
|
138
|
+
readonly value: ImageReferenceValue;
|
|
139
|
+
release(): Promise<void>;
|
|
140
|
+
}
|
|
141
|
+
type ImageReferenceResolution = {
|
|
142
|
+
readonly status: 'found';
|
|
143
|
+
readonly lease: ImageReferenceLease;
|
|
144
|
+
} | {
|
|
145
|
+
readonly status: 'expired';
|
|
146
|
+
} | {
|
|
147
|
+
readonly status: 'not_found';
|
|
148
|
+
};
|
|
149
|
+
interface ImageReferenceStore {
|
|
150
|
+
save(input: ImageReferenceSaveInput): Promise<ImageReferenceMetadata>;
|
|
151
|
+
resolve(tenantId: string, referenceId: ImageReferenceId): Promise<ImageReferenceResolution>;
|
|
152
|
+
delete(tenantId: string, referenceId: ImageReferenceId): Promise<boolean>;
|
|
153
|
+
cleanup(now?: number): Promise<number>;
|
|
154
|
+
}
|
|
155
|
+
/** Deterministic-clock test double; production wiring supplies a bounded persistent store. */
|
|
156
|
+
declare class InMemoryImageReferenceStore implements ImageReferenceStore {
|
|
157
|
+
#private;
|
|
158
|
+
constructor(now?: () => number);
|
|
159
|
+
save(input: ImageReferenceSaveInput): Promise<ImageReferenceMetadata>;
|
|
160
|
+
resolve(tenantId: string, referenceId: ImageReferenceId): Promise<ImageReferenceResolution>;
|
|
161
|
+
delete(tenantId: string, referenceId: ImageReferenceId): Promise<boolean>;
|
|
162
|
+
cleanup(now?: number): Promise<number>;
|
|
163
|
+
}
|
|
164
|
+
interface ImageTelemetryOutputMetadata {
|
|
165
|
+
readonly mimeType: `image/${string}`;
|
|
166
|
+
readonly byteLength: number;
|
|
167
|
+
readonly width: number;
|
|
168
|
+
readonly height: number;
|
|
169
|
+
readonly hasAlpha?: boolean;
|
|
170
|
+
}
|
|
171
|
+
/** No content-bearing, credential, tenant, account, URL, or raw-reference field exists here. */
|
|
172
|
+
interface ImageTelemetryRecord {
|
|
173
|
+
readonly requestId: string;
|
|
174
|
+
readonly providerId: string;
|
|
175
|
+
readonly model: string;
|
|
176
|
+
readonly action: ImageAction;
|
|
177
|
+
readonly quality: ImageQuality;
|
|
178
|
+
readonly background: ImageBackground;
|
|
179
|
+
readonly outputFormat: ImageOutputFormat;
|
|
180
|
+
readonly streaming: boolean;
|
|
181
|
+
readonly inputCount: number;
|
|
182
|
+
readonly inputBytes: number;
|
|
183
|
+
readonly requestedOutputCount: number;
|
|
184
|
+
readonly outputs: readonly ImageTelemetryOutputMetadata[];
|
|
185
|
+
readonly startedAt: number;
|
|
186
|
+
readonly acceptedAt?: number;
|
|
187
|
+
readonly firstPartialAt?: number;
|
|
188
|
+
readonly generationStartedAt?: number;
|
|
189
|
+
readonly finishedAt: number;
|
|
190
|
+
readonly terminal: 'completed' | 'failed' | 'cancelled';
|
|
191
|
+
readonly errorCode?: ImageGenerationErrorCode;
|
|
192
|
+
readonly usage?: ImageUsage;
|
|
193
|
+
readonly usageUnavailable: boolean;
|
|
194
|
+
/** Present only when the provider can report exact attempt counts. */
|
|
195
|
+
readonly retryCount?: number;
|
|
196
|
+
/** Present only when the provider can report exact successful refresh counts. */
|
|
197
|
+
readonly authRefreshCount?: number;
|
|
198
|
+
/** Present only when selected-account scheduling measured its own wait. */
|
|
199
|
+
readonly queueWaitMs?: number;
|
|
200
|
+
/** Present when retention was enabled; contains a count, never reference IDs. */
|
|
201
|
+
readonly referenceSaveCount?: number;
|
|
202
|
+
/** Count-only cleanup signal; never contains tenant or reference identifiers. */
|
|
203
|
+
readonly retentionRollbackFailures?: number;
|
|
204
|
+
}
|
|
205
|
+
interface ImageTelemetrySink {
|
|
206
|
+
record(record: ImageTelemetryRecord): void | Promise<void>;
|
|
207
|
+
}
|
|
208
|
+
declare function emitImageTelemetry(sink: ImageTelemetrySink | undefined, record: ImageTelemetryRecord): Promise<void>;
|
|
209
|
+
|
|
210
|
+
type ImageProviderRequest = NormalizedImageRequest<ImageAsset>;
|
|
211
|
+
interface ImageProviderContext {
|
|
212
|
+
readonly requestId: string;
|
|
213
|
+
readonly tenantId: string;
|
|
214
|
+
readonly signal: AbortSignal;
|
|
215
|
+
readonly sessionKey?: string;
|
|
216
|
+
readonly preferredAccountId?: string;
|
|
217
|
+
readonly preferredAccountGroup?: string;
|
|
218
|
+
readonly boundAccountFallbackPolicy?: 'strict' | 'pool';
|
|
219
|
+
}
|
|
220
|
+
/** Optional numeric-only job observations exposed to the orchestrator. */
|
|
221
|
+
interface ImageJobObservabilitySnapshot {
|
|
222
|
+
readonly queueWaitMs?: number;
|
|
223
|
+
readonly generationStartedAt?: number;
|
|
224
|
+
readonly retryCount?: number;
|
|
225
|
+
readonly authRefreshCount?: number;
|
|
226
|
+
}
|
|
227
|
+
interface ImageJobObservability {
|
|
228
|
+
snapshot(): ImageJobObservabilitySnapshot;
|
|
229
|
+
}
|
|
230
|
+
interface ImageJob {
|
|
231
|
+
readonly events: AsyncIterable<ImageProviderEvent<ImageAsset>>;
|
|
232
|
+
readonly observability?: ImageJobObservability;
|
|
233
|
+
cancel(reason?: string): Promise<void>;
|
|
234
|
+
}
|
|
235
|
+
interface ImageProviderLease {
|
|
236
|
+
readonly providerId: string;
|
|
237
|
+
readonly capabilities: ImageCapabilities;
|
|
238
|
+
start(request: ImageProviderRequest): Promise<ImageJob> | ImageJob;
|
|
239
|
+
release(): Promise<void>;
|
|
240
|
+
}
|
|
241
|
+
interface ImageProvider {
|
|
242
|
+
readonly id: string;
|
|
243
|
+
acquire(context: ImageProviderContext): Promise<ImageProviderLease>;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
declare class ImageProviderRegistry {
|
|
247
|
+
#private;
|
|
248
|
+
constructor(providers?: readonly ImageProvider[]);
|
|
249
|
+
register(provider: ImageProvider): void;
|
|
250
|
+
resolve(id: string): ImageProvider | undefined;
|
|
251
|
+
require(id: string): ImageProvider;
|
|
252
|
+
list(): readonly ImageProvider[];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
interface ImageRetentionPolicy {
|
|
256
|
+
readonly enabled: boolean;
|
|
257
|
+
readonly ttlMs: number;
|
|
258
|
+
}
|
|
259
|
+
interface ImageOrchestratorRunOptions {
|
|
260
|
+
readonly providerId: string;
|
|
261
|
+
readonly retention?: ImageRetentionPolicy;
|
|
262
|
+
/** Hosted Responses execution must be affirmed by the same acquired capability snapshot. */
|
|
263
|
+
readonly requireResponsesTool?: boolean;
|
|
264
|
+
}
|
|
265
|
+
interface ImageOrchestratorOptions {
|
|
266
|
+
readonly registry: ImageProviderRegistry;
|
|
267
|
+
readonly referenceStore?: ImageReferenceStore;
|
|
268
|
+
readonly telemetrySink?: ImageTelemetrySink;
|
|
269
|
+
readonly now?: () => number;
|
|
270
|
+
}
|
|
271
|
+
declare class ImageOrchestrator {
|
|
272
|
+
#private;
|
|
273
|
+
constructor(options: ImageOrchestratorOptions);
|
|
274
|
+
getCapabilities(providerId: string, context: ImageProviderContext): Promise<ImageCapabilities>;
|
|
275
|
+
run(request: ImageProviderRequest, context: ImageProviderContext, options: ImageOrchestratorRunOptions): AsyncIterable<ImageProviderEvent<ImageAsset>>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
interface ResponsesImageCallStateLease {
|
|
279
|
+
readonly binding: ResponsesImageCallBinding;
|
|
280
|
+
release(): Promise<void>;
|
|
281
|
+
}
|
|
282
|
+
interface ResponsesImageResponseStateLease {
|
|
283
|
+
readonly responseId: string;
|
|
284
|
+
readonly callIds: readonly ResponsesImageCallId[];
|
|
285
|
+
readonly expiresAt: number;
|
|
286
|
+
release(): Promise<void>;
|
|
287
|
+
}
|
|
288
|
+
type ResponsesImageCallResolution = {
|
|
289
|
+
readonly status: 'found';
|
|
290
|
+
readonly lease: ResponsesImageCallStateLease;
|
|
291
|
+
} | {
|
|
292
|
+
readonly status: 'expired';
|
|
293
|
+
} | {
|
|
294
|
+
readonly status: 'not_found';
|
|
295
|
+
};
|
|
296
|
+
type ResponsesImageResponseResolution = {
|
|
297
|
+
readonly status: 'found';
|
|
298
|
+
readonly lease: ResponsesImageResponseStateLease;
|
|
299
|
+
} | {
|
|
300
|
+
readonly status: 'expired';
|
|
301
|
+
} | {
|
|
302
|
+
readonly status: 'not_found';
|
|
303
|
+
};
|
|
304
|
+
interface ResponsesImageStateCommitInput {
|
|
305
|
+
readonly tenantId: string;
|
|
306
|
+
readonly responseId: string;
|
|
307
|
+
/** Empty is an explicit known-empty response marker, never a no-op. */
|
|
308
|
+
readonly bindings: readonly ResponsesImageCallBinding[];
|
|
309
|
+
readonly responseExpiresAt: number;
|
|
310
|
+
}
|
|
311
|
+
interface ResponsesImageStateStore {
|
|
312
|
+
commit(input: ResponsesImageStateCommitInput): Promise<readonly ResponsesImageCallBinding[]>;
|
|
313
|
+
resolveCall(tenantId: string, callId: ResponsesImageCallId): Promise<ResponsesImageCallResolution>;
|
|
314
|
+
resolveResponse(tenantId: string, responseId: string): Promise<ResponsesImageResponseResolution>;
|
|
315
|
+
deleteCall(tenantId: string, callId: ResponsesImageCallId): Promise<ResponsesImageCallBinding | undefined>;
|
|
316
|
+
deleteResponse(tenantId: string, responseId: string): Promise<boolean>;
|
|
317
|
+
cleanup(now?: number): Promise<readonly ResponsesImageCallBinding[]>;
|
|
318
|
+
}
|
|
319
|
+
interface InMemoryResponsesImageStateStoreOptions {
|
|
320
|
+
readonly maxCalls?: number;
|
|
321
|
+
readonly maxResponses?: number;
|
|
322
|
+
readonly maxTombstones?: number;
|
|
323
|
+
readonly tombstoneTtlMs?: number;
|
|
324
|
+
readonly now?: () => number;
|
|
325
|
+
}
|
|
326
|
+
/** Bounded deterministic test/default implementation; production wiring may inject persistence. */
|
|
327
|
+
declare class InMemoryResponsesImageStateStore implements ResponsesImageStateStore {
|
|
328
|
+
#private;
|
|
329
|
+
constructor(options?: InMemoryResponsesImageStateStoreOptions);
|
|
330
|
+
commit(input: ResponsesImageStateCommitInput): Promise<readonly ResponsesImageCallBinding[]>;
|
|
331
|
+
resolveCall(tenantId: string, callId: ResponsesImageCallId): Promise<ResponsesImageCallResolution>;
|
|
332
|
+
resolveResponse(tenantId: string, responseId: string): Promise<ResponsesImageResponseResolution>;
|
|
333
|
+
deleteCall(tenantId: string, callId: ResponsesImageCallId): Promise<ResponsesImageCallBinding | undefined>;
|
|
334
|
+
deleteResponse(tenantId: string, responseId: string): Promise<boolean>;
|
|
335
|
+
cleanup(now?: number): Promise<readonly ResponsesImageCallBinding[]>;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
type ResponsesImageAction = 'auto' | 'generate' | 'edit';
|
|
339
|
+
type ResponsesImageCallId = `ig_${string}`;
|
|
340
|
+
interface ResponsesImageInspectionInput {
|
|
341
|
+
readonly tools?: unknown;
|
|
342
|
+
readonly tool_choice?: unknown;
|
|
343
|
+
readonly stream?: unknown;
|
|
344
|
+
readonly previous_response_id?: unknown;
|
|
345
|
+
readonly input?: unknown;
|
|
346
|
+
}
|
|
347
|
+
interface ResponsesImageNormalizedOptions {
|
|
348
|
+
readonly action: ResponsesImageAction;
|
|
349
|
+
readonly quality: ImageQuality;
|
|
350
|
+
readonly size: ImageSize;
|
|
351
|
+
readonly background: ImageBackground;
|
|
352
|
+
readonly outputFormat: ImageOutputFormat;
|
|
353
|
+
readonly outputCompression?: number;
|
|
354
|
+
readonly partialImages: number;
|
|
355
|
+
}
|
|
356
|
+
type ResponsesImageSelectionPolicy = {
|
|
357
|
+
readonly kind: 'auto';
|
|
358
|
+
} | {
|
|
359
|
+
readonly kind: 'required';
|
|
360
|
+
} | {
|
|
361
|
+
readonly kind: 'none';
|
|
362
|
+
} | {
|
|
363
|
+
readonly kind: 'forced_image';
|
|
364
|
+
} | {
|
|
365
|
+
readonly kind: 'forced_other';
|
|
366
|
+
readonly toolType: string;
|
|
367
|
+
readonly toolName?: string;
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Closed identity for one non-image declaration. The declaration index is the
|
|
371
|
+
* trust anchor: selected plans cannot invent a type/name. Multiple bounded
|
|
372
|
+
* calls may reuse one declaration while their wire item/call IDs stay unique.
|
|
373
|
+
*/
|
|
374
|
+
interface ResponsesHostedToolIdentity {
|
|
375
|
+
readonly declarationIndex: number;
|
|
376
|
+
readonly type: string;
|
|
377
|
+
readonly name?: string;
|
|
378
|
+
}
|
|
379
|
+
interface ResponsesImageAdmission {
|
|
380
|
+
readonly declared: boolean;
|
|
381
|
+
readonly imageToolIndex?: number;
|
|
382
|
+
readonly otherToolCount: number;
|
|
383
|
+
readonly otherTools: readonly ResponsesHostedToolIdentity[];
|
|
384
|
+
readonly stream: boolean;
|
|
385
|
+
readonly previousResponseId?: string;
|
|
386
|
+
readonly explicitCallIds: readonly ResponsesImageCallId[];
|
|
387
|
+
readonly selectionPolicy: ResponsesImageSelectionPolicy;
|
|
388
|
+
readonly options?: ResponsesImageNormalizedOptions;
|
|
389
|
+
}
|
|
390
|
+
interface ResponsesSelectedImageCall {
|
|
391
|
+
readonly prompt: string;
|
|
392
|
+
}
|
|
393
|
+
interface ResponsesHostedToolSelection {
|
|
394
|
+
readonly imageCalls: readonly ResponsesSelectedImageCall[];
|
|
395
|
+
readonly otherToolCount: number;
|
|
396
|
+
readonly otherTools: readonly ResponsesHostedToolIdentity[];
|
|
397
|
+
}
|
|
398
|
+
interface ResponsesImageEventAllocator {
|
|
399
|
+
reserveOutputIndex(): number;
|
|
400
|
+
nextSequenceNumber(): number;
|
|
401
|
+
}
|
|
402
|
+
interface ResponsesImageCallBinding {
|
|
403
|
+
readonly callId: ResponsesImageCallId;
|
|
404
|
+
readonly referenceId: ImageReferenceId;
|
|
405
|
+
readonly expiresAt: number;
|
|
406
|
+
}
|
|
407
|
+
interface ResponsesImageGenerationCallItem {
|
|
408
|
+
readonly id: ResponsesImageCallId;
|
|
409
|
+
readonly type: 'image_generation_call';
|
|
410
|
+
readonly status: 'completed';
|
|
411
|
+
readonly result: string;
|
|
412
|
+
readonly revised_prompt?: string;
|
|
413
|
+
}
|
|
414
|
+
interface ResponsesImageGenerationCallStartedItem {
|
|
415
|
+
readonly id: ResponsesImageCallId;
|
|
416
|
+
readonly type: 'image_generation_call';
|
|
417
|
+
readonly status: 'in_progress';
|
|
418
|
+
}
|
|
419
|
+
interface ResponsesImagePartialEvent {
|
|
420
|
+
readonly type: 'response.image_generation_call.partial_image';
|
|
421
|
+
readonly output_index: number;
|
|
422
|
+
readonly item_id: ResponsesImageCallId;
|
|
423
|
+
readonly sequence_number: number;
|
|
424
|
+
readonly partial_image_index: number;
|
|
425
|
+
readonly partial_image_b64: string;
|
|
426
|
+
}
|
|
427
|
+
/** Internal start record; the integrator owns official item-added SSE events. */
|
|
428
|
+
interface ResponsesImageStartedRecord {
|
|
429
|
+
readonly kind: 'started';
|
|
430
|
+
readonly outputIndex: number;
|
|
431
|
+
readonly item: ResponsesImageGenerationCallStartedItem;
|
|
432
|
+
}
|
|
433
|
+
/** Internal terminal record; the integrator owns official terminal SSE events. */
|
|
434
|
+
interface ResponsesImageCompletedRecord {
|
|
435
|
+
readonly kind: 'completed';
|
|
436
|
+
readonly outputIndex: number;
|
|
437
|
+
readonly item: ResponsesImageGenerationCallItem;
|
|
438
|
+
}
|
|
439
|
+
/** Internal failure record for the integrator's normal Responses error path. */
|
|
440
|
+
interface ResponsesImageFailedRecord {
|
|
441
|
+
readonly kind: 'failed';
|
|
442
|
+
readonly outputIndex?: number;
|
|
443
|
+
readonly callId?: ResponsesImageCallId;
|
|
444
|
+
readonly error: ImageGenerationPublicError;
|
|
445
|
+
}
|
|
446
|
+
type ResponsesImageExecutionEvent = ResponsesImageStartedRecord | ResponsesImagePartialEvent | ResponsesImageCompletedRecord | ResponsesImageFailedRecord;
|
|
447
|
+
interface ResponsesImageTrustedRuntime {
|
|
448
|
+
readonly tenantId: string;
|
|
449
|
+
readonly requestId: string;
|
|
450
|
+
readonly providerId: string;
|
|
451
|
+
readonly imageModel: string;
|
|
452
|
+
readonly referenceTtlMs: number;
|
|
453
|
+
readonly maxOutputBytes: number;
|
|
454
|
+
readonly maxTotalOutputBytes: number;
|
|
455
|
+
readonly signal: AbortSignal;
|
|
456
|
+
readonly sessionKey?: string;
|
|
457
|
+
readonly preferredAccountId?: string;
|
|
458
|
+
readonly preferredAccountGroup?: string;
|
|
459
|
+
readonly boundAccountFallbackPolicy?: 'strict' | 'pool';
|
|
460
|
+
}
|
|
461
|
+
interface ResponsesImageRequestScopeInput {
|
|
462
|
+
readonly admission: ResponsesImageAdmission;
|
|
463
|
+
readonly runtime: ResponsesImageTrustedRuntime;
|
|
464
|
+
/** Must already be authorized by the existing Responses affinity boundary. */
|
|
465
|
+
readonly authorizedPreviousResponseId?: string;
|
|
466
|
+
/** True only when that authorized affinity record explicitly has no image context. */
|
|
467
|
+
readonly authorizedPreviousResponseKnownEmpty?: boolean;
|
|
468
|
+
}
|
|
469
|
+
interface ResponsesImageRequestScope {
|
|
470
|
+
executeSelectedCall(call: ResponsesSelectedImageCall, allocator: ResponsesImageEventAllocator): AsyncIterable<ResponsesImageExecutionEvent>;
|
|
471
|
+
commit(responseId: string): Promise<void>;
|
|
472
|
+
dispose(): Promise<void>;
|
|
473
|
+
waitForIdle(): Promise<void>;
|
|
474
|
+
}
|
|
475
|
+
interface ResponsesImageGenerationContributionDeps {
|
|
476
|
+
readonly orchestrator: ImageOrchestrator;
|
|
477
|
+
readonly stateStore: ResponsesImageStateStore;
|
|
478
|
+
/** Must be the same store injected into the orchestrator. */
|
|
479
|
+
readonly referenceStore: ImageReferenceStore;
|
|
480
|
+
readonly createCallId?: () => ResponsesImageCallId;
|
|
481
|
+
readonly now?: () => number;
|
|
482
|
+
}
|
|
483
|
+
interface ResponsesImageGenerationContribution {
|
|
484
|
+
readonly toolType: 'image_generation';
|
|
485
|
+
inspectRequest(input: ResponsesImageInspectionInput): ResponsesImageAdmission;
|
|
486
|
+
validateSelection(admission: ResponsesImageAdmission, selection: ResponsesHostedToolSelection): void;
|
|
487
|
+
createRequestScope(input: ResponsesImageRequestScopeInput): Promise<ResponsesImageRequestScope>;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
type ResponsesCredentialIdentity = {
|
|
491
|
+
readonly kind: 'subscription-account';
|
|
492
|
+
readonly id: string;
|
|
493
|
+
} | {
|
|
494
|
+
readonly kind: 'byo-key';
|
|
495
|
+
readonly id: string;
|
|
496
|
+
} | {
|
|
497
|
+
readonly kind: 'provider-key';
|
|
498
|
+
readonly id: string;
|
|
499
|
+
};
|
|
500
|
+
interface ResponsesAffinityScope {
|
|
501
|
+
readonly providerId: string;
|
|
502
|
+
readonly clientScope: string;
|
|
503
|
+
readonly sessionKey: string;
|
|
504
|
+
}
|
|
505
|
+
interface ResponsesAffinityPendingImageReceipt {
|
|
506
|
+
readonly upstreamCallId: string;
|
|
507
|
+
readonly publicImageCallId: string;
|
|
508
|
+
}
|
|
509
|
+
interface ResponsesAffinityHostedImageState {
|
|
510
|
+
readonly hasImageContext: boolean;
|
|
511
|
+
readonly pendingReceipts: readonly ResponsesAffinityPendingImageReceipt[];
|
|
512
|
+
}
|
|
513
|
+
interface ResponsesAffinityRecord extends ResponsesAffinityScope {
|
|
514
|
+
readonly responseId: string;
|
|
515
|
+
readonly credential: ResponsesCredentialIdentity;
|
|
516
|
+
readonly hostedImage?: ResponsesAffinityHostedImageState;
|
|
517
|
+
}
|
|
518
|
+
interface ResponsesAffinityEntry extends ResponsesAffinityRecord {
|
|
519
|
+
readonly expiresAt: number;
|
|
520
|
+
}
|
|
521
|
+
interface ResponsesAffinityStoreOptions {
|
|
522
|
+
readonly maxEntries?: number;
|
|
523
|
+
readonly ttlMs?: number;
|
|
524
|
+
readonly now?: () => number;
|
|
525
|
+
}
|
|
526
|
+
declare function previousResponseNotFound(): OpenAIOperationError;
|
|
527
|
+
/** Bounded process-local response identity index with sliding expiry and LRU eviction. */
|
|
528
|
+
declare class ResponsesAffinityStore {
|
|
529
|
+
private readonly entries;
|
|
530
|
+
private readonly maxEntries;
|
|
531
|
+
private readonly ttlMs;
|
|
532
|
+
private readonly now;
|
|
533
|
+
constructor(options?: ResponsesAffinityStoreOptions);
|
|
534
|
+
get size(): number;
|
|
535
|
+
record(record: ResponsesAffinityRecord): void;
|
|
536
|
+
/** Lookup never discloses whether an id exists in another provider/client/session scope. */
|
|
537
|
+
lookup(responseId: string, scope: ResponsesAffinityScope): ResponsesAffinityEntry;
|
|
538
|
+
clear(): void;
|
|
539
|
+
private pruneExpired;
|
|
540
|
+
}
|
|
541
|
+
/** Resolve one affinity store per app-session dependency container. */
|
|
542
|
+
declare function getResponsesAffinityStore(owner: object): ResponsesAffinityStore;
|
|
543
|
+
|
|
544
|
+
type ResponsesProfile = 'native' | 'reduced';
|
|
545
|
+
interface ResponsesProfileDeclaration {
|
|
546
|
+
readonly authMode: 'byo' | 'subscription';
|
|
547
|
+
readonly providerApiFormat?: ApiFormat;
|
|
548
|
+
readonly subscriptionProviderId?: string;
|
|
549
|
+
readonly subscriptionTransformerNames?: readonly string[];
|
|
550
|
+
readonly upstreamUrl?: string;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Resolve the protocol contract from explicit provider metadata. Transformer
|
|
554
|
+
* instance identity and transformer-array equality are deliberately irrelevant.
|
|
555
|
+
*/
|
|
556
|
+
declare function classifyResponsesProfile(declaration: ResponsesProfileDeclaration): ResponsesProfile;
|
|
557
|
+
|
|
558
|
+
interface ResponsesHostedImageOpenRequestInput {
|
|
559
|
+
readonly admission: ResponsesImageAdmission;
|
|
560
|
+
readonly tenantId: string;
|
|
561
|
+
readonly requestId: string;
|
|
562
|
+
readonly sessionKey: string;
|
|
563
|
+
readonly signal: AbortSignal;
|
|
564
|
+
readonly authorizedPreviousResponseId?: string;
|
|
565
|
+
/** Derived only from the authorized affinity record, never from request input. */
|
|
566
|
+
readonly authorizedPreviousResponseKnownEmpty?: boolean;
|
|
567
|
+
readonly mainProviderId: string;
|
|
568
|
+
readonly selectedMainAccountId?: string;
|
|
569
|
+
}
|
|
570
|
+
/** Structural app-session port implemented by the daemon's pinned image generation. */
|
|
571
|
+
interface ResponsesHostedImageRuntimeLease {
|
|
572
|
+
readonly generationId: string;
|
|
573
|
+
inspectRequest(input: ResponsesImageInspectionInput): ResponsesImageAdmission;
|
|
574
|
+
validateSelection(admission: ResponsesImageAdmission, selection: ResponsesHostedToolSelection): void;
|
|
575
|
+
openRequest(input: ResponsesHostedImageOpenRequestInput): Promise<ResponsesImageRequestScope>;
|
|
576
|
+
release(): Promise<void>;
|
|
577
|
+
}
|
|
578
|
+
/** Dormant until an admitted Responses request explicitly acquires it. */
|
|
579
|
+
interface ResponsesHostedImageRuntimeFactory {
|
|
580
|
+
acquire(): Promise<ResponsesHostedImageRuntimeLease>;
|
|
581
|
+
}
|
|
582
|
+
interface ResponsesHostedImagePrepareInput {
|
|
583
|
+
readonly body: Readonly<Record<string, unknown>>;
|
|
584
|
+
readonly profile: ResponsesProfile;
|
|
585
|
+
readonly operation: 'create' | 'compact';
|
|
586
|
+
readonly hostedImageGenerationAllowed: boolean;
|
|
587
|
+
readonly tenantId?: string;
|
|
588
|
+
readonly sessionKey: string;
|
|
589
|
+
readonly authorizedPreviousResponseId?: string;
|
|
590
|
+
readonly previousHostedImageState?: ResponsesAffinityHostedImageState;
|
|
591
|
+
readonly mainProviderId: string;
|
|
592
|
+
readonly signal: AbortSignal;
|
|
593
|
+
}
|
|
594
|
+
interface ResponsesHostedImageWrapInput {
|
|
595
|
+
readonly response: Response;
|
|
596
|
+
readonly rawStatus: number | null;
|
|
597
|
+
readonly selectedMainAccountId?: string;
|
|
598
|
+
readonly onTerminalSuccess: (responseId: string, state: ResponsesAffinityHostedImageState) => void | Promise<void>;
|
|
599
|
+
}
|
|
600
|
+
interface ResponsesHostedImageRequestLease {
|
|
601
|
+
readonly upstreamBody: Record<string, unknown>;
|
|
602
|
+
wrapUpstreamResponse(input: ResponsesHostedImageWrapInput): Promise<Response>;
|
|
603
|
+
dispose(): Promise<void>;
|
|
604
|
+
}
|
|
605
|
+
/** Deep Native Responses mediator; ingress owns only prepare/wrap/dispose composition. */
|
|
606
|
+
interface ResponsesHostedImageIngress {
|
|
607
|
+
prepare(input: ResponsesHostedImagePrepareInput): Promise<ResponsesHostedImageRequestLease | null>;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Shared contract types for the resident `ProviderProxy`.
|
|
612
|
+
*
|
|
613
|
+
* The `ProviderProxy` (OpenSpec `engine-provider-decouple`, design D0/D3/D7/D9)
|
|
614
|
+
* is the single resident `127.0.0.1` listener that subsumes both of the
|
|
615
|
+
* host's per-session proxies (Anthropic Messages ingress and OpenAI Responses
|
|
616
|
+
* ingress). Per-run state lives in a `Map<token, RouteContext>`
|
|
617
|
+
* minted at run start and reaped at run end / on idle TTL.
|
|
618
|
+
*
|
|
619
|
+
* These types are kept in their own module so the server, route map, router,
|
|
620
|
+
* and the two ingress parsers can share shapes without importing one another
|
|
621
|
+
* for type-only purposes.
|
|
622
|
+
*
|
|
623
|
+
* @module provider-proxy/types
|
|
624
|
+
*/
|
|
625
|
+
|
|
626
|
+
/** Callback for retry events (client toast). */
|
|
627
|
+
type RetryCallback = (info: {
|
|
628
|
+
attempt: number;
|
|
629
|
+
maxAttempts: number;
|
|
630
|
+
delayMs: number;
|
|
631
|
+
statusCode: number;
|
|
632
|
+
error?: string;
|
|
633
|
+
}) => void;
|
|
634
|
+
/** Callback for real-time SSE streaming events (content_block_delta, content_block_start, etc.) */
|
|
635
|
+
type StreamEventCallback = (event: Record<string, unknown>) => void;
|
|
636
|
+
/**
|
|
637
|
+
* Routing attribution carried alongside usage records — `messageId` is per-request
|
|
638
|
+
* and unknown at this layer, so only the persistent `sessionId` + `apiKeyId` flow
|
|
639
|
+
* through.
|
|
640
|
+
*/
|
|
641
|
+
interface ProxyAttribution {
|
|
642
|
+
sessionId?: string | null;
|
|
643
|
+
apiKeyId?: string | null;
|
|
644
|
+
/** Token-free Route Lease attribution; never contains the bearer token. */
|
|
645
|
+
routeLease?: RouteLeaseUsageAttribution | null;
|
|
646
|
+
}
|
|
647
|
+
interface RouteLeaseUsageAttribution {
|
|
648
|
+
readonly leaseId: string;
|
|
649
|
+
readonly consumer: string;
|
|
650
|
+
readonly runId?: string;
|
|
651
|
+
readonly stageId?: string;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* 1M-context opt-in for outbound Anthropic requests. Populated by
|
|
655
|
+
* the host's Claude-SDK engine from the active session's `cliBackend` /
|
|
656
|
+
* `useExtendedContext` schema fields. When `enabled` is true and `model`
|
|
657
|
+
* is in the 1M-capable allowlist, `injectExtendedContextBeta` adds
|
|
658
|
+
* `'context-1m-2025-08-07'` to the request's `anthropic-beta` header
|
|
659
|
+
* before transport.
|
|
660
|
+
*/
|
|
661
|
+
interface ExtendedContextHint {
|
|
662
|
+
enabled: boolean;
|
|
663
|
+
model: string;
|
|
664
|
+
}
|
|
665
|
+
/** Lightweight summary derived from the inbound Anthropic request body —
|
|
666
|
+
* consumed by `modelMapper` (scenario routing) without full body access. */
|
|
667
|
+
interface SubscriptionRequestSummary {
|
|
668
|
+
messageCount: number;
|
|
669
|
+
/** cl100k_base-estimated token count of system + messages (no tools). */
|
|
670
|
+
estimatedInputTokens: number;
|
|
671
|
+
/**
|
|
672
|
+
* OPTIONAL bounded per-message text slice (system prompt + the most recent
|
|
673
|
+
* user/system messages, each per-message-capped) consumed ONLY by the
|
|
674
|
+
* OpenCodeGo keyword matcher in `@omnicross/subscriptions`
|
|
675
|
+
* (`resolveOpenCodeGoScenario`). Core only WRITES this `string[]`; it never
|
|
676
|
+
* reads it and never names the matcher — keeping the cross-layer litmus at 0
|
|
677
|
+
* (no `@omnicross/core` → `@omnicross/subscriptions` edge). Optional so callers
|
|
678
|
+
* that omit it (legacy/tests) compile and degrade to the token-threshold +
|
|
679
|
+
* `default` routing.
|
|
680
|
+
*/
|
|
681
|
+
matchText?: string[];
|
|
682
|
+
}
|
|
683
|
+
interface SubscriptionDispatchProfile {
|
|
684
|
+
readonly providerId: SubscriptionProviderId;
|
|
685
|
+
readonly displayName: string;
|
|
686
|
+
readonly authStrategy: AuthStrategy;
|
|
687
|
+
/** Pass-through providers (Claude) skip the transformer chain entirely.
|
|
688
|
+
* Transformer providers use the chain below + the proxy's existing
|
|
689
|
+
* `AnthropicTransformer` endpoint reverse-decoder. */
|
|
690
|
+
readonly mode: 'pass-through' | 'transformer';
|
|
691
|
+
/** Resolve the upstream URL for a given resolved model id. Required for
|
|
692
|
+
* `mode === 'transformer'`; unused for pass-through (proxy hard-codes
|
|
693
|
+
* `api.anthropic.com`). The OPTIONAL 2nd `config` arg lets the opencodego
|
|
694
|
+
* profile honor a per-account `baseUrl` override (D1) — additive, so existing
|
|
695
|
+
* one-arg callers compile unchanged. */
|
|
696
|
+
readonly resolveUpstreamUrl?: (resolvedModel: string, config?: OpenCodeGoTokenConfig) => string;
|
|
697
|
+
/** Names of transformers (registered in `TransformerService`) to run on the
|
|
698
|
+
* provider chain. The proxy adds `AnthropicTransformer` as the endpoint
|
|
699
|
+
* reverse-decoder. */
|
|
700
|
+
readonly providerTransformerNames?: readonly string[];
|
|
701
|
+
readonly modelTransformerNames?: readonly string[];
|
|
702
|
+
/**
|
|
703
|
+
* OPTIONAL shape-aware provider transformer-name resolver (opencodego zen).
|
|
704
|
+
* Parallel to `resolveUpstreamUrl(model, config)`: lets a profile vary its
|
|
705
|
+
* provider chain by the RESOLVED model's wire shape (e.g. zen `responses` ⇒
|
|
706
|
+
* `['openai-response']`, `gemini` ⇒ `['gemini']`). `config` is `unknown` on the
|
|
707
|
+
* core side (opaque-config discipline — core never names
|
|
708
|
+
* `OpenCodeGoTokenConfig` from `@omnicross/subscriptions`); the subscriptions
|
|
709
|
+
* implementation narrows it. When ABSENT, both ingress paths fall back to the
|
|
710
|
+
* static `providerTransformerNames` — BYTE-IDENTICAL for claude / codex / gemini
|
|
711
|
+
* (which leave this unset). Purely additive (optional).
|
|
712
|
+
*/
|
|
713
|
+
readonly resolveProviderTransformerNames?: (model: string, config?: unknown) => readonly string[];
|
|
714
|
+
/** Optional model placeholder rewriter — only set for OpenCodeGo. */
|
|
715
|
+
readonly modelMapper?: (sdkModel: string, summary: SubscriptionRequestSummary, config: OpenCodeGoTokenConfig | undefined) => {
|
|
716
|
+
resolvedModel: string;
|
|
717
|
+
scenario: OpenCodeGoScenario;
|
|
718
|
+
};
|
|
719
|
+
/** Optional fallback resolver — for OpenCodeGo, picks the next model after
|
|
720
|
+
* an unrecoverable error. Returns `null` when exhausted. Cap = 3. The
|
|
721
|
+
* opencodego implementation ALSO consults the circuit breaker (D5): it skips
|
|
722
|
+
* models whose circuit is open. */
|
|
723
|
+
readonly nextFallback?: (scenario: OpenCodeGoScenario, attempted: readonly string[], config: OpenCodeGoTokenConfig | undefined) => OpenCodeGoModelEntry | null;
|
|
724
|
+
/** Optional circuit-breaker admission gate for the PRIMARY (mapped) model
|
|
725
|
+
* (D5 primary-gating). Only set for OpenCodeGo. Returns whether `modelId`'s
|
|
726
|
+
* circuit currently admits a request (side-effecting: flips an `open` model
|
|
727
|
+
* to `half-open` once its window elapses, exactly like `nextFallback`'s
|
|
728
|
+
* internal consult). `nextFallback` covers the FALLBACKS; this covers the
|
|
729
|
+
* primary the loop already holds. Absent/undefined ⇒ the loop treats the
|
|
730
|
+
* primary as always admitted (claude / codex / gemini have no breaker). */
|
|
731
|
+
readonly allowModel?: (modelId: string) => boolean;
|
|
732
|
+
/** Optional record-outcome callback (D5 record seam). Only set for OpenCodeGo.
|
|
733
|
+
* Both fallback loops invoke it after each attempt: `ok: true` on a `2xx`,
|
|
734
|
+
* `ok: false` on a thrown/network error / `5xx` / `429`; a non-429 `4xx` is
|
|
735
|
+
* NEUTRAL and the loops MUST NOT call it. Drives the per-model breaker.
|
|
736
|
+
* Absent/undefined for claude / codex / gemini ⇒ a no-op (no breaker). */
|
|
737
|
+
readonly recordModelOutcome?: (modelId: string, ok: boolean) => void;
|
|
738
|
+
}
|
|
739
|
+
/** The single-entry handler the Anthropic ingress drives per request. */
|
|
740
|
+
interface AnthropicIngressHandler {
|
|
741
|
+
handle(req: http.IncomingMessage, res: http.ServerResponse): Promise<void>;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Per-run inputs the resident proxy threads into the ingress handler factory.
|
|
745
|
+
* Structural mirror of the host's `RouteHandlerParams` — kept here so the
|
|
746
|
+
* ingress + `ProviderProxyDeps` do not import upward. The host's
|
|
747
|
+
* `RouteHandlerParams` re-exports / aligns to this shape (so its
|
|
748
|
+
* request-handler factory is assignable to the factory type below).
|
|
749
|
+
*/
|
|
750
|
+
interface AnthropicRouteHandlerParams {
|
|
751
|
+
readonly llmConfig: ProviderConfigSource;
|
|
752
|
+
readonly providerId: string;
|
|
753
|
+
readonly model: string;
|
|
754
|
+
readonly apiKey: string;
|
|
755
|
+
readonly backgroundTaskModel?: string;
|
|
756
|
+
readonly isOfficialProvider: boolean;
|
|
757
|
+
readonly thinkingLevel?: ThinkLevel;
|
|
758
|
+
readonly extendedContext?: ExtendedContextHint | null;
|
|
759
|
+
readonly passThrough: boolean;
|
|
760
|
+
/** Upstream Bearer for the pass-through path (resident-proxy route token swap). */
|
|
761
|
+
readonly passThroughAuthToken?: string | null;
|
|
762
|
+
/** Lazy per-request resolver for the pass-through Bearer (takes precedence over the static one). */
|
|
763
|
+
readonly resolvePassThroughAuthToken?: (() => Promise<string | null>) | null;
|
|
764
|
+
readonly subscriptionProfile?: SubscriptionDispatchProfile | null;
|
|
765
|
+
/** Bound subscription account forwarded to the host's Anthropic handler. */
|
|
766
|
+
readonly preferredAccountId?: string;
|
|
767
|
+
readonly preferredAccountGroup?: string;
|
|
768
|
+
/** Strict by default; pool fallback is an explicit endpoint opt-in. */
|
|
769
|
+
readonly boundAccountFallbackPolicy?: BoundAccountFallbackPolicy;
|
|
770
|
+
/** Preferred provider-pool key selected by a resource-level binding. */
|
|
771
|
+
readonly preferredKeyId?: string;
|
|
772
|
+
/** Strict by default; pool fallback is an explicit binding opt-in. */
|
|
773
|
+
readonly boundKeyFallbackPolicy?: BoundAccountFallbackPolicy;
|
|
774
|
+
readonly maxConcurrency?: number;
|
|
775
|
+
/** Instance-level web-search backend; falls back to the proxy-global one. */
|
|
776
|
+
readonly webSearchService?: WebSearchBackend | null;
|
|
777
|
+
readonly onRetry?: RetryCallback;
|
|
778
|
+
readonly onStreamEvent?: StreamEventCallback;
|
|
779
|
+
readonly usageRecorder?: UsageRecorderImport | null;
|
|
780
|
+
readonly attribution?: ProxyAttribution | null;
|
|
781
|
+
}
|
|
782
|
+
/** Factory that builds a per-request Anthropic ingress handler. */
|
|
783
|
+
type AnthropicIngressHandlerFactory = (params: AnthropicRouteHandlerParams) => AnthropicIngressHandler;
|
|
784
|
+
/**
|
|
785
|
+
* Wire format the proxy ingests for a given route. Phase 1 landed the two
|
|
786
|
+
* already-sound parsers (`anthropic-messages`, `openai-responses`);
|
|
787
|
+
* `provider-proxy-transformer-matrix` adds `openai-chat` (qwen / copilot /
|
|
788
|
+
* opencode) and `gemini-generatecontent` (gemini-CLI api-key/relay) — completing
|
|
789
|
+
* the resident proxy's 4-ingress-parser matrix.
|
|
790
|
+
*/
|
|
791
|
+
type IngressFormat = 'anthropic-messages' | 'openai-responses' | 'openai-chat' | 'gemini-generatecontent';
|
|
792
|
+
/**
|
|
793
|
+
* The target Provider's wire format. The proxy's internal pass-through-vs-
|
|
794
|
+
* transform decision is keyed on `(ingressFormat, targetProviderFormat)`:
|
|
795
|
+
* when they MATCH the request is passed through + re-authed; otherwise it is
|
|
796
|
+
* transformed through the Unified chain (design D3).
|
|
797
|
+
*
|
|
798
|
+
* NOTE: `'anthropic'` here is the FORMAT family, not a provider id. An official
|
|
799
|
+
* or third-party Anthropic Messages provider is `'anthropic'`; an
|
|
800
|
+
* OpenAI-compatible / Responses provider is `'openai-responses'`.
|
|
801
|
+
*/
|
|
802
|
+
type TargetProviderFormat = 'anthropic' | 'openai-responses' | 'transform';
|
|
803
|
+
/**
|
|
804
|
+
* How the proxy re-authenticates a route upstream. `'byo'` resolves the key
|
|
805
|
+
* from an LLM-config provider row (with optional `ApiKeyPool` failover);
|
|
806
|
+
* `'subscription'` re-auths via a subscription `AuthStrategy` (OAuth bearer +
|
|
807
|
+
* 401 refresh). The forwarded route-token sentinel is ALWAYS discarded — the
|
|
808
|
+
* proxy never trusts the CLI/SDK-carried key.
|
|
809
|
+
*/
|
|
810
|
+
type RouteAuthMode = 'byo' | 'subscription';
|
|
811
|
+
/**
|
|
812
|
+
* The Anthropic SDK-hint bundle carried on a `RouteContext` for routes whose
|
|
813
|
+
* ingress is `'anthropic-messages'`. The Anthropic path is NOT re-implemented
|
|
814
|
+
* inside the resident proxy — it is DELEGATED wholesale to the host's existing
|
|
815
|
+
* per-request proxy handler (engine-provider-decouple task 2.10, "delegate for
|
|
816
|
+
* parity"). That handler keeps owning its own upstream fetch + all the SDK
|
|
817
|
+
* quirks (probe-mock, local web-search interception, thinkingLevel / 1M-context
|
|
818
|
+
* beta injection, subscription dispatch, and the 5h/7d window header taps) — so
|
|
819
|
+
* everything the host proxy used to receive per session is threaded here per
|
|
820
|
+
* run and fed straight into the per-request handler factory.
|
|
821
|
+
*
|
|
822
|
+
* D7 conversion-SSOT is ALREADY MET: the delegated host handler runs
|
|
823
|
+
* its Anthropic⇄Unified⇄provider conversion through the SAME shared pipeline
|
|
824
|
+
* SSOT (`executeProviderCall` + `AnthropicTransformer`) that the Responses /
|
|
825
|
+
* OpenAI-Chat / Gemini ingresses use — there is no second conversion stack. The
|
|
826
|
+
* SDK quirks listed above (probe / web-search / thinking / window-tap) are
|
|
827
|
+
* INGRESS concerns and deliberately stay at the ingress under the design's
|
|
828
|
+
* ingress-vs-core split; they are NOT folded into the shared core.
|
|
829
|
+
*/
|
|
830
|
+
interface AnthropicSdkHints {
|
|
831
|
+
/** Real provider key (resolved at run start) for `getProviderHeaders`. */
|
|
832
|
+
readonly apiKey: string;
|
|
833
|
+
/** Official-Anthropic provider → skip probe caching + transformer pipeline. */
|
|
834
|
+
readonly isOfficialProvider: boolean;
|
|
835
|
+
/** claude-code OAuth pass-through (forward to api.anthropic.com verbatim). */
|
|
836
|
+
readonly passThrough: boolean;
|
|
837
|
+
/**
|
|
838
|
+
* Host-managed OAuth Bearer token for the pass-through path. With the
|
|
839
|
+
* resident proxy the SDK forwards the route TOKEN as its `Authorization`
|
|
840
|
+
* header (used only for route lookup, then discarded), so the real upstream
|
|
841
|
+
* Bearer can no longer ride the SDK header — it is carried here and
|
|
842
|
+
* re-applied by the pass-through forwarder. `null`/absent → fall back to the
|
|
843
|
+
* SDK's own forwarded credential (system `~/.claude/.credentials.json`).
|
|
844
|
+
*/
|
|
845
|
+
readonly passThroughAuthToken?: string | null;
|
|
846
|
+
/**
|
|
847
|
+
* OPTIONAL lazy resolver for the pass-through upstream Bearer, evaluated at
|
|
848
|
+
* REQUEST time rather than route-build time. When present it takes precedence
|
|
849
|
+
* over the static `passThroughAuthToken`, so a long-lived route always forwards
|
|
850
|
+
* a freshly auto-refreshed token (the host re-reads its OAuth store / system
|
|
851
|
+
* credentials per request) instead of the one captured when the route was
|
|
852
|
+
* built — that capture is what makes a session outlive its token and 401
|
|
853
|
+
* mid-run. Returns `null` (or throws) to fall back to the static token.
|
|
854
|
+
*/
|
|
855
|
+
readonly resolvePassThroughAuthToken?: (() => Promise<string | null>) | null;
|
|
856
|
+
/** User thinking-budget preference (Anthropic-direct + reasoning chain). */
|
|
857
|
+
readonly thinkingLevel?: ThinkLevel;
|
|
858
|
+
/** 1M-context opt-in (injects `context-1m-2025-08-07` into anthropic_beta). */
|
|
859
|
+
readonly extendedContext?: ExtendedContextHint | null;
|
|
860
|
+
/** Subscription dispatch profile (Codex/Gemini/OpenCodeGo over the SDK wire). */
|
|
861
|
+
readonly subscriptionProfile?: SubscriptionDispatchProfile | null;
|
|
862
|
+
/** Bound subscription account for the delegated Anthropic path. */
|
|
863
|
+
readonly preferredAccountId?: string;
|
|
864
|
+
readonly preferredAccountGroup?: string;
|
|
865
|
+
/** Strict by default; pool fallback is an explicit endpoint opt-in. */
|
|
866
|
+
readonly boundAccountFallbackPolicy?: BoundAccountFallbackPolicy;
|
|
867
|
+
/** Preferred provider-pool key for a delegated BYO Anthropic route. */
|
|
868
|
+
readonly preferredKeyId?: string;
|
|
869
|
+
/** Strict by default; pool fallback is an explicit binding opt-in. */
|
|
870
|
+
readonly boundKeyFallbackPolicy?: BoundAccountFallbackPolicy;
|
|
871
|
+
/** Per-request max-concurrency cap for the error-handler semaphore. */
|
|
872
|
+
readonly maxConcurrency?: number;
|
|
873
|
+
/** Instance-level web-search backend (falls back to the proxy-global one). */
|
|
874
|
+
readonly webSearchService?: WebSearchBackend | null;
|
|
875
|
+
/** Retry-event callback (client toast). */
|
|
876
|
+
readonly onRetry?: RetryCallback;
|
|
877
|
+
/** Real-time SSE event callback (client live-display). */
|
|
878
|
+
readonly onStreamEvent?: StreamEventCallback;
|
|
879
|
+
/** Usage attribution (sessionId + apiKeyId) for recorded usage rows. */
|
|
880
|
+
readonly attribution?: ProxyAttribution | null;
|
|
881
|
+
/**
|
|
882
|
+
* The usage recorder (`UsageRecorderImport` port) for the delegated
|
|
883
|
+
* stream-manager taps (stream + non-stream + 5h/7d window). Per-run
|
|
884
|
+
* because `buildProviderEnvWithProxy` resolves it from the explicit arg ??
|
|
885
|
+
* the module-level recorder, exactly as the host proxy received it. The
|
|
886
|
+
* host injects its concrete usage-recorder service, which satisfies the port.
|
|
887
|
+
*/
|
|
888
|
+
readonly usageRecorder?: UsageRecorderImport | null;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Per-run routing context, looked up by the crypto route token carried in the
|
|
892
|
+
* forwarded `Authorization` sentinel. Shaped to exactly what the pipeline call
|
|
893
|
+
* (`executeProviderCall` + the `endpointTransformer` seam) needs to re-auth and
|
|
894
|
+
* route a single run's traffic. There is NO fallback: a token miss or an
|
|
895
|
+
* expired entry is rejected (design D9).
|
|
896
|
+
*/
|
|
897
|
+
interface RouteContext {
|
|
898
|
+
/** Owning chat session id — usage attribution + ApiKeyPool affinity. */
|
|
899
|
+
readonly sessionId: string | null;
|
|
900
|
+
/**
|
|
901
|
+
* Target Provider's wire format. Drives the internal pass-through-vs-transform
|
|
902
|
+
* decision against the route's `ingressFormat`.
|
|
903
|
+
*/
|
|
904
|
+
readonly targetProviderFormat: TargetProviderFormat;
|
|
905
|
+
/** Resolved provider model the upstream request targets. */
|
|
906
|
+
readonly model: string;
|
|
907
|
+
/**
|
|
908
|
+
* The client's ORIGINAL requested model id, for RESPONSE `model` passthrough
|
|
909
|
+
* on the kind-mapped outbound endpoints (`messages`/`responses`). Stamped ONLY
|
|
910
|
+
* by the outbound `resolveRoute` for those endpoints; the resident-proxy route
|
|
911
|
+
* minting path leaves it `undefined`, so internal completions are never
|
|
912
|
+
* rewritten (the two kind-mapped ingresses pass it as `relayResponse`'s
|
|
913
|
+
* `rewriteModel` — undefined ⇒ byte-identical passthrough).
|
|
914
|
+
*/
|
|
915
|
+
readonly requestedModel?: string;
|
|
916
|
+
/**
|
|
917
|
+
* The outbound named-key id (`verified.id`) this request authenticated with,
|
|
918
|
+
* for usage attribution (the ByApiKey view). Stamped ONLY by the outbound
|
|
919
|
+
* `resolveRoute`; the resident-proxy route-minting path leaves it `undefined`,
|
|
920
|
+
* so internal completions record `apiKeyId: null` (the taps read
|
|
921
|
+
* `route.apiKeyId ?? null`), exactly as before.
|
|
922
|
+
*/
|
|
923
|
+
readonly apiKeyId?: string;
|
|
924
|
+
/** Explicit hosted-image authority projected from the verified `images` permission. */
|
|
925
|
+
readonly hostedImageGenerationAllowed?: boolean;
|
|
926
|
+
/**
|
|
927
|
+
* Per-request, one-way audit seam supplied by the outbound router. Hosted
|
|
928
|
+
* image admission invokes it before any mediated response bytes are relayed.
|
|
929
|
+
*/
|
|
930
|
+
readonly suppressAuditBodies?: () => void;
|
|
931
|
+
/** Safe process-local lease attribution. The route token is intentionally absent. */
|
|
932
|
+
readonly routeLease?: RouteLeaseUsageAttribution;
|
|
933
|
+
/** Wire format this route's ingress decodes. */
|
|
934
|
+
readonly ingressFormat: IngressFormat;
|
|
935
|
+
/** Re-auth mode (BYO key vs subscription OAuth). */
|
|
936
|
+
readonly authMode: RouteAuthMode;
|
|
937
|
+
/**
|
|
938
|
+
* LLM-config provider row id whose key/headers authenticate a BYO call.
|
|
939
|
+
* Required for `authMode === 'byo'`; ignored for subscription routes.
|
|
940
|
+
*/
|
|
941
|
+
readonly providerId?: string;
|
|
942
|
+
/**
|
|
943
|
+
* Background-task model (the SDK's haiku probes map to this). Optional —
|
|
944
|
+
* falls back to `model` when omitted. Anthropic ingress quirk only.
|
|
945
|
+
*/
|
|
946
|
+
readonly backgroundTaskModel?: string;
|
|
947
|
+
/**
|
|
948
|
+
* Pre-built `AuthSource` for this route, when the caller resolved it at run
|
|
949
|
+
* start (subscription routes supply this). When omitted for BYO routes the
|
|
950
|
+
* proxy builds an `LlmConfigProviderAuth` from `providerId` at request time.
|
|
951
|
+
*/
|
|
952
|
+
readonly auth?: AuthSource;
|
|
953
|
+
/**
|
|
954
|
+
* Subscription profile (structural `SubscriptionAuthProfile` subset — the
|
|
955
|
+
* registry's full `SubscriptionDispatchProfile` satisfies it). REQUIRED when
|
|
956
|
+
* `authMode === 'subscription'`. The route resolver populates it for BOTH the
|
|
957
|
+
* OpenAI-Responses ingress and the built-in (factory-absent) Anthropic
|
|
958
|
+
* `/v1/messages` ingress (RT2.1). The Responses ingress consumes only
|
|
959
|
+
* `authStrategy` / `resolveUpstreamUrl` / `providerTransformerNames`; the
|
|
960
|
+
* built-in messages subscription path additionally reads the OPTIONAL `mode`
|
|
961
|
+
* + `modelMapper` fields (present on the registry profile passed here). The
|
|
962
|
+
* factory-present Anthropic delegation carries its OWN profile inside
|
|
963
|
+
* `anthropicSdkHints.subscriptionProfile` and ignores this field.
|
|
964
|
+
*/
|
|
965
|
+
readonly subscriptionProfile?: SubscriptionAuthProfile | null;
|
|
966
|
+
/**
|
|
967
|
+
* Per-request preferred subscription account id (provider/subscription
|
|
968
|
+
* duality). Stamped by the outbound `resolveRoute` from
|
|
969
|
+
* `EndpointRoutingConfig.boundAccountId`; strict bindings fail when this
|
|
970
|
+
* account cannot serve. The pool is used only when the route carries the
|
|
971
|
+
* explicit `'pool'` fallback policy. Undefined ⇒ pool auto-schedule.
|
|
972
|
+
*/
|
|
973
|
+
readonly preferredAccountId?: string;
|
|
974
|
+
/** Account-group binding projected by the outbound gateway. */
|
|
975
|
+
readonly preferredAccountGroup?: string;
|
|
976
|
+
/** Bound-account behavior; `'pool'` is the explicit fallback opt-in. */
|
|
977
|
+
readonly boundAccountFallbackPolicy?: BoundAccountFallbackPolicy;
|
|
978
|
+
/** Optional provider key selected by a resource-level gateway binding. */
|
|
979
|
+
readonly preferredKeyId?: string;
|
|
980
|
+
/** Strict by default; `'pool'` permits normal provider key selection. */
|
|
981
|
+
readonly boundKeyFallbackPolicy?: BoundAccountFallbackPolicy;
|
|
982
|
+
/**
|
|
983
|
+
* OPAQUE per-account subscription config (opencodego-only). Populated by the
|
|
984
|
+
* route resolver from the subscription registry's `getOpenCodeGoConfig()`
|
|
985
|
+
* getter; passed BACK INTO the profile closures (`modelMapper` /
|
|
986
|
+
* `nextFallback` / `resolveUpstreamUrl`) by the built-in (factory-absent)
|
|
987
|
+
* `/v1/messages` plan builder so user `baseUrl` / `modelMap` / `fallbacks`
|
|
988
|
+
* overrides apply on that path.
|
|
989
|
+
*
|
|
990
|
+
* Typed `unknown` ON PURPOSE: core MUST NOT name the concrete
|
|
991
|
+
* `OpenCodeGoTokenConfig` type from `@omnicross/subscriptions` (cross-layer
|
|
992
|
+
* litmus = 0). The plan builder narrows it to the contract type
|
|
993
|
+
* (`@omnicross/contracts`) at the single profile-call boundary.
|
|
994
|
+
*
|
|
995
|
+
* INERT when an Anthropic ingress factory is injected (the built-in plan
|
|
996
|
+
* builder is then unreachable) and for non-opencodego routes (claude /
|
|
997
|
+
* codex / gemini leave it `undefined`).
|
|
998
|
+
*/
|
|
999
|
+
readonly subscriptionConfig?: unknown;
|
|
1000
|
+
/**
|
|
1001
|
+
* The Anthropic SDK-hint bundle. REQUIRED when
|
|
1002
|
+
* `ingressFormat === 'anthropic-messages'` (the resident proxy delegates that
|
|
1003
|
+
* ingress to the host's existing per-request handler, which needs the full bundle).
|
|
1004
|
+
* Ignored for the OpenAI Responses ingress.
|
|
1005
|
+
*/
|
|
1006
|
+
readonly anthropicSdkHints?: AnthropicSdkHints | null;
|
|
1007
|
+
/**
|
|
1008
|
+
* count_tokens strategy for `/v1/messages/count_tokens` requests
|
|
1009
|
+
* (claude-api-routing-errors, widened in claude-api-protocol-fidelity).
|
|
1010
|
+
* Absent ⇒ `'auto'`: Anthropic-wire upstream → passthrough, translation
|
|
1011
|
+
* upstream → estimate. Stamped onto the minted route by the outbound router
|
|
1012
|
+
* for count_tokens requests only; resident direct traffic stays `'auto'`.
|
|
1013
|
+
*/
|
|
1014
|
+
readonly anthropicCountTokensMode?: 'auto' | 'passthrough' | 'estimate' | 'reject';
|
|
1015
|
+
/**
|
|
1016
|
+
* Wall-clock budget (ms) for the local count_tokens estimate walk
|
|
1017
|
+
* (`anthropic.countTokens.estimateBudgetMs`, §10). Absent ⇒ the estimator's
|
|
1018
|
+
* 2000ms default.
|
|
1019
|
+
*/
|
|
1020
|
+
readonly anthropicCountTokensEstimateBudgetMs?: number;
|
|
1021
|
+
/**
|
|
1022
|
+
* Budget (ms) for the translate-path PDF text extraction
|
|
1023
|
+
* (`anthropic.pdfTextExtraction.budgetMs`, claude-api-transform-fidelity).
|
|
1024
|
+
* Absent ⇒ the extractor's 2000ms default. Applies to GENERATION translate
|
|
1025
|
+
* routes (documents in message content), stamped by the outbound router for
|
|
1026
|
+
* Anthropic-protocol requests; resident direct traffic uses the default.
|
|
1027
|
+
*/
|
|
1028
|
+
readonly anthropicPdfTextExtractionBudgetMs?: number;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* App-session-scoped dependencies the resident proxy needs to service ALL
|
|
1032
|
+
* routes. Unlike the per-run proxies these are wired ONCE at startup; per-run
|
|
1033
|
+
* state lives in the route map.
|
|
1034
|
+
*/
|
|
1035
|
+
interface ProviderProxyDeps {
|
|
1036
|
+
readonly llmConfig: ProviderConfigSource;
|
|
1037
|
+
/**
|
|
1038
|
+
* Trusted handlers for OpenAI resource operations not owned by the built-in
|
|
1039
|
+
* create ingresses. Optional so existing embedders stay source-compatible.
|
|
1040
|
+
*/
|
|
1041
|
+
readonly openAIOperationRegistry?: OpenAIOperationRegistry | null;
|
|
1042
|
+
/** Optional Native Responses hosted-image mediator composed by the daemon. */
|
|
1043
|
+
readonly responsesHostedImageIngress?: ResponsesHostedImageIngress | null;
|
|
1044
|
+
/**
|
|
1045
|
+
* Session-affine key selection + 429/529/401/403 failover. Centralized here
|
|
1046
|
+
* (task 2.8) so the next-batch cutover removes the per-proxy taps. Optional —
|
|
1047
|
+
* BYO single-key routes work without it.
|
|
1048
|
+
*/
|
|
1049
|
+
readonly apiKeyPool?: ApiKeyPoolService | null;
|
|
1050
|
+
/**
|
|
1051
|
+
* The single usage tap (task 2.8). When set, both ingress relays
|
|
1052
|
+
* record their non-stream usage through it. Optional.
|
|
1053
|
+
*/
|
|
1054
|
+
readonly usageRecorder?: UsageRecorderImport | null;
|
|
1055
|
+
/**
|
|
1056
|
+
* Factory for the per-request Anthropic `/v1/messages` ingress handler
|
|
1057
|
+
* (E1 de-inversion). The ingress builds its delegated request handler
|
|
1058
|
+
* through THIS injected factory instead of importing the host's factory
|
|
1059
|
+
* directly. Bootstrap supplies the host implementation.
|
|
1060
|
+
*
|
|
1061
|
+
* Optional so unit-test constructors that never drive the Anthropic ingress
|
|
1062
|
+
* (env-wiring smoke, pool failover, etc.) compile unchanged; when a route
|
|
1063
|
+
* with `ingressFormat: 'anthropic-messages'` IS served without it wired, the
|
|
1064
|
+
* ingress responds 502 (the factory is a hard dependency of THAT path only).
|
|
1065
|
+
*/
|
|
1066
|
+
readonly anthropicIngressHandlerFactory?: AnthropicIngressHandlerFactory | null;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Structural port for the usage recorder — only the `record` method.
|
|
1070
|
+
*
|
|
1071
|
+
* Kept structural so the serving core does not depend on the host's concrete
|
|
1072
|
+
* usage-recorder class. The host injects that concrete service at
|
|
1073
|
+
* bootstrap; it satisfies this port. Both the proxy taps (narrow literal-null
|
|
1074
|
+
* payloads) and the CompletionService / TransformerHandler completion path
|
|
1075
|
+
* (rich payloads with `messageId` / `apiKeyId` / `'completion'` origin) call
|
|
1076
|
+
* through this single `record()`, so the accepted input is the full structural
|
|
1077
|
+
* mirror of the host's `UsageRecordInput`.
|
|
1078
|
+
*/
|
|
1079
|
+
interface UsageRecorderImport {
|
|
1080
|
+
record(input: UsageRecordImportInput): void;
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* The usage payload accepted by the recorder port — structural mirror of the
|
|
1084
|
+
* host's `UsageRecordInput` (type-only; no host import). Covers both the proxy
|
|
1085
|
+
* taps and the completion path.
|
|
1086
|
+
*/
|
|
1087
|
+
interface UsageRecordImportInput {
|
|
1088
|
+
messageId?: string | null;
|
|
1089
|
+
parentMessageId?: string | null;
|
|
1090
|
+
sessionId?: string | null;
|
|
1091
|
+
providerId: string;
|
|
1092
|
+
model: string;
|
|
1093
|
+
apiKeyId?: string | null;
|
|
1094
|
+
engineOrigin: UsageEngineOrigin;
|
|
1095
|
+
usage: UsageTokens;
|
|
1096
|
+
rawUsage?: unknown;
|
|
1097
|
+
runId?: string | null;
|
|
1098
|
+
/** Token-free managed-route attribution. */
|
|
1099
|
+
routeLeaseId?: string | null;
|
|
1100
|
+
routeLeaseConsumer?: string | null;
|
|
1101
|
+
routeLeaseStageId?: string | null;
|
|
1102
|
+
eventId?: string | null;
|
|
1103
|
+
/** Safe prompt-cache-key provenance; raw key material is never recorded. */
|
|
1104
|
+
cacheKeySource?: UsageCacheKeySource;
|
|
1105
|
+
/** Whether the gateway, rather than the client, attached the cache key. */
|
|
1106
|
+
cacheKeyInjected?: boolean;
|
|
1107
|
+
/**
|
|
1108
|
+
* OPTIONAL per-request audit correlation key (request-audit-log) — the outbound
|
|
1109
|
+
* relay taps set this to the request's `http.ServerResponse` so the recorder can
|
|
1110
|
+
* stash this request's tokens/cost for the audit capture. Opaque; unset ⇒ no-op.
|
|
1111
|
+
*/
|
|
1112
|
+
auditResponse?: object;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
export { ResponsesAffinityStore as $, type AnthropicIngressHandler as A, InMemoryResponsesImageStateStore as B, type InMemoryResponsesImageStateStoreOptions as C, type IngressFormat as D, type ExtendedContextHint as E, type OpenAIOperationBodyKind as F, type OpenAIOperationDispatchContext as G, OpenAIOperationError as H, type ImageAsset as I, type OpenAIOperationErrorInit as J, type OpenAIOperationHandler as K, type OpenAIOperationHandlerContext as L, type OpenAIOperationId as M, type OpenAIOperationOwner as N, type OpenAIOperation as O, OpenAIOperationRegistrationError as P, type OpenAIOperationRegistrationErrorCode as Q, OpenAIOperationRegistry as R, type OpenAIPolicyFamily as S, type OpenAIRequestedModelSource as T, type UsageRecorderImport as U, type OpenAIRouteFamily as V, type ProviderProxyDeps as W, type ProxyAttribution as X, type ResponsesAffinityEntry as Y, type ResponsesAffinityRecord as Z, type ResponsesAffinityScope as _, type AnthropicIngressHandlerFactory as a, type ResponsesAffinityStoreOptions as a0, type ResponsesCredentialIdentity as a1, type ResponsesHostedImageIngress as a2, type ResponsesHostedImageRequestLease as a3, type ResponsesHostedImageRuntimeFactory as a4, type ResponsesHostedImageRuntimeLease as a5, type ResponsesHostedToolIdentity as a6, type ResponsesHostedToolSelection as a7, type ResponsesImageAction as a8, type ResponsesImageAdmission as a9, type ResponsesSelectedImageCall as aA, type RetryCallback as aB, type RouteAuthMode as aC, type RouteContext as aD, type RouteLeaseUsageAttribution as aE, type StreamEventCallback as aF, type SubscriptionDispatchProfile as aG, type SubscriptionRequestSummary as aH, type TargetProviderFormat as aI, classifyOpenAIOperation as aJ, classifyResponsesProfile as aK, emitImageTelemetry as aL, getOpenAIOperation as aM, getResponsesAffinityStore as aN, previousResponseNotFound as aO, readImageAssetBytes as aP, unsupportedOpenAIOperation as aQ, writeOpenAIOperationError as aR, type UsageRecordImportInput as aS, type ResponsesImageCallBinding as aa, type ResponsesImageCallId as ab, type ResponsesImageCallResolution as ac, type ResponsesImageCallStateLease as ad, type ResponsesImageCompletedRecord as ae, type ResponsesImageEventAllocator as af, type ResponsesImageExecutionEvent as ag, type ResponsesImageFailedRecord as ah, type ResponsesImageGenerationCallItem as ai, type ResponsesImageGenerationCallStartedItem as aj, type ResponsesImageGenerationContribution as ak, type ResponsesImageGenerationContributionDeps as al, type ResponsesImageInspectionInput as am, type ResponsesImageNormalizedOptions as an, type ResponsesImagePartialEvent as ao, type ResponsesImageRequestScope as ap, type ResponsesImageRequestScopeInput as aq, type ResponsesImageResponseResolution as ar, type ResponsesImageResponseStateLease as as, type ResponsesImageSelectionPolicy as at, type ResponsesImageStartedRecord as au, type ResponsesImageStateCommitInput as av, type ResponsesImageStateStore as aw, type ResponsesImageTrustedRuntime as ax, type ResponsesProfile as ay, type ResponsesProfileDeclaration as az, type AnthropicRouteHandlerParams as b, type AnthropicSdkHints as c, type ExtensionOpenAIOperationId as d, type ImageJob as e, type ImageJobObservability as f, type ImageJobObservabilitySnapshot as g, ImageOrchestrator as h, type ImageOrchestratorOptions as i, type ImageOrchestratorRunOptions as j, type ImageProvider as k, type ImageProviderContext as l, type ImageProviderLease as m, ImageProviderRegistry as n, type ImageProviderRequest as o, type ImageReferenceLease as p, type ImageReferenceResolution as q, type ImageReferenceSaveInput as r, type ImageReferenceStore as s, type ImageReferenceValue as t, type ImageRetentionPolicy as u, type ImageTelemetryOutputMetadata as v, type ImageTelemetryRecord as w, type ImageTelemetrySink as x, InMemoryImageAsset as y, InMemoryImageReferenceStore as z };
|