@x12i/ai-dispatcher 2.0.0 → 2.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/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _x12i_openrouter_runtime from '@x12i/openrouter-runtime';
2
2
  import { RuntimeToolExecutor, RuntimeLogger, RuntimeRequest, RuntimeResponse, RuntimeUsage, RuntimeStreamEvent, CompiledOpenRouterRequest, OpenRouterRuntimeOptions } from '@x12i/openrouter-runtime';
3
- export { CompiledOpenRouterRequest, OpenRouterRuntimeOptions, RuntimeDefaults, RuntimeLogger, RuntimeMessage, RuntimeRequest, RuntimeResponse, RuntimeServerToolsPolicy, RuntimeStreamEvent, decodeProviderMetadata } from '@x12i/openrouter-runtime';
3
+ export { CompiledOpenRouterRequest, METADATA_NORMALIZATION_MAP, NormalizedMetadataKey, OpenRouterRuntimeOptions, RuntimeDefaults, RuntimeLogger, RuntimeMessage, RuntimeRequest, RuntimeResponse, RuntimeServerToolsPolicy, RuntimeStreamEvent, canonicalMetadataKey, decodeProviderMetadata, normalizeMetadata } from '@x12i/openrouter-runtime';
4
4
  import { ReasoningEffort, ReasoningOutcome } from '@x12i/ai-profiles';
5
5
  export { ReasoningEffort, ReasoningOutcome } from '@x12i/ai-profiles';
6
6
  import { CompiledBedrockRequest, BedrockRuntimeOptions } from '@x12i/bedrock-runtime';
@@ -215,6 +215,13 @@ interface AiDispatcherOptions {
215
215
  cloudflare?: CloudflareRuntimeOptions;
216
216
  /** Connected MCP servers. The dispatcher does not open transports. */
217
217
  mcp?: DispatcherMcpOptions;
218
+ /**
219
+ * Highest priority first for the one metadata record.
220
+ * Listed keys are kept ahead of keys that are not in the list.
221
+ * The dispatcher trims on every call and adds a `METADATA_RECORD_TRIMMED` warning when it drops keys.
222
+ * The default keeps `agentId`, `orgId`, `stepId`, `skillId`, `recordId`, and `objectType`.
223
+ */
224
+ metadataPriority?: readonly string[];
218
225
  logger?: RuntimeLogger;
219
226
  }
220
227
  interface CompiledOpenAiRequest {
@@ -294,6 +301,8 @@ interface AiDispatcher {
294
301
  readonly provider: AiProviderId;
295
302
  }
296
303
 
304
+ /** Identity keys stay when a record has to be trimmed. Earlier entries are kept ahead of later ones. */
305
+ declare const DEFAULT_METADATA_PRIORITY: readonly ["agentId", "orgId", "stepId", "skillId", "recordId", "objectType"];
297
306
  declare function createAiDispatcher(options?: AiDispatcherOptions): AiDispatcher;
298
307
 
299
308
  declare class AiDispatcherError extends Error {
@@ -311,4 +320,4 @@ declare function stripReasoningHistoryFields<T>(message: T, paths: readonly stri
311
320
 
312
321
  declare function resolveProvider(requestProvider: AiProviderId | undefined, defaultProvider: AiProviderId): ImplementedAiProvider;
313
322
 
314
- export { type AiDispatcher, AiDispatcherError, type AiDispatcherOptions, type AiDispatcherRequest, type AiDispatcherResponse, type AiDispatcherUsage, type AiProviderAdapter, type AiProviderId, type CacheMode, type CacheOutcome, type CachePolicy, type CacheResolution, type CacheTtl, type CloudflareBackoff, type CloudflareCallContext, type CloudflareEndpoint, type CloudflareEndpointChoice, type CloudflareGatewayControls, type CloudflareRequestOptions, type CloudflareRunOptions, type CloudflareRuntimeOptions, type CloudflareWebhookFormat, type CompiledAiRequest, type CompiledCloudflareRequest, type CompiledOpenAiRequest, type DispatcherMcpOptions, type DispatcherMcpServer, type DispatcherMcpTool, IMPLEMENTED_AI_PROVIDERS, type ImplementedAiProvider, type OpenAiRuntimeOptions, type ReasoningResolution, createAiDispatcher, isImplementedAiProvider, providerNotImplemented, resolveProvider, stripReasoningHistoryFields };
323
+ export { type AiDispatcher, AiDispatcherError, type AiDispatcherOptions, type AiDispatcherRequest, type AiDispatcherResponse, type AiDispatcherUsage, type AiProviderAdapter, type AiProviderId, type CacheMode, type CacheOutcome, type CachePolicy, type CacheResolution, type CacheTtl, type CloudflareBackoff, type CloudflareCallContext, type CloudflareEndpoint, type CloudflareEndpointChoice, type CloudflareGatewayControls, type CloudflareRequestOptions, type CloudflareRunOptions, type CloudflareRuntimeOptions, type CloudflareWebhookFormat, type CompiledAiRequest, type CompiledCloudflareRequest, type CompiledOpenAiRequest, DEFAULT_METADATA_PRIORITY, type DispatcherMcpOptions, type DispatcherMcpServer, type DispatcherMcpTool, IMPLEMENTED_AI_PROVIDERS, type ImplementedAiProvider, type OpenAiRuntimeOptions, type ReasoningResolution, createAiDispatcher, isImplementedAiProvider, providerNotImplemented, resolveProvider, stripReasoningHistoryFields };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _x12i_openrouter_runtime from '@x12i/openrouter-runtime';
2
2
  import { RuntimeToolExecutor, RuntimeLogger, RuntimeRequest, RuntimeResponse, RuntimeUsage, RuntimeStreamEvent, CompiledOpenRouterRequest, OpenRouterRuntimeOptions } from '@x12i/openrouter-runtime';
3
- export { CompiledOpenRouterRequest, OpenRouterRuntimeOptions, RuntimeDefaults, RuntimeLogger, RuntimeMessage, RuntimeRequest, RuntimeResponse, RuntimeServerToolsPolicy, RuntimeStreamEvent, decodeProviderMetadata } from '@x12i/openrouter-runtime';
3
+ export { CompiledOpenRouterRequest, METADATA_NORMALIZATION_MAP, NormalizedMetadataKey, OpenRouterRuntimeOptions, RuntimeDefaults, RuntimeLogger, RuntimeMessage, RuntimeRequest, RuntimeResponse, RuntimeServerToolsPolicy, RuntimeStreamEvent, canonicalMetadataKey, decodeProviderMetadata, normalizeMetadata } from '@x12i/openrouter-runtime';
4
4
  import { ReasoningEffort, ReasoningOutcome } from '@x12i/ai-profiles';
5
5
  export { ReasoningEffort, ReasoningOutcome } from '@x12i/ai-profiles';
6
6
  import { CompiledBedrockRequest, BedrockRuntimeOptions } from '@x12i/bedrock-runtime';
@@ -215,6 +215,13 @@ interface AiDispatcherOptions {
215
215
  cloudflare?: CloudflareRuntimeOptions;
216
216
  /** Connected MCP servers. The dispatcher does not open transports. */
217
217
  mcp?: DispatcherMcpOptions;
218
+ /**
219
+ * Highest priority first for the one metadata record.
220
+ * Listed keys are kept ahead of keys that are not in the list.
221
+ * The dispatcher trims on every call and adds a `METADATA_RECORD_TRIMMED` warning when it drops keys.
222
+ * The default keeps `agentId`, `orgId`, `stepId`, `skillId`, `recordId`, and `objectType`.
223
+ */
224
+ metadataPriority?: readonly string[];
218
225
  logger?: RuntimeLogger;
219
226
  }
220
227
  interface CompiledOpenAiRequest {
@@ -294,6 +301,8 @@ interface AiDispatcher {
294
301
  readonly provider: AiProviderId;
295
302
  }
296
303
 
304
+ /** Identity keys stay when a record has to be trimmed. Earlier entries are kept ahead of later ones. */
305
+ declare const DEFAULT_METADATA_PRIORITY: readonly ["agentId", "orgId", "stepId", "skillId", "recordId", "objectType"];
297
306
  declare function createAiDispatcher(options?: AiDispatcherOptions): AiDispatcher;
298
307
 
299
308
  declare class AiDispatcherError extends Error {
@@ -311,4 +320,4 @@ declare function stripReasoningHistoryFields<T>(message: T, paths: readonly stri
311
320
 
312
321
  declare function resolveProvider(requestProvider: AiProviderId | undefined, defaultProvider: AiProviderId): ImplementedAiProvider;
313
322
 
314
- export { type AiDispatcher, AiDispatcherError, type AiDispatcherOptions, type AiDispatcherRequest, type AiDispatcherResponse, type AiDispatcherUsage, type AiProviderAdapter, type AiProviderId, type CacheMode, type CacheOutcome, type CachePolicy, type CacheResolution, type CacheTtl, type CloudflareBackoff, type CloudflareCallContext, type CloudflareEndpoint, type CloudflareEndpointChoice, type CloudflareGatewayControls, type CloudflareRequestOptions, type CloudflareRunOptions, type CloudflareRuntimeOptions, type CloudflareWebhookFormat, type CompiledAiRequest, type CompiledCloudflareRequest, type CompiledOpenAiRequest, type DispatcherMcpOptions, type DispatcherMcpServer, type DispatcherMcpTool, IMPLEMENTED_AI_PROVIDERS, type ImplementedAiProvider, type OpenAiRuntimeOptions, type ReasoningResolution, createAiDispatcher, isImplementedAiProvider, providerNotImplemented, resolveProvider, stripReasoningHistoryFields };
323
+ export { type AiDispatcher, AiDispatcherError, type AiDispatcherOptions, type AiDispatcherRequest, type AiDispatcherResponse, type AiDispatcherUsage, type AiProviderAdapter, type AiProviderId, type CacheMode, type CacheOutcome, type CachePolicy, type CacheResolution, type CacheTtl, type CloudflareBackoff, type CloudflareCallContext, type CloudflareEndpoint, type CloudflareEndpointChoice, type CloudflareGatewayControls, type CloudflareRequestOptions, type CloudflareRunOptions, type CloudflareRuntimeOptions, type CloudflareWebhookFormat, type CompiledAiRequest, type CompiledCloudflareRequest, type CompiledOpenAiRequest, DEFAULT_METADATA_PRIORITY, type DispatcherMcpOptions, type DispatcherMcpServer, type DispatcherMcpTool, IMPLEMENTED_AI_PROVIDERS, type ImplementedAiProvider, type OpenAiRuntimeOptions, type ReasoningResolution, createAiDispatcher, isImplementedAiProvider, providerNotImplemented, resolveProvider, stripReasoningHistoryFields };
package/dist/index.js CHANGED
@@ -1,5 +1,13 @@
1
1
  // src/index.ts
2
- import { decodeProviderMetadata } from "@x12i/openrouter-runtime";
2
+ import {
3
+ decodeProviderMetadata,
4
+ METADATA_NORMALIZATION_MAP,
5
+ canonicalMetadataKey,
6
+ normalizeMetadata
7
+ } from "@x12i/openrouter-runtime";
8
+
9
+ // src/create-dispatcher.ts
10
+ import { createMetadataPacker } from "@x12i/provider-metadata";
3
11
 
4
12
  // src/cache-usage.ts
5
13
  function readCacheTokens(source) {
@@ -1125,8 +1133,7 @@ function isRouterImplicit(id) {
1125
1133
 
1126
1134
  // src/providers/cloudflare.ts
1127
1135
  import {
1128
- OPENROUTER_METADATA_LIMITS,
1129
- toProviderMetadata
1136
+ packProviderRecord
1130
1137
  } from "@x12i/openrouter-runtime";
1131
1138
  var DEFAULT_BASE_URL = "https://api.cloudflare.com/client/v4";
1132
1139
  var DEFAULT_TIMEOUT_MS = 12e4;
@@ -1154,8 +1161,8 @@ function restoreCloudflareModel(model, prefix) {
1154
1161
  if (!prefix || model.includes("/")) return model;
1155
1162
  return `${prefix}${model}`;
1156
1163
  }
1157
- function createCloudflareProviderAdapter(options = {}) {
1158
- const resolved = resolveCloudflareOptions(options);
1164
+ function createCloudflareProviderAdapter(options = {}, packer) {
1165
+ const resolved = resolveCloudflareOptions(options, packer);
1159
1166
  return {
1160
1167
  compile(request, call) {
1161
1168
  return compileCloudflareRequest(request, resolved, call, false);
@@ -1208,12 +1215,13 @@ function compileCloudflareRequest(request, options, call, streaming) {
1208
1215
  if (endpoint !== "run") body = { ...body, stream: streaming };
1209
1216
  const gateway = mergeGateway(options.gateway, call?.cloudflare?.gateway);
1210
1217
  const fromBody = isRecord5(body.metadata) ? body.metadata : void 0;
1211
- const record2 = toProviderMetadata(
1218
+ const packed = packProviderRecord(
1212
1219
  request.metadata,
1213
1220
  request.agentId,
1214
- OPENROUTER_METADATA_LIMITS,
1215
- overlayMetadata(gateway?.metadata, fromBody)
1221
+ overlayMetadata(gateway?.metadata, fromBody),
1222
+ options.metadataPacker
1216
1223
  );
1224
+ const record2 = packed.wire;
1217
1225
  body = applyProviderRecord(body, record2);
1218
1226
  if (endpoint === "run") body = wrapRun(body, run);
1219
1227
  return {
@@ -1221,7 +1229,7 @@ function compileCloudflareRequest(request, options, call, streaming) {
1221
1229
  url: endpointUrl(options, endpoint),
1222
1230
  headers: buildHeaders(options, call?.cloudflare, model, record2),
1223
1231
  body,
1224
- warnings: []
1232
+ warnings: packed.warning ? [packed.warning] : []
1225
1233
  };
1226
1234
  }
1227
1235
  function compileResponsesBody(request, model) {
@@ -2270,7 +2278,7 @@ function parseSsePart(part) {
2270
2278
  return void 0;
2271
2279
  }
2272
2280
  }
2273
- function resolveCloudflareOptions(options) {
2281
+ function resolveCloudflareOptions(options, packer) {
2274
2282
  const {
2275
2283
  apiToken,
2276
2284
  accountId,
@@ -2299,7 +2307,8 @@ function resolveCloudflareOptions(options) {
2299
2307
  maxAttempts: maxAttempts ?? 2,
2300
2308
  fetch: fetch ?? globalThis.fetch,
2301
2309
  ...tools ? { tools } : {},
2302
- ...logger ? { logger } : {}
2310
+ ...logger ? { logger } : {},
2311
+ ...packer ? { metadataPacker: packer } : {}
2303
2312
  };
2304
2313
  }
2305
2314
  function hasGateway(gateway) {
@@ -2814,13 +2823,12 @@ function isBedrockToolChoice(toolChoice) {
2814
2823
 
2815
2824
  // src/providers/openai.ts
2816
2825
  import {
2817
- OPENROUTER_METADATA_LIMITS as OPENROUTER_METADATA_LIMITS2,
2818
- toProviderMetadata as toProviderMetadata2
2826
+ packProviderRecord as packProviderRecord2
2819
2827
  } from "@x12i/openrouter-runtime";
2820
2828
  var DEFAULT_BASE_URL2 = "https://api.openai.com/v1";
2821
2829
  var DEFAULT_TIMEOUT_MS2 = 12e4;
2822
- function createOpenAiProviderAdapter(options = {}) {
2823
- const resolved = resolveOpenAiOptions(options);
2830
+ function createOpenAiProviderAdapter(options = {}, packer) {
2831
+ const resolved = resolveOpenAiOptions(options, packer);
2824
2832
  return {
2825
2833
  compile(request, call) {
2826
2834
  return compileOpenAiRequest(request, resolved, call, false);
@@ -2873,12 +2881,13 @@ function compileOpenAiRequest(request, options, call, streaming) {
2873
2881
  if (call?.finalizeBody) body = call.finalizeBody(body);
2874
2882
  if (streaming) body = { ...body, stream: true };
2875
2883
  else body = { ...body, stream: false };
2876
- body = attachProviderMetadata(body, request);
2884
+ const packed = attachProviderMetadata(body, request, options.metadataPacker);
2885
+ body = packed.body;
2877
2886
  return {
2878
2887
  url: `${options.baseUrl}/responses`,
2879
2888
  headers: buildHeaders2(options),
2880
2889
  body,
2881
- warnings: []
2890
+ warnings: packed.warning ? [packed.warning] : []
2882
2891
  };
2883
2892
  }
2884
2893
  function assertSupported2(request) {
@@ -3378,14 +3387,14 @@ function messageFrom2(body) {
3378
3387
  function numberValue2(value) {
3379
3388
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
3380
3389
  }
3381
- function attachProviderMetadata(body, request) {
3390
+ function attachProviderMetadata(body, request, packer) {
3382
3391
  const fromBody = isRecord7(body.metadata) ? body.metadata : void 0;
3383
- const metadata = toProviderMetadata2(request.metadata, request.agentId, OPENROUTER_METADATA_LIMITS2, fromBody);
3384
- if (metadata) return { ...body, metadata };
3385
- if (body.metadata === void 0) return body;
3392
+ const packed = packProviderRecord2(request.metadata, request.agentId, fromBody, packer);
3393
+ if (packed.wire) return { body: { ...body, metadata: packed.wire }, ...packed.warning ? { warning: packed.warning } : {} };
3394
+ if (body.metadata === void 0) return { body, ...packed.warning ? { warning: packed.warning } : {} };
3386
3395
  const rest = { ...body };
3387
3396
  delete rest.metadata;
3388
- return rest;
3397
+ return { body: rest, ...packed.warning ? { warning: packed.warning } : {} };
3389
3398
  }
3390
3399
  function clean2(body) {
3391
3400
  return Object.fromEntries(Object.entries(body).filter(([, value]) => value !== void 0));
@@ -3433,7 +3442,7 @@ function parseSsePart2(part) {
3433
3442
  return void 0;
3434
3443
  }
3435
3444
  }
3436
- function resolveOpenAiOptions(options) {
3445
+ function resolveOpenAiOptions(options, packer) {
3437
3446
  const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL2).replace(/\/+$/, "");
3438
3447
  return {
3439
3448
  apiKey: options.apiKey ?? readEnv3("OPENAI_API_KEY") ?? "",
@@ -3445,7 +3454,8 @@ function resolveOpenAiOptions(options) {
3445
3454
  maxAttempts: options.maxAttempts ?? 3,
3446
3455
  fetch: options.fetch ?? globalThis.fetch,
3447
3456
  ...options.tools ? { tools: options.tools } : {},
3448
- ...options.logger ? { logger: options.logger } : {}
3457
+ ...options.logger ? { logger: options.logger } : {},
3458
+ ...packer ? { metadataPacker: packer } : {}
3449
3459
  };
3450
3460
  }
3451
3461
  function readEnv3(name) {
@@ -3500,7 +3510,9 @@ function resolveProvider(requestProvider, defaultProvider) {
3500
3510
 
3501
3511
  // src/create-dispatcher.ts
3502
3512
  var SECRET_HEADERS = /* @__PURE__ */ new Set(["authorization", "x-api-key", "api-key"]);
3513
+ var DEFAULT_METADATA_PRIORITY = ["agentId", "orgId", "stepId", "skillId", "recordId", "objectType"];
3503
3514
  function createAiDispatcher(options = {}) {
3515
+ const packer = createMetadataPacker({ priority: options.metadataPriority ?? DEFAULT_METADATA_PRIORITY });
3504
3516
  const defaultProvider = resolveProvider(options.provider, "openrouter");
3505
3517
  const catalog = createMcpCatalog(options.mcp);
3506
3518
  let refreshChain = Promise.resolve();
@@ -3509,6 +3521,7 @@ function createAiDispatcher(options = {}) {
3509
3521
  if (provider === "openrouter") {
3510
3522
  const openrouterOptions = {
3511
3523
  ...options.openrouter,
3524
+ metadataPacker: packer,
3512
3525
  ...options.logger && !options.openrouter?.logger ? { logger: options.logger } : {}
3513
3526
  };
3514
3527
  return createOpenRouterProviderAdapter(openrouterOptions);
@@ -3516,6 +3529,7 @@ function createAiDispatcher(options = {}) {
3516
3529
  if (provider === "bedrock") {
3517
3530
  const bedrockOptions = {
3518
3531
  ...options.bedrock,
3532
+ metadataPacker: packer,
3519
3533
  ...options.logger && !options.bedrock?.logger ? { logger: options.logger } : {}
3520
3534
  };
3521
3535
  return createBedrockProviderAdapter(bedrockOptions);
@@ -3525,14 +3539,14 @@ function createAiDispatcher(options = {}) {
3525
3539
  ...options.openai,
3526
3540
  ...options.logger && !options.openai?.logger ? { logger: options.logger } : {}
3527
3541
  };
3528
- return createOpenAiProviderAdapter(openaiOptions);
3542
+ return createOpenAiProviderAdapter(openaiOptions, packer);
3529
3543
  }
3530
3544
  if (provider === "cloudflare") {
3531
3545
  const cloudflareOptions = {
3532
3546
  ...options.cloudflare,
3533
3547
  ...options.logger && !options.cloudflare?.logger ? { logger: options.logger } : {}
3534
3548
  };
3535
- return createCloudflareProviderAdapter(cloudflareOptions);
3549
+ return createCloudflareProviderAdapter(cloudflareOptions, packer);
3536
3550
  }
3537
3551
  throw new AiDispatcherError(
3538
3552
  "PROVIDER_ADAPTER_MISSING",
@@ -3652,10 +3666,14 @@ function stripReasoningHistoryFields(message, paths) {
3652
3666
  }
3653
3667
  export {
3654
3668
  AiDispatcherError,
3669
+ DEFAULT_METADATA_PRIORITY,
3655
3670
  IMPLEMENTED_AI_PROVIDERS,
3671
+ METADATA_NORMALIZATION_MAP,
3672
+ canonicalMetadataKey,
3656
3673
  createAiDispatcher,
3657
3674
  decodeProviderMetadata,
3658
3675
  isImplementedAiProvider,
3676
+ normalizeMetadata,
3659
3677
  providerNotImplemented,
3660
3678
  resolveProvider,
3661
3679
  stripReasoningHistoryFields