@x12i/ai-dispatcher 2.0.0 → 2.1.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
@@ -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
@@ -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,6 +1,9 @@
1
1
  // src/index.ts
2
2
  import { decodeProviderMetadata } from "@x12i/openrouter-runtime";
3
3
 
4
+ // src/create-dispatcher.ts
5
+ import { createMetadataPacker } from "@x12i/provider-metadata";
6
+
4
7
  // src/cache-usage.ts
5
8
  function readCacheTokens(source) {
6
9
  const cached = [];
@@ -1125,8 +1128,7 @@ function isRouterImplicit(id) {
1125
1128
 
1126
1129
  // src/providers/cloudflare.ts
1127
1130
  import {
1128
- OPENROUTER_METADATA_LIMITS,
1129
- toProviderMetadata
1131
+ packProviderRecord
1130
1132
  } from "@x12i/openrouter-runtime";
1131
1133
  var DEFAULT_BASE_URL = "https://api.cloudflare.com/client/v4";
1132
1134
  var DEFAULT_TIMEOUT_MS = 12e4;
@@ -1154,8 +1156,8 @@ function restoreCloudflareModel(model, prefix) {
1154
1156
  if (!prefix || model.includes("/")) return model;
1155
1157
  return `${prefix}${model}`;
1156
1158
  }
1157
- function createCloudflareProviderAdapter(options = {}) {
1158
- const resolved = resolveCloudflareOptions(options);
1159
+ function createCloudflareProviderAdapter(options = {}, packer) {
1160
+ const resolved = resolveCloudflareOptions(options, packer);
1159
1161
  return {
1160
1162
  compile(request, call) {
1161
1163
  return compileCloudflareRequest(request, resolved, call, false);
@@ -1208,12 +1210,13 @@ function compileCloudflareRequest(request, options, call, streaming) {
1208
1210
  if (endpoint !== "run") body = { ...body, stream: streaming };
1209
1211
  const gateway = mergeGateway(options.gateway, call?.cloudflare?.gateway);
1210
1212
  const fromBody = isRecord5(body.metadata) ? body.metadata : void 0;
1211
- const record2 = toProviderMetadata(
1213
+ const packed = packProviderRecord(
1212
1214
  request.metadata,
1213
1215
  request.agentId,
1214
- OPENROUTER_METADATA_LIMITS,
1215
- overlayMetadata(gateway?.metadata, fromBody)
1216
+ overlayMetadata(gateway?.metadata, fromBody),
1217
+ options.metadataPacker
1216
1218
  );
1219
+ const record2 = packed.wire;
1217
1220
  body = applyProviderRecord(body, record2);
1218
1221
  if (endpoint === "run") body = wrapRun(body, run);
1219
1222
  return {
@@ -1221,7 +1224,7 @@ function compileCloudflareRequest(request, options, call, streaming) {
1221
1224
  url: endpointUrl(options, endpoint),
1222
1225
  headers: buildHeaders(options, call?.cloudflare, model, record2),
1223
1226
  body,
1224
- warnings: []
1227
+ warnings: packed.warning ? [packed.warning] : []
1225
1228
  };
1226
1229
  }
1227
1230
  function compileResponsesBody(request, model) {
@@ -2270,7 +2273,7 @@ function parseSsePart(part) {
2270
2273
  return void 0;
2271
2274
  }
2272
2275
  }
2273
- function resolveCloudflareOptions(options) {
2276
+ function resolveCloudflareOptions(options, packer) {
2274
2277
  const {
2275
2278
  apiToken,
2276
2279
  accountId,
@@ -2299,7 +2302,8 @@ function resolveCloudflareOptions(options) {
2299
2302
  maxAttempts: maxAttempts ?? 2,
2300
2303
  fetch: fetch ?? globalThis.fetch,
2301
2304
  ...tools ? { tools } : {},
2302
- ...logger ? { logger } : {}
2305
+ ...logger ? { logger } : {},
2306
+ ...packer ? { metadataPacker: packer } : {}
2303
2307
  };
2304
2308
  }
2305
2309
  function hasGateway(gateway) {
@@ -2814,13 +2818,12 @@ function isBedrockToolChoice(toolChoice) {
2814
2818
 
2815
2819
  // src/providers/openai.ts
2816
2820
  import {
2817
- OPENROUTER_METADATA_LIMITS as OPENROUTER_METADATA_LIMITS2,
2818
- toProviderMetadata as toProviderMetadata2
2821
+ packProviderRecord as packProviderRecord2
2819
2822
  } from "@x12i/openrouter-runtime";
2820
2823
  var DEFAULT_BASE_URL2 = "https://api.openai.com/v1";
2821
2824
  var DEFAULT_TIMEOUT_MS2 = 12e4;
2822
- function createOpenAiProviderAdapter(options = {}) {
2823
- const resolved = resolveOpenAiOptions(options);
2825
+ function createOpenAiProviderAdapter(options = {}, packer) {
2826
+ const resolved = resolveOpenAiOptions(options, packer);
2824
2827
  return {
2825
2828
  compile(request, call) {
2826
2829
  return compileOpenAiRequest(request, resolved, call, false);
@@ -2873,12 +2876,13 @@ function compileOpenAiRequest(request, options, call, streaming) {
2873
2876
  if (call?.finalizeBody) body = call.finalizeBody(body);
2874
2877
  if (streaming) body = { ...body, stream: true };
2875
2878
  else body = { ...body, stream: false };
2876
- body = attachProviderMetadata(body, request);
2879
+ const packed = attachProviderMetadata(body, request, options.metadataPacker);
2880
+ body = packed.body;
2877
2881
  return {
2878
2882
  url: `${options.baseUrl}/responses`,
2879
2883
  headers: buildHeaders2(options),
2880
2884
  body,
2881
- warnings: []
2885
+ warnings: packed.warning ? [packed.warning] : []
2882
2886
  };
2883
2887
  }
2884
2888
  function assertSupported2(request) {
@@ -3378,14 +3382,14 @@ function messageFrom2(body) {
3378
3382
  function numberValue2(value) {
3379
3383
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
3380
3384
  }
3381
- function attachProviderMetadata(body, request) {
3385
+ function attachProviderMetadata(body, request, packer) {
3382
3386
  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;
3387
+ const packed = packProviderRecord2(request.metadata, request.agentId, fromBody, packer);
3388
+ if (packed.wire) return { body: { ...body, metadata: packed.wire }, ...packed.warning ? { warning: packed.warning } : {} };
3389
+ if (body.metadata === void 0) return { body, ...packed.warning ? { warning: packed.warning } : {} };
3386
3390
  const rest = { ...body };
3387
3391
  delete rest.metadata;
3388
- return rest;
3392
+ return { body: rest, ...packed.warning ? { warning: packed.warning } : {} };
3389
3393
  }
3390
3394
  function clean2(body) {
3391
3395
  return Object.fromEntries(Object.entries(body).filter(([, value]) => value !== void 0));
@@ -3433,7 +3437,7 @@ function parseSsePart2(part) {
3433
3437
  return void 0;
3434
3438
  }
3435
3439
  }
3436
- function resolveOpenAiOptions(options) {
3440
+ function resolveOpenAiOptions(options, packer) {
3437
3441
  const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL2).replace(/\/+$/, "");
3438
3442
  return {
3439
3443
  apiKey: options.apiKey ?? readEnv3("OPENAI_API_KEY") ?? "",
@@ -3445,7 +3449,8 @@ function resolveOpenAiOptions(options) {
3445
3449
  maxAttempts: options.maxAttempts ?? 3,
3446
3450
  fetch: options.fetch ?? globalThis.fetch,
3447
3451
  ...options.tools ? { tools: options.tools } : {},
3448
- ...options.logger ? { logger: options.logger } : {}
3452
+ ...options.logger ? { logger: options.logger } : {},
3453
+ ...packer ? { metadataPacker: packer } : {}
3449
3454
  };
3450
3455
  }
3451
3456
  function readEnv3(name) {
@@ -3500,7 +3505,9 @@ function resolveProvider(requestProvider, defaultProvider) {
3500
3505
 
3501
3506
  // src/create-dispatcher.ts
3502
3507
  var SECRET_HEADERS = /* @__PURE__ */ new Set(["authorization", "x-api-key", "api-key"]);
3508
+ var DEFAULT_METADATA_PRIORITY = ["agentId", "orgId", "stepId", "skillId", "recordId", "objectType"];
3503
3509
  function createAiDispatcher(options = {}) {
3510
+ const packer = createMetadataPacker({ priority: options.metadataPriority ?? DEFAULT_METADATA_PRIORITY });
3504
3511
  const defaultProvider = resolveProvider(options.provider, "openrouter");
3505
3512
  const catalog = createMcpCatalog(options.mcp);
3506
3513
  let refreshChain = Promise.resolve();
@@ -3509,6 +3516,7 @@ function createAiDispatcher(options = {}) {
3509
3516
  if (provider === "openrouter") {
3510
3517
  const openrouterOptions = {
3511
3518
  ...options.openrouter,
3519
+ metadataPacker: packer,
3512
3520
  ...options.logger && !options.openrouter?.logger ? { logger: options.logger } : {}
3513
3521
  };
3514
3522
  return createOpenRouterProviderAdapter(openrouterOptions);
@@ -3516,6 +3524,7 @@ function createAiDispatcher(options = {}) {
3516
3524
  if (provider === "bedrock") {
3517
3525
  const bedrockOptions = {
3518
3526
  ...options.bedrock,
3527
+ metadataPacker: packer,
3519
3528
  ...options.logger && !options.bedrock?.logger ? { logger: options.logger } : {}
3520
3529
  };
3521
3530
  return createBedrockProviderAdapter(bedrockOptions);
@@ -3525,14 +3534,14 @@ function createAiDispatcher(options = {}) {
3525
3534
  ...options.openai,
3526
3535
  ...options.logger && !options.openai?.logger ? { logger: options.logger } : {}
3527
3536
  };
3528
- return createOpenAiProviderAdapter(openaiOptions);
3537
+ return createOpenAiProviderAdapter(openaiOptions, packer);
3529
3538
  }
3530
3539
  if (provider === "cloudflare") {
3531
3540
  const cloudflareOptions = {
3532
3541
  ...options.cloudflare,
3533
3542
  ...options.logger && !options.cloudflare?.logger ? { logger: options.logger } : {}
3534
3543
  };
3535
- return createCloudflareProviderAdapter(cloudflareOptions);
3544
+ return createCloudflareProviderAdapter(cloudflareOptions, packer);
3536
3545
  }
3537
3546
  throw new AiDispatcherError(
3538
3547
  "PROVIDER_ADAPTER_MISSING",
@@ -3652,6 +3661,7 @@ function stripReasoningHistoryFields(message, paths) {
3652
3661
  }
3653
3662
  export {
3654
3663
  AiDispatcherError,
3664
+ DEFAULT_METADATA_PRIORITY,
3655
3665
  IMPLEMENTED_AI_PROVIDERS,
3656
3666
  createAiDispatcher,
3657
3667
  decodeProviderMetadata,