@x12i/ai-dispatcher 3.0.0 → 3.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/README.md CHANGED
@@ -144,7 +144,7 @@ Text can arrive as `prompt`, `messages`, `input`, `system`, or `instructions`. A
144
144
  | `functionTools` | Local function tools: `name`, `description`, `parameters`, optional `executor`. |
145
145
  | `toolChoice` | `"auto"`, `"none"`, `"required"`, `{ type: "function", functionName }`, or an OpenRouter `{ type: "server_tool", serverTool }`. |
146
146
  | `execution` | `maxToolIterations`, `maxServerToolCalls`, `maxFunctionToolCalls`, `timeoutMs`. Bedrock keeps the iteration, function-call, and timeout limits. |
147
- | `metadata` | The one metadata record. String, number, and boolean values, including `xtivix.execution`, `recordId`, and `objectType`. |
147
+ | `metadata` | The one metadata record. String, number, and boolean values, including `session_id`, `xtivix.caller`, `xtivix.execution`, `recordId`, and `objectType`. The package adds `xtivix.gate`. |
148
148
  | `serverTools` | OpenRouter server tools only. Bedrock, direct OpenAI, and Cloudflare reject an enabled policy. |
149
149
  | `apiMode` | `"chat"`, `"responses"`, or `"auto"`. Direct OpenAI rejects `"chat"`. Bedrock rejects any `apiMode`. On Cloudflare, `"chat"` and `"responses"` select those endpoints when `cloudflare.endpoint` is omitted or `auto`. |
150
150
  | `responseFormat` | OpenRouter forwards it. Direct OpenAI and Cloudflare Responses place it on `text`. Cloudflare chat sends `response_format`. Cloudflare messages and run reject it. Bedrock rejects it. |
@@ -156,6 +156,8 @@ Text can arrive as `prompt`, `messages`, `input`, `system`, or `instructions`. A
156
156
 
157
157
  Set `metadata` for the pairs you want back from a log. `agentId`, `orgId`, `stepId`, and `skillId` are fields on the same record. A `role` object expands to `role`, `roleLayer`, `roleDigest`, and `profileChoice` on that record. A dedicated field wins over the same key inside `metadata`. Omit an id you do not have. The dispatcher does not invent one.
158
158
 
159
+ `session_id` is the thread id. Send the full string on `metadata`, including `dd:`, the package, the version, and the hash. Leave it as one string. `session.id` is promoted to `session_id`. A key named `sessionId` is a different key and does not become the thread. `xtivix.caller` is your name for who sent the call. Omit it when you do not have one. The dispatcher does not invent it. `xtivix.gate` is written by this package on every call, as `ai-dispatcher` (`AI_DISPATCHER_GATE`). A value you send for that key is replaced. The gate is not the model provider. These values are plain strings. Slashes, `@`, and colons in the session id need no escaping.
160
+
159
161
  ```ts
160
162
  import { decodeProviderMetadata } from "@x12i/ai-dispatcher";
161
163
 
@@ -167,6 +169,8 @@ await dispatcher.run({
167
169
  stepId: "step-3",
168
170
  skillId: "skill-9",
169
171
  metadata: {
172
+ session_id: "dd:@xverix/mail-decisions/vendor@0.1.0:46b03b5e",
173
+ "xtivix.caller": "mail-decisions",
170
174
  "xtivix.execution": executionJson,
171
175
  recordId: "rec-1",
172
176
  objectType: "note"
@@ -176,9 +180,9 @@ await dispatcher.run({
176
180
  const record = decodeProviderMetadata(logMetadata);
177
181
  ```
178
182
 
179
- `metadata` is the one record. When `rawOpenRouterOverrides` only repeats `metadata`, the dispatcher folds it in. `metadata` wins when the same key is in both places. String, number, and boolean values are stored, including a JSON string. Objects and arrays stay on the normalized response and the tool context.
183
+ `metadata` is the one record. When `rawOpenRouterOverrides` only repeats `metadata`, the dispatcher folds it in. `metadata` wins when the same key is in both places. `xtivix.gate` is the exception: the package value wins. String, number, and boolean values are stored, including a JSON string. Objects and arrays stay on the normalized response and the tool context.
180
184
 
181
- Every provider writes that record as `m.0`, `m.1`, and so on: one base64 string, 256 characters per piece, at most 16 pieces. The base64 is the UTF-8 JSON object of the string map, with keys sorted. `decodeProviderMetadata` reads those pieces from OpenRouter body `metadata`, OpenAI Responses `metadata`, Bedrock `requestMetadata`, or Cloudflare body `metadata`. Pass the Cloudflare `cf-aig-metadata` header as that same object or as the raw JSON string. The pieces are the same on every provider. The dispatcher trims on every call. Pass `metadataPriority` (highest priority first) to choose what stays. The default keeps `agentId`, `orgId`, `stepId`, `skillId`, `role`, `roleLayer`, `roleDigest`, `profileChoice`, `recordId`, and `objectType`. A trimmed call adds a `METADATA_RECORD_TRIMMED` warning.
185
+ Every provider writes that record as `m.0`, `m.1`, and so on: one base64 string, 256 characters per piece, at most 16 pieces. The base64 is the UTF-8 JSON object of the string map, with keys sorted. `decodeProviderMetadata` reads those pieces from OpenRouter body `metadata`, OpenAI Responses `metadata`, Bedrock `requestMetadata`, or Cloudflare body `metadata`. Pass the Cloudflare `cf-aig-metadata` header as that same object or as the raw JSON string. The pieces are the same on every provider. The dispatcher trims on every call. Pass `metadataPriority` (highest priority first) to choose what stays. The default keeps `agentId`, `orgId`, `stepId`, `skillId`, `role`, `roleLayer`, `roleDigest`, `profileChoice`, `recordId`, and `objectType`. `session_id`, `xtivix.caller`, and `xtivix.gate` are not in that list. Unlisted keys are dropped longest first, so these short values stay unless the record is still over the limit after every longer unlisted value, including `xtivix.execution`, has been dropped. Include `session_id`, `xtivix.caller`, and `xtivix.gate` when you pass your own `metadataPriority`. A trimmed call adds a `METADATA_RECORD_TRIMMED` warning.
182
186
 
183
187
  Repeating vendor fields normalize to one key. Prefer `metadata.api_key_name` over `metadata.openrouter.api_key_name`. `normalizeMetadata` and `decodeProviderMetadata` promote known aliases and keep the vendor key. Grow `METADATA_NORMALIZATION_MAP` as more shared fields appear.
184
188
 
package/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AI_DISPATCHER_GATE: () => AI_DISPATCHER_GATE,
33
34
  AiDispatcherError: () => AiDispatcherError,
34
35
  DEFAULT_METADATA_PRIORITY: () => DEFAULT_METADATA_PRIORITY,
35
36
  IMPLEMENTED_AI_PROVIDERS: () => IMPLEMENTED_AI_PROVIDERS,
@@ -2650,6 +2651,7 @@ function prepareDispatchRequest(params) {
2650
2651
  applyRoleStamp(cloned);
2651
2652
  applyDispatchIdentity(cloned);
2652
2653
  absorbOverrideMetadata(cloned);
2654
+ applyDispatchGate(cloned);
2653
2655
  const provider = params.provider;
2654
2656
  const reasoningEffort = cloned.reasoningEffort;
2655
2657
  const bedrockControls = cloned.bedrockControls;
@@ -3002,6 +3004,12 @@ function applyDispatchIdentity(request) {
3002
3004
  for (const key of Object.keys(identity)) delete rest[key];
3003
3005
  request.metadata = { ...identity, ...rest };
3004
3006
  }
3007
+ var AI_DISPATCHER_GATE = "ai-dispatcher";
3008
+ function applyDispatchGate(request) {
3009
+ const rest = { ...request.metadata ?? {} };
3010
+ delete rest["xtivix.gate"];
3011
+ request.metadata = { "xtivix.gate": AI_DISPATCHER_GATE, ...rest };
3012
+ }
3005
3013
  function cloneRequest(request) {
3006
3014
  const functionTools = request.functionTools?.map((tool) => ({ ...tool }));
3007
3015
  const cloned = JSON.parse(JSON.stringify(request));
@@ -4026,6 +4034,7 @@ function stripReasoningHistoryFields(message, paths) {
4026
4034
  }
4027
4035
  // Annotate the CommonJS export names for ESM import in node:
4028
4036
  0 && (module.exports = {
4037
+ AI_DISPATCHER_GATE,
4029
4038
  AiDispatcherError,
4030
4039
  DEFAULT_METADATA_PRIORITY,
4031
4040
  IMPLEMENTED_AI_PROVIDERS,