@jeffusion/bungee-core 5.23.1 → 5.23.3
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/dist/config-storage-worker.js +927 -393
- package/dist/main.js +2523 -619
- package/dist/plugin-state-worker.js +178 -16
- package/dist/plugins/codex-router/control.js +1 -1
- package/dist/plugins/codex-router/control.js.map +3 -3
- package/dist/plugins/codex-router/index.js +2289 -3
- package/dist/plugins/codex-router/index.js.map +17 -6
- package/dist/plugins/llm-protocol-adapter/control.js +93 -19
- package/dist/plugins/llm-protocol-adapter/control.js.map +7 -6
- package/dist/plugins/llm-protocol-adapter/index.js +131 -36
- package/dist/plugins/llm-protocol-adapter/index.js.map +10 -9
- package/dist/plugins/model-mapping/control.js +1 -1
- package/dist/plugins/model-mapping/control.js.map +3 -3
- package/dist/plugins/model-mapping/index.js +48 -17
- package/dist/plugins/model-mapping/index.js.map +6 -5
- package/dist/plugins/model-mapping/manifest.json +50 -6
- package/dist/plugins/models-dev/control.js +1 -1
- package/dist/plugins/models-dev/control.js.map +3 -3
- package/dist/plugins/models-dev/index.js +1 -1
- package/dist/plugins/models-dev/index.js.map +3 -3
- package/dist/plugins/token-stats/control.js +1 -1
- package/dist/plugins/token-stats/control.js.map +3 -3
- package/dist/plugins/token-stats/index.js +1 -1
- package/dist/plugins/token-stats/index.js.map +3 -3
- package/package.json +2 -2
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../plugins/models-dev/contract.ts", "../../../../../plugins/model-mapping/server/catalog.ts", "../../../../../plugins/model-mapping/server/control.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Public contract of the models-dev catalog provider.\n *\n * This is the ONLY file other plugins may import from models-dev. It contains the\n * declared service identity, the wire-contract snapshot literal and the data types\n * of the read surface; it never exposes the downloader, the private storage keys or\n * the internal catalog representation.\n *\n * Consumers must declare a real dependency on `models-dev` and consume the local\n * service for their own process. The service methods are synchronous and read an\n * already-loaded in-memory view: no per-request network or SQL is performed.\n */\n\n/** Provider plugin name. Must match the manifest. */\nexport const MODELS_DEV_PLUGIN_NAME = 'models-dev';\n\n/** The single upstream source; models-dev is the only component allowed to fetch it. */\nexport const MODELS_DEV_SOURCE_URL = 'https://models.dev/api.json';\n\n/** Same-process local read service, published in both the control and worker processes. */\nexport const MODELS_DEV_CATALOG_SERVICE_ID = 'models-dev.catalog.v1';\nexport const MODELS_DEV_CATALOG_CONTRACT_VERSION = 1;\n\n/** Versioned immutable snapshot of the full catalog, published by the control writer. */\nexport const MODELS_DEV_CATALOG_SNAPSHOT_ID = 'models-dev.catalog.snapshot.v1';\nexport const MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT_VERSION = 1;\n/**\n * One atomic record keeps fetchedAt and the immutable catalog with its version.\n * The catalog remains unrestricted JSON so every upstream field is preserved.\n */\nexport const MODELS_DEV_CATALOG_SNAPSHOT_SCHEMA = Object.freeze({\n type: 'object', properties: {\n version: { type: 'number', integer: true, minimum: 1 },\n fetchedAt: { type: 'number', minimum: 0 },\n catalog: { type: 'json', maxBytes: 32 * 1024 * 1024 },\n },\n} as const);\nexport const MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT = Object.freeze({\n id: MODELS_DEV_CATALOG_SNAPSHOT_ID,\n version: MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT_VERSION,\n content: MODELS_DEV_CATALOG_SNAPSHOT_SCHEMA,\n});\n\n/** Catalog availability is separate from whether the service is published. */\nexport type ModelsDevCatalogState = 'empty' | 'ready' | 'stale' | 'failed';\n\nexport interface ModelsDevCatalogStatus {\n readonly state: ModelsDevCatalogState;\n /** Monotonic published data version; `null` before the first successful load. */\n readonly version: number | null;\n readonly fetchedAt: number | null;\n readonly providerCount: number;\n readonly modelCount: number;\n /** Last failure reason; `null` after a fully successful load. */\n readonly error: string | null;\n}\n\nexport interface ModelsDevProviderSummary {\n readonly provider: string;\n readonly name: string;\n /** Normalized upstream API base (`provider.api`), or `null` when models.dev declares none. */\n readonly api: string | null;\n readonly modelCount: number;\n}\n\n/** One selectable catalog model. `provider` is the pricing provider, never the protocol. */\nexport interface ModelsDevModelOption {\n readonly provider: string;\n readonly providerName: string;\n readonly model: string;\n readonly name: string;\n}\n\nexport interface ModelsDevModelPage {\n readonly models: readonly ModelsDevModelOption[];\n readonly total: number;\n /** 1-based page actually returned. */\n readonly page: number;\n readonly pageSize: number;\n}\n\n/** USD per million tokens, applied to the whole request at this input threshold. */\nexport interface ModelsDevContextTier {\n readonly minimumInputTokens: number;\n readonly input: number;\n readonly output: number;\n readonly cacheRead: number | null;\n readonly cacheWrite: number | null;\n}\n\n/** A resolved catalog entry with optional ascending context price bands. */\nexport interface ModelsDevModelMatch {\n readonly provider: string;\n readonly model: string;\n readonly input: number;\n readonly output: number;\n readonly cacheRead: number | null;\n readonly cacheWrite: number | null;\n readonly tiered: boolean;\n readonly contextTiers?: readonly ModelsDevContextTier[];\n}\n\nexport interface ModelsDevProviderMatch {\n readonly provider: string;\n}\n\n/**\n * The declared local read surface. Implementations must be side-effect free and\n * must never throw for a miss/corruption of the current view: an unavailable\n * catalog returns an `empty`/`failed` status instead of a fabricated price.\n */\nexport interface ModelsDevCatalogService {\n status(): ModelsDevCatalogStatus;\n providers(): readonly ModelsDevProviderSummary[];\n modelOptions(input?: { readonly provider?: string; readonly search?: string; readonly page?: number; readonly pageSize?: number }): ModelsDevModelPage;\n /**\n * Resolve exactly one catalog entry for a client model name.\n *\n * `url` (when supplied) is canonicalized to host + path and matched against the\n * full catalog's `provider.api`; more than one candidate is ambiguous and returns\n * null. `pricingProvider` is a catalog provider id and takes priority over URL and\n * prefix inference. A model id present under several providers without an explicit\n * provider is ambiguous. Matching defaults to exact and case-sensitive.\n * `estimate` additionally permits normalized names, original-lab prices and\n * dated members of the same family. Explicit provider IDs remain binding;\n * an unresolved URL is only a hint in estimate mode.\n */\n resolveModel(input: { readonly model: string; readonly pricingProvider?: string; readonly url?: string; readonly mode?: 'exact' | 'estimate' }): ModelsDevModelMatch | null;\n /** Resolve one provider from a real upstream URL via `provider.api`; ambiguous/none => null. */\n resolveProvider(input: { readonly url: string }): ModelsDevProviderMatch | null;\n}\n\n/** Capability reads are additive; existing catalog.v1 consumers stay unchanged. */\nexport const MODELS_DEV_CAPABILITIES_SERVICE_ID = 'models-dev.capabilities.v1';\nexport const MODELS_DEV_CAPABILITIES_CONTRACT_VERSION = 1;\n/** Upstream control values; null/default do not name a concrete effort level. */\nexport type ModelsDevReasoningEffortValue = null | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'default';\n/** Validated models.dev reasoning_options, without inferred controls or levels. */\nexport type ModelsDevReasoningOption =\n | { readonly type: 'effort'; readonly values: readonly ModelsDevReasoningEffortValue[] }\n | { readonly type: 'toggle' }\n | { readonly type: 'budget_tokens'; readonly min?: number; readonly max?: number };\nexport type ModelsDevReasoningOptionsStatus = 'known' | 'missing' | 'invalid';\nexport interface ModelsDevCapabilities {\n readonly provider: string;\n readonly model: string;\n readonly name: string;\n readonly contextWindow: number | null;\n readonly outputLimit: number | null;\n readonly toolCall: boolean;\n readonly reasoning: boolean;\n /** null for missing/invalid metadata; a validated empty list remains known. */\n readonly reasoningOptions: readonly ModelsDevReasoningOption[] | null;\n readonly reasoningOptionsStatus: ModelsDevReasoningOptionsStatus;\n /** Version of the same complete snapshot that supplied all fields of this result. */\n readonly catalogVersion: number;\n readonly inputModalities: readonly string[];\n}\nexport interface ModelsDevCapabilitiesService {\n status(): ModelsDevCatalogStatus;\n /** Without a provider, require a unique exact model or a declared API URL match. */\n model(input: { readonly provider?: string; readonly model: string; readonly url?: string }): ModelsDevCapabilities | null;\n}\n",
|
|
5
|
+
"/**\n * Public contract of the models-dev catalog provider.\n *\n * This is the ONLY file other plugins may import from models-dev. It contains the\n * declared service identity, the wire-contract snapshot literal and the data types\n * of the read surface; it never exposes the downloader, the private storage keys or\n * the internal catalog representation.\n *\n * Consumers must declare a real dependency on `models-dev` and consume the local\n * service for their own process. The service methods are synchronous and read an\n * already-loaded in-memory view: no per-request network or SQL is performed.\n */\n\n/** Provider plugin name. Must match the manifest. */\nexport const MODELS_DEV_PLUGIN_NAME = 'models-dev';\n\n/** Explicit catalog identity, independent from the provider's wire model name. */\nexport interface CatalogModelReference {\n readonly provider: string;\n readonly model: string;\n}\nexport interface ModelIdentityDeclaration {\n readonly wireModel: string;\n readonly catalogModel: CatalogModelReference;\n}\nexport const MODEL_IDENTITY_ANNOTATION_KEY = 'models-dev.model-identity';\n\n/** The single upstream source; models-dev is the only component allowed to fetch it. */\nexport const MODELS_DEV_SOURCE_URL = 'https://models.dev/api.json';\n\n/** Same-process local read service, published in both the control and worker processes. */\nexport const MODELS_DEV_CATALOG_SERVICE_ID = 'models-dev.catalog.v1';\nexport const MODELS_DEV_CATALOG_CONTRACT_VERSION = 1;\n\n/** Versioned immutable snapshot of the full catalog, published by the control writer. */\nexport const MODELS_DEV_CATALOG_SNAPSHOT_ID = 'models-dev.catalog.snapshot.v1';\nexport const MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT_VERSION = 1;\n/**\n * One atomic record keeps fetchedAt and the immutable catalog with its version.\n * The catalog remains unrestricted JSON so every upstream field is preserved.\n */\nexport const MODELS_DEV_CATALOG_SNAPSHOT_SCHEMA = Object.freeze({\n type: 'object', properties: {\n version: { type: 'number', integer: true, minimum: 1 },\n fetchedAt: { type: 'number', minimum: 0 },\n catalog: { type: 'json', maxBytes: 32 * 1024 * 1024 },\n },\n} as const);\nexport const MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT = Object.freeze({\n id: MODELS_DEV_CATALOG_SNAPSHOT_ID,\n version: MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT_VERSION,\n content: MODELS_DEV_CATALOG_SNAPSHOT_SCHEMA,\n});\n\n/** Catalog availability is separate from whether the service is published. */\nexport type ModelsDevCatalogState = 'empty' | 'ready' | 'stale' | 'failed';\n\nexport interface ModelsDevCatalogStatus {\n readonly state: ModelsDevCatalogState;\n /** Monotonic published data version; `null` before the first successful load. */\n readonly version: number | null;\n readonly fetchedAt: number | null;\n readonly providerCount: number;\n readonly modelCount: number;\n /** Last failure reason; `null` after a fully successful load. */\n readonly error: string | null;\n}\n\nexport interface ModelsDevProviderSummary {\n readonly provider: string;\n readonly name: string;\n /** Normalized upstream API base (`provider.api`), or `null` when models.dev declares none. */\n readonly api: string | null;\n readonly modelCount: number;\n}\n\n/** One selectable catalog model. `provider` is the pricing provider, never the protocol. */\nexport interface ModelsDevModelOption {\n readonly provider: string;\n readonly providerName: string;\n readonly model: string;\n readonly name: string;\n}\n\nexport interface ModelsDevModelPage {\n readonly models: readonly ModelsDevModelOption[];\n readonly total: number;\n /** 1-based page actually returned. */\n readonly page: number;\n readonly pageSize: number;\n}\n\n/** USD per million tokens, applied to the whole request at this input threshold. */\nexport interface ModelsDevContextTier {\n readonly minimumInputTokens: number;\n readonly input: number;\n readonly output: number;\n readonly cacheRead: number | null;\n readonly cacheWrite: number | null;\n}\n\n/** A resolved catalog entry with optional ascending context price bands. */\nexport interface ModelsDevModelMatch {\n readonly provider: string;\n readonly model: string;\n readonly input: number;\n readonly output: number;\n readonly cacheRead: number | null;\n readonly cacheWrite: number | null;\n readonly tiered: boolean;\n readonly contextTiers?: readonly ModelsDevContextTier[];\n}\n\nexport interface ModelsDevProviderMatch {\n readonly provider: string;\n}\n\n/**\n * The declared local read surface. Implementations must be side-effect free and\n * must never throw for a miss/corruption of the current view: an unavailable\n * catalog returns an `empty`/`failed` status instead of a fabricated price.\n */\nexport interface ModelsDevCatalogService {\n status(): ModelsDevCatalogStatus;\n providers(): readonly ModelsDevProviderSummary[];\n modelOptions(input?: { readonly provider?: string; readonly search?: string; readonly page?: number; readonly pageSize?: number }): ModelsDevModelPage;\n /**\n * Resolve exactly one catalog entry for a client model name.\n *\n * `url` (when supplied) is canonicalized to host + path and matched against the\n * full catalog's `provider.api`; more than one candidate is ambiguous and returns\n * null. `pricingProvider` is a catalog provider id and takes priority over URL and\n * prefix inference. A model id present under several providers without an explicit\n * provider is ambiguous. Matching defaults to exact and case-sensitive.\n * `estimate` additionally permits normalized names, original-lab prices and\n * dated members of the same family. Explicit provider IDs remain binding;\n * an unresolved URL is only a hint in estimate mode.\n */\n resolveModel(input: { readonly model: string; readonly pricingProvider?: string; readonly url?: string; readonly mode?: 'exact' | 'estimate' }): ModelsDevModelMatch | null;\n /** Resolve one provider from a real upstream URL via `provider.api`; ambiguous/none => null. */\n resolveProvider(input: { readonly url: string }): ModelsDevProviderMatch | null;\n}\n\n/** Capability reads are additive; existing catalog.v1 consumers stay unchanged. */\nexport const MODELS_DEV_CAPABILITIES_SERVICE_ID = 'models-dev.capabilities.v1';\nexport const MODELS_DEV_CAPABILITIES_CONTRACT_VERSION = 1;\n/** Upstream control values; null/default do not name a concrete effort level. */\nexport type ModelsDevReasoningEffortValue = null | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'default';\n/** Validated models.dev reasoning_options, without inferred controls or levels. */\nexport type ModelsDevReasoningOption =\n | { readonly type: 'effort'; readonly values: readonly ModelsDevReasoningEffortValue[] }\n | { readonly type: 'toggle' }\n | { readonly type: 'budget_tokens'; readonly min?: number; readonly max?: number };\nexport type ModelsDevReasoningOptionsStatus = 'known' | 'missing' | 'invalid';\nexport interface ModelsDevCapabilities {\n readonly provider: string;\n readonly model: string;\n readonly name: string;\n readonly contextWindow: number | null;\n readonly outputLimit: number | null;\n readonly toolCall: boolean;\n readonly reasoning: boolean;\n /** null for missing/invalid metadata; a validated empty list remains known. */\n readonly reasoningOptions: readonly ModelsDevReasoningOption[] | null;\n readonly reasoningOptionsStatus: ModelsDevReasoningOptionsStatus;\n /** Version of the same complete snapshot that supplied all fields of this result. */\n readonly catalogVersion: number;\n readonly inputModalities: readonly string[];\n}\nexport interface ModelsDevCapabilitiesService {\n status(): ModelsDevCatalogStatus;\n /** Without a provider, require a unique exact model or a declared API URL match. */\n model(input: { readonly provider?: string; readonly model: string; readonly url?: string }): ModelsDevCapabilities | null;\n}\n",
|
|
6
6
|
"/**\n * model-mapping catalog adapter.\n *\n * model-mapping no longer downloads or caches a catalog. It reads the models-dev\n * public service (control or worker process) and reshapes the result for its own\n * mapping UI. There is no second refresh entry and no offline catalogue fallback.\n */\n\nimport type { ModelsDevCatalogService } from '../../models-dev/contract';\n\nexport type ModelOption = { value: string; label: string; description: string; provider?: string };\nexport type ModelCatalogSource = 'catalog';\nexport type ModelCatalogStatus = {\n source: ModelCatalogSource;\n fetchedAt: number | null;\n modelCount: number;\n providerCount: number;\n models: ModelOption[];\n providers: string[];\n matchedCount: number;\n page: number;\n pageSize: number;\n};\n\nexport const MODEL_CATALOG_PAGE_SIZE = 50;\nconst MAX_CATALOG_QUERY_BYTES = 512;\n\nconst encoder = new TextEncoder();\n\nexport function catalogQueryIsValid(options: { provider?: string; search?: string; page?: number }): boolean {\n const page = options.page ?? 1;\n return Number.isSafeInteger(page) && page >= 1\n && (options.provider === undefined || options.provider.length <= MAX_CATALOG_QUERY_BYTES)\n && (options.search === undefined || options.search.length <= MAX_CATALOG_QUERY_BYTES);\n}\n\n/** Reshape the models-dev read surface into the catalog status the mapping UI consumes. */\nexport function buildModelCatalogStatus(\n service: ModelsDevCatalogService,\n options: { provider?: string; search?: string; page?: number } = {},\n): ModelCatalogStatus {\n const page = options.page ?? 1;\n const result = service.modelOptions({\n ...(options.provider === undefined ? {} : { provider: options.provider }),\n ...(options.search === undefined ? {} : { search: options.search }),\n page,\n pageSize: MODEL_CATALOG_PAGE_SIZE,\n });\n const status = service.status();\n const providers = service.providers().map(provider => provider.provider);\n return {\n source: 'catalog',\n fetchedAt: status.fetchedAt,\n modelCount: status.modelCount,\n providerCount: status.providerCount,\n providers,\n matchedCount: result.total,\n page: result.page,\n pageSize: result.pageSize,\n models: result.models.map(model => ({\n value: model.model,\n label: model.name,\n description: model.providerName,\n provider: model.provider,\n })),\n };\n}\n\nexport { encoder as modelCatalogEncoder };\n",
|
|
7
7
|
"import type {\n ControlApiDeclaration,\n ControlApiHandlerContext,\n ControlHostContext,\n ControlPlugin,\n PluginControl,\n} from '@jeffusion/bungee-core/plugin';\nimport { MODELS_DEV_CATALOG_CONTRACT_VERSION, MODELS_DEV_CATALOG_SERVICE_ID, type ModelsDevCatalogService } from '../../models-dev/contract';\nimport { buildModelCatalogStatus, catalogQueryIsValid, type ModelCatalogStatus } from './catalog';\n\nconst API_ROUTES = Object.freeze([\n { path: '/catalog', methods: ['GET'], handler: 'getCatalog' },\n] as const);\nconst MAX_RESPONSE_BYTES = 256 * 1024;\nconst MAX_CATALOG_PAGE = 400;\n\nfunction catalogQuery(request: Request): { provider?: string; search?: string; page: number } | null {\n const params = new URL(request.url).searchParams;\n for (const key of ['provider', 'search', 'page']) {\n if (params.getAll(key).length > 1) return null;\n }\n const provider = params.get('provider') ?? undefined;\n const search = params.get('search') ?? undefined;\n const rawPage = params.get('page');\n const page = rawPage === null ? 1 : Number(rawPage);\n const query = { provider, search, page };\n if (page > MAX_CATALOG_PAGE || !catalogQueryIsValid(query)) return null;\n return query;\n}\n\nfunction jsonResponse(value: unknown, status = 200): Response {\n const body = JSON.stringify(value);\n if (new TextEncoder().encode(body).byteLength > MAX_RESPONSE_BYTES) {\n return new Response(JSON.stringify({ error: 'response_limit' }), {\n status: 500,\n headers: { 'content-type': 'application/json; charset=utf-8' },\n });\n }\n return new Response(body, { status, headers: { 'content-type': 'application/json; charset=utf-8' } });\n}\n\nclass ModelMappingControl implements PluginControl {\n readonly api: readonly ControlApiDeclaration[];\n readonly rpc = [] as const;\n private disposed = false;\n private readonly abortListener: () => void;\n\n constructor(private readonly host: ControlHostContext) {\n this.abortListener = () => { void this.dispose(); };\n if (host.signal.aborted) this.disposed = true;\n else host.signal.addEventListener('abort', this.abortListener, { once: true });\n const invoke = (handler: (context: ControlApiHandlerContext) => Promise<Response> | Response) => async (context: ControlApiHandlerContext) => {\n try {\n if (this.disposed || this.host.signal.aborted) return jsonResponse({ error: 'inactive' }, 503);\n return await handler(context);\n } catch {\n return jsonResponse({ error: 'catalog_unavailable' }, 502);\n }\n };\n this.api = [\n { ...API_ROUTES[0], invoke: invoke((context) => {\n const query = catalogQuery(context.request);\n if (!query) return jsonResponse({ error: 'invalid_query' }, 400);\n const services = this.host.services;\n if (services === undefined) return jsonResponse({ error: 'catalog_unavailable' }, 503);\n let service: ModelsDevCatalogService;\n try {\n service = services.consume<ModelsDevCatalogService>(\n 'models-dev', MODELS_DEV_CATALOG_SERVICE_ID, MODELS_DEV_CATALOG_CONTRACT_VERSION,\n );\n } catch { return jsonResponse({ error: 'catalog_unavailable' }, 503); }\n return jsonResponse(buildModelCatalogStatus(service, query) satisfies ModelCatalogStatus);\n }) },\n ];\n }\n\n start(): void {\n if (this.host.signal.aborted) throw new Error('inactive');\n }\n\n async dispose(): Promise<void> {\n if (!this.disposed) {\n this.disposed = true;\n this.host.signal.removeEventListener('abort', this.abortListener);\n }\n }\n}\n\nexport function createControl(context: ControlHostContext): PluginControl {\n return new ModelMappingControl(context);\n}\n\nexport default { createControl } satisfies ControlPlugin;\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": ";;
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "E8ED9478AFC2956164756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -33,6 +33,29 @@ function definePlugin(plugin) {
|
|
|
33
33
|
}
|
|
34
34
|
// packages/core/src/plugin-extensions.ts
|
|
35
35
|
var ANONYMOUS_PRINCIPAL = Object.freeze({ domain: "anonymous", keyId: "", credentialVersion: 0 });
|
|
36
|
+
// packages/core/src/data-admission/errors.ts
|
|
37
|
+
function safeDetails(details) {
|
|
38
|
+
if (!details)
|
|
39
|
+
return;
|
|
40
|
+
const message = typeof details.message === "string" && details.message.length <= 512 && !/[\x00-\x1f\x7f]/.test(details.message) ? details.message : undefined;
|
|
41
|
+
const param = typeof details.param === "string" && details.param.length <= 256 && /^[a-zA-Z_$][\w.$\[\]-]*$/.test(details.param) ? details.param : undefined;
|
|
42
|
+
return message === undefined && param === undefined ? undefined : Object.freeze({ message, param });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class DataAdmissionError extends Error {
|
|
46
|
+
status;
|
|
47
|
+
code;
|
|
48
|
+
retryAfter;
|
|
49
|
+
name = "DataAdmissionError";
|
|
50
|
+
details;
|
|
51
|
+
constructor(status, code, retryAfter, details) {
|
|
52
|
+
super(code);
|
|
53
|
+
this.status = status;
|
|
54
|
+
this.code = code;
|
|
55
|
+
this.retryAfter = retryAfter;
|
|
56
|
+
this.details = safeDetails(details);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
36
59
|
// packages/core/src/plugin-durable-state.ts
|
|
37
60
|
var MAX_BYTES = 1024 * 1024;
|
|
38
61
|
// packages/core/src/plugin-services/host-rpc.ts
|
|
@@ -133,6 +156,7 @@ var retryActionBrand = Symbol.for("@jeffusion/bungee/request-retry-action");
|
|
|
133
156
|
var HOUR = 3600000;
|
|
134
157
|
var TOKEN_STATS_RETENTION_MS = 31 * 24 * HOUR;
|
|
135
158
|
// plugins/models-dev/contract.ts
|
|
159
|
+
var MODEL_IDENTITY_ANNOTATION_KEY = "models-dev.model-identity";
|
|
136
160
|
var MODELS_DEV_CATALOG_SERVICE_ID = "models-dev.catalog.v1";
|
|
137
161
|
var MODELS_DEV_CATALOG_CONTRACT_VERSION = 1;
|
|
138
162
|
var MODELS_DEV_CATALOG_SNAPSHOT_ID = "models-dev.catalog.snapshot.v1";
|
|
@@ -193,7 +217,7 @@ class ModelMappingPluginImpl {
|
|
|
193
217
|
const source = typeof item?.source === "string" ? item.source.trim() : "";
|
|
194
218
|
const target = typeof item?.target === "string" ? item.target.trim() : "";
|
|
195
219
|
if (source && target)
|
|
196
|
-
map.set(source, target);
|
|
220
|
+
map.set(source, { source, target, ...item.catalogModel ? { catalogModel: structuredClone(item.catalogModel) } : {} });
|
|
197
221
|
}
|
|
198
222
|
return map;
|
|
199
223
|
}
|
|
@@ -201,7 +225,7 @@ class ModelMappingPluginImpl {
|
|
|
201
225
|
const sourceKey = source.trim();
|
|
202
226
|
const targetValue = typeof target === "string" ? target.trim() : "";
|
|
203
227
|
if (sourceKey && targetValue)
|
|
204
|
-
map.set(sourceKey, targetValue);
|
|
228
|
+
map.set(sourceKey, { source: sourceKey, target: targetValue });
|
|
205
229
|
}
|
|
206
230
|
return map;
|
|
207
231
|
}
|
|
@@ -212,17 +236,23 @@ class ModelMappingPluginImpl {
|
|
|
212
236
|
if (!modelInfo)
|
|
213
237
|
return;
|
|
214
238
|
const { model: currentModel, source } = modelInfo;
|
|
215
|
-
const
|
|
216
|
-
if (!
|
|
217
|
-
return;
|
|
218
|
-
const normalizedMappedModel = this.normalizeMappedTargetModel(mappedModel);
|
|
219
|
-
if (!normalizedMappedModel || normalizedMappedModel === currentModel)
|
|
239
|
+
const rule = this.resolveMappedModel(currentModel);
|
|
240
|
+
if (!rule)
|
|
220
241
|
return;
|
|
242
|
+
const normalizedMappedModel = this.normalizeMappedTargetModel(rule.target);
|
|
221
243
|
if (source === "body" && ctx.body && typeof ctx.body === "object") {
|
|
222
244
|
ctx.body.model = normalizedMappedModel;
|
|
223
245
|
} else if (source === "url") {
|
|
224
|
-
this.updateModelInUrlPath(ctx.url,
|
|
246
|
+
this.updateModelInUrlPath(ctx.url, normalizedMappedModel);
|
|
225
247
|
}
|
|
248
|
+
if (rule.catalogModel) {
|
|
249
|
+
ctx.annotations ??= {};
|
|
250
|
+
ctx.annotations[MODEL_IDENTITY_ANNOTATION_KEY] = {
|
|
251
|
+
wireModel: normalizedMappedModel,
|
|
252
|
+
catalogModel: { provider: rule.catalogModel.provider, model: rule.catalogModel.model }
|
|
253
|
+
};
|
|
254
|
+
} else if (ctx.annotations)
|
|
255
|
+
delete ctx.annotations[MODEL_IDENTITY_ANNOTATION_KEY];
|
|
226
256
|
logger.debug({ fromModel: currentModel, toModel: normalizedMappedModel, source }, "Model mapping applied");
|
|
227
257
|
}
|
|
228
258
|
extractModelFromContext(ctx) {
|
|
@@ -237,19 +267,17 @@ class ModelMappingPluginImpl {
|
|
|
237
267
|
return null;
|
|
238
268
|
}
|
|
239
269
|
extractModelFromUrlPath(pathname) {
|
|
240
|
-
const match = pathname.match(
|
|
270
|
+
const match = pathname.match(/\/models\/([^/]+)(?::|\/)(?:generateContent|streamGenerateContent)$/);
|
|
241
271
|
if (!match)
|
|
242
272
|
return null;
|
|
243
273
|
try {
|
|
244
274
|
return decodeURIComponent(match[1]);
|
|
245
275
|
} catch {
|
|
246
|
-
|
|
276
|
+
throw new DataAdmissionError(422, "model_mapping_invalid_model_url");
|
|
247
277
|
}
|
|
248
278
|
}
|
|
249
|
-
updateModelInUrlPath(url,
|
|
250
|
-
|
|
251
|
-
const encodedOldModel = encodeURIComponent(oldModel);
|
|
252
|
-
url.pathname = url.pathname.includes(encodedOldModel) ? url.pathname.replace(encodedOldModel, encodedNewModel) : url.pathname.replace(oldModel, encodedNewModel);
|
|
279
|
+
updateModelInUrlPath(url, newModel) {
|
|
280
|
+
url.pathname = url.pathname.replace(/(\/models\/)[^/]+((?::|\/)(?:generateContent|streamGenerateContent))$/, `$1${encodeURIComponent(newModel)}$2`);
|
|
253
281
|
}
|
|
254
282
|
resolveMappedModel(currentModel) {
|
|
255
283
|
const exactMappedModel = this.modelMappingMap.get(currentModel);
|
|
@@ -277,11 +305,14 @@ class ModelMappingPluginImpl {
|
|
|
277
305
|
continue;
|
|
278
306
|
if (candidate === undefined)
|
|
279
307
|
candidate = target;
|
|
280
|
-
else if (candidate !== target)
|
|
281
|
-
|
|
308
|
+
else if (this.ruleIdentity(candidate) !== this.ruleIdentity(target))
|
|
309
|
+
throw new DataAdmissionError(422, "model_mapping_ambiguous");
|
|
282
310
|
}
|
|
283
311
|
return candidate;
|
|
284
312
|
}
|
|
313
|
+
ruleIdentity(rule) {
|
|
314
|
+
return JSON.stringify([this.normalizeMappedTargetModel(rule.target), rule.catalogModel?.provider ?? null, rule.catalogModel?.model ?? null]);
|
|
315
|
+
}
|
|
285
316
|
stripModelRevisionSuffix(model) {
|
|
286
317
|
const matched = model.trim().match(/^(.*)-\d{8}$/);
|
|
287
318
|
return matched?.[1] || model.trim();
|
|
@@ -321,4 +352,4 @@ export {
|
|
|
321
352
|
server_default as default
|
|
322
353
|
};
|
|
323
354
|
|
|
324
|
-
//# debugId=
|
|
355
|
+
//# debugId=5AE5CB759517140064756E2164756E21
|