@anuma/sdk 6.14.2 → 6.15.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.
Files changed (26) hide show
  1. package/dist/client/index.cjs +13 -0
  2. package/dist/client/index.d.mts +187 -1
  3. package/dist/client/index.d.ts +187 -1
  4. package/dist/client/index.mjs +11 -0
  5. package/dist/expo/{chunk-O25LUKBK.mjs → chunk-3V3BBJLH.mjs} +66 -8
  6. package/dist/expo/{chunk-M4JSLFTQ.mjs → chunk-DIUQLXEH.mjs} +1 -1
  7. package/dist/expo/{chunk-JA7CDJCA.mjs → chunk-LUSKQQDD.mjs} +2 -2
  8. package/dist/{react/consolidate-LSDBMQDW.mjs → expo/consolidate-GTMXZZ4C.mjs} +2 -2
  9. package/dist/expo/index.cjs +67 -9
  10. package/dist/expo/index.mjs +4 -4
  11. package/dist/expo/{recall-JYVHWU6N.mjs → recall-GKYVPD2B.mjs} +2 -2
  12. package/dist/react/{chunk-2XLHV2XW.mjs → chunk-2GNOTRG4.mjs} +1 -1
  13. package/dist/react/{chunk-O25LUKBK.mjs → chunk-3V3BBJLH.mjs} +66 -8
  14. package/dist/react/{chunk-DNSPMVBY.mjs → chunk-PDKKPAXP.mjs} +2 -2
  15. package/dist/{expo/consolidate-S3KFA2WT.mjs → react/consolidate-Y2XWEZRQ.mjs} +2 -2
  16. package/dist/react/index.cjs +67 -9
  17. package/dist/react/index.mjs +4 -4
  18. package/dist/react/{recall-2BWBJWGG.mjs → recall-5HNAFHLL.mjs} +2 -2
  19. package/dist/server/{chunk-O7TB36P3.mjs → chunk-2QFK4L7Y.mjs} +2 -2
  20. package/dist/server/{chunk-7D3RI25K.mjs → chunk-H4G3DLDJ.mjs} +66 -8
  21. package/dist/server/{chunk-GP6YY6H5.mjs → chunk-JPLFOSB2.mjs} +1 -1
  22. package/dist/server/{consolidate-Z2JJP7LW.mjs → consolidate-CMMDTZ37.mjs} +2 -2
  23. package/dist/server/index.cjs +67 -9
  24. package/dist/server/index.mjs +4 -4
  25. package/dist/server/{recall-VHU372MK.mjs → recall-EODNEKIA.mjs} +2 -2
  26. package/package.json +2 -2
@@ -6429,6 +6429,23 @@ function supportsResponseFormat(model, variant = "json_object") {
6429
6429
  const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
6430
6430
  return model.split("/").some((seg) => allow.has(seg));
6431
6431
  }
6432
+ function responsesExtra(extra) {
6433
+ if (!extra) return {};
6434
+ const out = {};
6435
+ for (const [key, value] of Object.entries(extra)) {
6436
+ const target = CHAT_TO_RESPONSES_FIELDS[key] ?? key;
6437
+ if (target !== key && target in extra) continue;
6438
+ out[target] = value;
6439
+ }
6440
+ return out;
6441
+ }
6442
+ function assertTransportMatchesEndpoint(transport, endpoint) {
6443
+ const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
6444
+ if (!endpoint.endsWith(foreign)) return;
6445
+ throw new Error(
6446
+ `endpointOverride "${endpoint}" is the other transport's endpoint, but transport is "${transport}". The request body is built for the transport, so this sends the wrong shape and 400s without retry.`
6447
+ );
6448
+ }
6432
6449
  function isRetryableStatus(status) {
6433
6450
  return status >= 500 || RETRYABLE_HTTP.has(status);
6434
6451
  }
@@ -6469,13 +6486,14 @@ async function resolvePortalAuthHeaders(auth, tag) {
6469
6486
  }
6470
6487
  async function callPortalJsonCompletion(req) {
6471
6488
  const log = getLogger();
6472
- let endpoint = "/api/v1/chat/completions";
6489
+ let endpoint = req.transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
6473
6490
  if (req.endpointOverride !== void 0) {
6474
6491
  const overrideValidation = validateEndpointOverride(req.endpointOverride);
6475
6492
  if (!overrideValidation.valid) {
6476
6493
  throw new Error(overrideValidation.message);
6477
6494
  }
6478
6495
  endpoint = overrideValidation.endpoint;
6496
+ assertTransportMatchesEndpoint(req.transport ?? "chat", endpoint);
6479
6497
  }
6480
6498
  const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
6481
6499
  const startedAt = Date.now();
@@ -6537,8 +6555,8 @@ async function attemptPortalJson(req, endpoint) {
6537
6555
  const authHeaders = await resolvePortalAuthHeaders(req, req.tag);
6538
6556
  if (authHeaders === null)
6539
6557
  return { kind: "terminal", code: "auth-unavailable", reason: "auth unavailable (no token)" };
6540
- const isAnthropic = req.model.startsWith("anthropic/");
6541
- const prefill = isAnthropic ? "{" : "";
6558
+ const usesPrefill = req.transport !== "responses" && req.model.startsWith("anthropic/");
6559
+ const prefill = usesPrefill ? "{" : "";
6542
6560
  const messages = [
6543
6561
  // Every caller of this helper is a first-party BACKGROUND op (fact extraction,
6544
6562
  // topic sweep, consolidation, classifiers, graph traversal, query
@@ -6557,13 +6575,34 @@ async function attemptPortalJson(req, endpoint) {
6557
6575
  const supportsJsonObjectFormat = supportsResponseFormat(req.model);
6558
6576
  const controller = new AbortController();
6559
6577
  const timer = setTimeout(() => controller.abort(), timeoutMs);
6560
- const requestBody = {
6578
+ const requestBody = req.transport === "responses" ? {
6579
+ model: req.model,
6580
+ // Same system+user pair under the Responses-API field name. No prefill
6581
+ // entry to strip: `usesPrefill` is false on this transport, so it was
6582
+ // never pushed and the response-side restore is disarmed with it. An
6583
+ // earlier version pushed it and sliced it back off here, which left
6584
+ // `prefill` truthy and the restore still armed — the fix belonged at
6585
+ // the decision, not at the two symptoms.
6586
+ input: messages,
6587
+ ...req.reasoning && { reasoning: req.reasoning },
6588
+ // NO response_format. The Responses API spells structured output
6589
+ // differently (`text.format`), and it is unverified against this
6590
+ // portal — so this transport relies on the same strict-JSON system
6591
+ // prompt plus `extractJsonCandidate` that every response_format-
6592
+ // rejecting model already relies on. Verified end to end on dev:
6593
+ // luna returns clean parseable JSON here without it. Add the field
6594
+ // only with a per-provider check, exactly as RESPONSE_FORMAT_OK was
6595
+ // earned.
6596
+ ...responsesExtra(req.extra)
6597
+ } : {
6561
6598
  model: req.model,
6562
6599
  messages,
6563
6600
  ...supportsJsonObjectFormat && { response_format: { type: "json_object" } },
6564
6601
  ...req.extra
6565
6602
  };
6566
- if (!supportsJsonObjectFormat) delete requestBody.response_format;
6603
+ if (req.transport === "responses" || !supportsJsonObjectFormat) {
6604
+ delete requestBody.response_format;
6605
+ }
6567
6606
  let response;
6568
6607
  try {
6569
6608
  response = await fetchImpl(`${baseUrl}${endpoint}`, {
@@ -6693,13 +6732,15 @@ function logPortalUsage(body, tag) {
6693
6732
  const root = asRecord(body);
6694
6733
  if (!root) return;
6695
6734
  const usage = asRecord(root.usage);
6696
- const promptTokens = asCount(usage?.prompt_tokens);
6697
- const completionTokens = asCount(usage?.completion_tokens);
6735
+ const promptTokens = asCount(usage?.prompt_tokens) ?? asCount(usage?.input_tokens);
6736
+ const completionTokens = asCount(usage?.completion_tokens) ?? asCount(usage?.output_tokens);
6698
6737
  if (promptTokens === void 0 && completionTokens === void 0) return;
6699
- const cachedTokens = asCount(asRecord(root.portal)?.cached_tokens) ?? asCount(asRecord(usage?.prompt_tokens_details)?.cached_tokens) ?? 0;
6738
+ const cachedTokens = asCount(asRecord(root.portal)?.cached_tokens) ?? asCount(asRecord(usage?.prompt_tokens_details)?.cached_tokens) ?? asCount(asRecord(usage?.input_tokens_details)?.cached_tokens) ?? 0;
6739
+ const reasoningTokens = asCount(asRecord(usage?.output_tokens_details)?.reasoning_tokens) ?? asCount(asRecord(usage?.completion_tokens_details)?.reasoning_tokens);
6700
6740
  const parts = [];
6701
6741
  if (promptTokens !== void 0) parts.push(`prompt=${promptTokens}`);
6702
6742
  if (completionTokens !== void 0) parts.push(`completion=${completionTokens}`);
6743
+ if (reasoningTokens !== void 0) parts.push(`reasoning=${reasoningTokens}`);
6703
6744
  parts.push(`cached=${cachedTokens}`);
6704
6745
  getLogger().debug(`[${tag}] usage ${parts.join(" ")}`);
6705
6746
  } catch {
@@ -6707,13 +6748,23 @@ function logPortalUsage(body, tag) {
6707
6748
  }
6708
6749
  function extractCompletionContent(body) {
6709
6750
  if (typeof body !== "object" || body === null) return null;
6751
+ const responsesText = extractResponsesContent(body);
6752
+ if (responsesText !== null) return responsesText;
6710
6753
  const choices = body.choices;
6711
6754
  if (!Array.isArray(choices) || choices.length === 0) return null;
6712
6755
  const first = choices[0];
6713
6756
  const content = first?.message?.content;
6714
6757
  return typeof content === "string" ? content : null;
6715
6758
  }
6716
- var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RETRYABLE_HTTP;
6759
+ function extractResponsesContent(body) {
6760
+ const root = asRecord(body);
6761
+ if (!root) return null;
6762
+ if (typeof root.output_text === "string" && root.output_text !== "") return root.output_text;
6763
+ if (!Array.isArray(root.output)) return null;
6764
+ const text12 = root.output.filter((item) => asRecord(item)?.type === "message").flatMap((item) => Array.isArray(item.content) ? item.content : []).map((part) => asRecord(part)?.text).filter((t) => typeof t === "string").join("");
6765
+ return text12;
6766
+ }
6767
+ var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
6717
6768
  var init_portalLlm = __esm({
6718
6769
  "src/lib/memory/portalLlm.ts"() {
6719
6770
  "use strict";
@@ -6725,6 +6776,13 @@ var init_portalLlm = __esm({
6725
6776
  RESPONSE_FORMAT_OK = /* @__PURE__ */ new Set(["openai", "inclusionai", "deepseek"]);
6726
6777
  RESPONSE_SCHEMA_OK = /* @__PURE__ */ new Set(["openai"]);
6727
6778
  JSON_CONTRACT_REMINDER = "Output ONLY the strict JSON object requested. No prose, no explanation, no markdown.";
6779
+ CHAT_TO_RESPONSES_FIELDS = {
6780
+ max_completion_tokens: "max_output_tokens"
6781
+ };
6782
+ FOREIGN_ENDPOINT_SUFFIX = {
6783
+ chat: "/responses",
6784
+ responses: "/chat/completions"
6785
+ };
6728
6786
  RETRYABLE_HTTP = /* @__PURE__ */ new Set([408, 409, 425, 429]);
6729
6787
  }
6730
6788
  });
@@ -178,14 +178,14 @@ import {
178
178
  updateVaultMemoryOp,
179
179
  useEncryption,
180
180
  vaultMemoryToStored
181
- } from "./chunk-DNSPMVBY.mjs";
181
+ } from "./chunk-PDKKPAXP.mjs";
182
182
  import {
183
183
  PiiRedactor,
184
184
  createStreamingDeAnonymizer,
185
185
  isPiiRedactor,
186
186
  notifyConsolidationFallback,
187
187
  resolvePiiRedactor
188
- } from "./chunk-2XLHV2XW.mjs";
188
+ } from "./chunk-2GNOTRG4.mjs";
189
189
  import {
190
190
  INTERNAL_FLOW_MARKER,
191
191
  callPortalJsonCompletion,
@@ -199,7 +199,7 @@ import {
199
199
  taskTypeHeader,
200
200
  validateEndpointOverride,
201
201
  withInternalFlowMarker
202
- } from "./chunk-O25LUKBK.mjs";
202
+ } from "./chunk-3V3BBJLH.mjs";
203
203
  import {
204
204
  BASE_URL,
205
205
  MCP_R2_DOMAIN,
@@ -7686,7 +7686,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7686
7686
  content: m.content,
7687
7687
  similarity: m.similarity
7688
7688
  }));
7689
- const { consolidateMemory: doConsolidate } = await import("./consolidate-LSDBMQDW.mjs");
7689
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-Y2XWEZRQ.mjs");
7690
7690
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
7691
7691
  if (decision.action === "create") return null;
7692
7692
  if (decision.action === "supersede" && decision.content) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-DNSPMVBY.mjs";
4
- import "./chunk-O25LUKBK.mjs";
3
+ } from "./chunk-PDKKPAXP.mjs";
4
+ import "./chunk-3V3BBJLH.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {
7
7
  recall
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  callPortalJsonCompletion,
3
3
  getLogger
4
- } from "./chunk-7D3RI25K.mjs";
4
+ } from "./chunk-H4G3DLDJ.mjs";
5
5
  import {
6
6
  BASE_URL,
7
7
  __commonJS,
@@ -20923,7 +20923,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
20923
20923
  subQueries = decomp.subQueries;
20924
20924
  }
20925
20925
  }
20926
- const { recall: recall2 } = await import("./recall-VHU372MK.mjs");
20926
+ const { recall: recall2 } = await import("./recall-EODNEKIA.mjs");
20927
20927
  let recallDegraded = [];
20928
20928
  const result = await recall2(
20929
20929
  query,
@@ -57,6 +57,30 @@ function supportsResponseFormat(model, variant = "json_object") {
57
57
  const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
58
58
  return model.split("/").some((seg) => allow.has(seg));
59
59
  }
60
+ var CHAT_TO_RESPONSES_FIELDS = {
61
+ max_completion_tokens: "max_output_tokens"
62
+ };
63
+ function responsesExtra(extra) {
64
+ if (!extra) return {};
65
+ const out = {};
66
+ for (const [key, value] of Object.entries(extra)) {
67
+ const target = CHAT_TO_RESPONSES_FIELDS[key] ?? key;
68
+ if (target !== key && target in extra) continue;
69
+ out[target] = value;
70
+ }
71
+ return out;
72
+ }
73
+ var FOREIGN_ENDPOINT_SUFFIX = {
74
+ chat: "/responses",
75
+ responses: "/chat/completions"
76
+ };
77
+ function assertTransportMatchesEndpoint(transport, endpoint) {
78
+ const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
79
+ if (!endpoint.endsWith(foreign)) return;
80
+ throw new Error(
81
+ `endpointOverride "${endpoint}" is the other transport's endpoint, but transport is "${transport}". The request body is built for the transport, so this sends the wrong shape and 400s without retry.`
82
+ );
83
+ }
60
84
  var RETRYABLE_HTTP = /* @__PURE__ */ new Set([408, 409, 425, 429]);
61
85
  function isRetryableStatus(status) {
62
86
  return status >= 500 || RETRYABLE_HTTP.has(status);
@@ -98,13 +122,14 @@ async function resolvePortalAuthHeaders(auth, tag) {
98
122
  }
99
123
  async function callPortalJsonCompletion(req) {
100
124
  const log = getLogger();
101
- let endpoint = "/api/v1/chat/completions";
125
+ let endpoint = req.transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
102
126
  if (req.endpointOverride !== void 0) {
103
127
  const overrideValidation = validateEndpointOverride(req.endpointOverride);
104
128
  if (!overrideValidation.valid) {
105
129
  throw new Error(overrideValidation.message);
106
130
  }
107
131
  endpoint = overrideValidation.endpoint;
132
+ assertTransportMatchesEndpoint(req.transport ?? "chat", endpoint);
108
133
  }
109
134
  const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
110
135
  const startedAt = Date.now();
@@ -166,8 +191,8 @@ async function attemptPortalJson(req, endpoint) {
166
191
  const authHeaders = await resolvePortalAuthHeaders(req, req.tag);
167
192
  if (authHeaders === null)
168
193
  return { kind: "terminal", code: "auth-unavailable", reason: "auth unavailable (no token)" };
169
- const isAnthropic = req.model.startsWith("anthropic/");
170
- const prefill = isAnthropic ? "{" : "";
194
+ const usesPrefill = req.transport !== "responses" && req.model.startsWith("anthropic/");
195
+ const prefill = usesPrefill ? "{" : "";
171
196
  const messages = [
172
197
  // Every caller of this helper is a first-party BACKGROUND op (fact extraction,
173
198
  // topic sweep, consolidation, classifiers, graph traversal, query
@@ -186,13 +211,34 @@ async function attemptPortalJson(req, endpoint) {
186
211
  const supportsJsonObjectFormat = supportsResponseFormat(req.model);
187
212
  const controller = new AbortController();
188
213
  const timer = setTimeout(() => controller.abort(), timeoutMs);
189
- const requestBody = {
214
+ const requestBody = req.transport === "responses" ? {
215
+ model: req.model,
216
+ // Same system+user pair under the Responses-API field name. No prefill
217
+ // entry to strip: `usesPrefill` is false on this transport, so it was
218
+ // never pushed and the response-side restore is disarmed with it. An
219
+ // earlier version pushed it and sliced it back off here, which left
220
+ // `prefill` truthy and the restore still armed — the fix belonged at
221
+ // the decision, not at the two symptoms.
222
+ input: messages,
223
+ ...req.reasoning && { reasoning: req.reasoning },
224
+ // NO response_format. The Responses API spells structured output
225
+ // differently (`text.format`), and it is unverified against this
226
+ // portal — so this transport relies on the same strict-JSON system
227
+ // prompt plus `extractJsonCandidate` that every response_format-
228
+ // rejecting model already relies on. Verified end to end on dev:
229
+ // luna returns clean parseable JSON here without it. Add the field
230
+ // only with a per-provider check, exactly as RESPONSE_FORMAT_OK was
231
+ // earned.
232
+ ...responsesExtra(req.extra)
233
+ } : {
190
234
  model: req.model,
191
235
  messages,
192
236
  ...supportsJsonObjectFormat && { response_format: { type: "json_object" } },
193
237
  ...req.extra
194
238
  };
195
- if (!supportsJsonObjectFormat) delete requestBody.response_format;
239
+ if (req.transport === "responses" || !supportsJsonObjectFormat) {
240
+ delete requestBody.response_format;
241
+ }
196
242
  let response;
197
243
  try {
198
244
  response = await fetchImpl(`${baseUrl}${endpoint}`, {
@@ -322,13 +368,15 @@ function logPortalUsage(body, tag) {
322
368
  const root = asRecord(body);
323
369
  if (!root) return;
324
370
  const usage = asRecord(root.usage);
325
- const promptTokens = asCount(usage?.prompt_tokens);
326
- const completionTokens = asCount(usage?.completion_tokens);
371
+ const promptTokens = asCount(usage?.prompt_tokens) ?? asCount(usage?.input_tokens);
372
+ const completionTokens = asCount(usage?.completion_tokens) ?? asCount(usage?.output_tokens);
327
373
  if (promptTokens === void 0 && completionTokens === void 0) return;
328
- const cachedTokens = asCount(asRecord(root.portal)?.cached_tokens) ?? asCount(asRecord(usage?.prompt_tokens_details)?.cached_tokens) ?? 0;
374
+ const cachedTokens = asCount(asRecord(root.portal)?.cached_tokens) ?? asCount(asRecord(usage?.prompt_tokens_details)?.cached_tokens) ?? asCount(asRecord(usage?.input_tokens_details)?.cached_tokens) ?? 0;
375
+ const reasoningTokens = asCount(asRecord(usage?.output_tokens_details)?.reasoning_tokens) ?? asCount(asRecord(usage?.completion_tokens_details)?.reasoning_tokens);
329
376
  const parts = [];
330
377
  if (promptTokens !== void 0) parts.push(`prompt=${promptTokens}`);
331
378
  if (completionTokens !== void 0) parts.push(`completion=${completionTokens}`);
379
+ if (reasoningTokens !== void 0) parts.push(`reasoning=${reasoningTokens}`);
332
380
  parts.push(`cached=${cachedTokens}`);
333
381
  getLogger().debug(`[${tag}] usage ${parts.join(" ")}`);
334
382
  } catch {
@@ -336,12 +384,22 @@ function logPortalUsage(body, tag) {
336
384
  }
337
385
  function extractCompletionContent(body) {
338
386
  if (typeof body !== "object" || body === null) return null;
387
+ const responsesText = extractResponsesContent(body);
388
+ if (responsesText !== null) return responsesText;
339
389
  const choices = body.choices;
340
390
  if (!Array.isArray(choices) || choices.length === 0) return null;
341
391
  const first = choices[0];
342
392
  const content = first?.message?.content;
343
393
  return typeof content === "string" ? content : null;
344
394
  }
395
+ function extractResponsesContent(body) {
396
+ const root = asRecord(body);
397
+ if (!root) return null;
398
+ if (typeof root.output_text === "string" && root.output_text !== "") return root.output_text;
399
+ if (!Array.isArray(root.output)) return null;
400
+ const text = root.output.filter((item) => asRecord(item)?.type === "message").flatMap((item) => Array.isArray(item.content) ? item.content : []).map((part) => asRecord(part)?.text).filter((t) => typeof t === "string").join("");
401
+ return text;
402
+ }
345
403
 
346
404
  export {
347
405
  getLogger,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getLogger
3
- } from "./chunk-7D3RI25K.mjs";
3
+ } from "./chunk-H4G3DLDJ.mjs";
4
4
 
5
5
  // src/lib/pii/patterns.ts
6
6
  function luhnCheck(digits) {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  notifyConsolidationFallback,
3
3
  resolvePiiRedactor
4
- } from "./chunk-GP6YY6H5.mjs";
4
+ } from "./chunk-JPLFOSB2.mjs";
5
5
  import {
6
6
  callPortalJsonCompletion
7
- } from "./chunk-7D3RI25K.mjs";
7
+ } from "./chunk-H4G3DLDJ.mjs";
8
8
  import "./chunk-3RPGXXPZ.mjs";
9
9
 
10
10
  // src/lib/memory/consolidate.ts
@@ -20611,6 +20611,23 @@ function supportsResponseFormat(model, variant = "json_object") {
20611
20611
  const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
20612
20612
  return model.split("/").some((seg) => allow.has(seg));
20613
20613
  }
20614
+ function responsesExtra(extra) {
20615
+ if (!extra) return {};
20616
+ const out = {};
20617
+ for (const [key, value] of Object.entries(extra)) {
20618
+ const target = CHAT_TO_RESPONSES_FIELDS[key] ?? key;
20619
+ if (target !== key && target in extra) continue;
20620
+ out[target] = value;
20621
+ }
20622
+ return out;
20623
+ }
20624
+ function assertTransportMatchesEndpoint(transport, endpoint) {
20625
+ const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
20626
+ if (!endpoint.endsWith(foreign)) return;
20627
+ throw new Error(
20628
+ `endpointOverride "${endpoint}" is the other transport's endpoint, but transport is "${transport}". The request body is built for the transport, so this sends the wrong shape and 400s without retry.`
20629
+ );
20630
+ }
20614
20631
  function isRetryableStatus(status) {
20615
20632
  return status >= 500 || RETRYABLE_HTTP.has(status);
20616
20633
  }
@@ -20651,13 +20668,14 @@ async function resolvePortalAuthHeaders(auth, tag) {
20651
20668
  }
20652
20669
  async function callPortalJsonCompletion(req) {
20653
20670
  const log = getLogger();
20654
- let endpoint = "/api/v1/chat/completions";
20671
+ let endpoint = req.transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
20655
20672
  if (req.endpointOverride !== void 0) {
20656
20673
  const overrideValidation = validateEndpointOverride(req.endpointOverride);
20657
20674
  if (!overrideValidation.valid) {
20658
20675
  throw new Error(overrideValidation.message);
20659
20676
  }
20660
20677
  endpoint = overrideValidation.endpoint;
20678
+ assertTransportMatchesEndpoint(req.transport ?? "chat", endpoint);
20661
20679
  }
20662
20680
  const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
20663
20681
  const startedAt = Date.now();
@@ -20719,8 +20737,8 @@ async function attemptPortalJson(req, endpoint) {
20719
20737
  const authHeaders = await resolvePortalAuthHeaders(req, req.tag);
20720
20738
  if (authHeaders === null)
20721
20739
  return { kind: "terminal", code: "auth-unavailable", reason: "auth unavailable (no token)" };
20722
- const isAnthropic = req.model.startsWith("anthropic/");
20723
- const prefill = isAnthropic ? "{" : "";
20740
+ const usesPrefill = req.transport !== "responses" && req.model.startsWith("anthropic/");
20741
+ const prefill = usesPrefill ? "{" : "";
20724
20742
  const messages = [
20725
20743
  // Every caller of this helper is a first-party BACKGROUND op (fact extraction,
20726
20744
  // topic sweep, consolidation, classifiers, graph traversal, query
@@ -20739,13 +20757,34 @@ async function attemptPortalJson(req, endpoint) {
20739
20757
  const supportsJsonObjectFormat = supportsResponseFormat(req.model);
20740
20758
  const controller = new AbortController();
20741
20759
  const timer = setTimeout(() => controller.abort(), timeoutMs);
20742
- const requestBody = {
20760
+ const requestBody = req.transport === "responses" ? {
20761
+ model: req.model,
20762
+ // Same system+user pair under the Responses-API field name. No prefill
20763
+ // entry to strip: `usesPrefill` is false on this transport, so it was
20764
+ // never pushed and the response-side restore is disarmed with it. An
20765
+ // earlier version pushed it and sliced it back off here, which left
20766
+ // `prefill` truthy and the restore still armed — the fix belonged at
20767
+ // the decision, not at the two symptoms.
20768
+ input: messages,
20769
+ ...req.reasoning && { reasoning: req.reasoning },
20770
+ // NO response_format. The Responses API spells structured output
20771
+ // differently (`text.format`), and it is unverified against this
20772
+ // portal — so this transport relies on the same strict-JSON system
20773
+ // prompt plus `extractJsonCandidate` that every response_format-
20774
+ // rejecting model already relies on. Verified end to end on dev:
20775
+ // luna returns clean parseable JSON here without it. Add the field
20776
+ // only with a per-provider check, exactly as RESPONSE_FORMAT_OK was
20777
+ // earned.
20778
+ ...responsesExtra(req.extra)
20779
+ } : {
20743
20780
  model: req.model,
20744
20781
  messages,
20745
20782
  ...supportsJsonObjectFormat && { response_format: { type: "json_object" } },
20746
20783
  ...req.extra
20747
20784
  };
20748
- if (!supportsJsonObjectFormat) delete requestBody.response_format;
20785
+ if (req.transport === "responses" || !supportsJsonObjectFormat) {
20786
+ delete requestBody.response_format;
20787
+ }
20749
20788
  let response;
20750
20789
  try {
20751
20790
  response = await fetchImpl(`${baseUrl}${endpoint}`, {
@@ -20875,13 +20914,15 @@ function logPortalUsage(body, tag) {
20875
20914
  const root = asRecord(body);
20876
20915
  if (!root) return;
20877
20916
  const usage = asRecord(root.usage);
20878
- const promptTokens = asCount(usage?.prompt_tokens);
20879
- const completionTokens = asCount(usage?.completion_tokens);
20917
+ const promptTokens = asCount(usage?.prompt_tokens) ?? asCount(usage?.input_tokens);
20918
+ const completionTokens = asCount(usage?.completion_tokens) ?? asCount(usage?.output_tokens);
20880
20919
  if (promptTokens === void 0 && completionTokens === void 0) return;
20881
- const cachedTokens = asCount(asRecord(root.portal)?.cached_tokens) ?? asCount(asRecord(usage?.prompt_tokens_details)?.cached_tokens) ?? 0;
20920
+ const cachedTokens = asCount(asRecord(root.portal)?.cached_tokens) ?? asCount(asRecord(usage?.prompt_tokens_details)?.cached_tokens) ?? asCount(asRecord(usage?.input_tokens_details)?.cached_tokens) ?? 0;
20921
+ const reasoningTokens = asCount(asRecord(usage?.output_tokens_details)?.reasoning_tokens) ?? asCount(asRecord(usage?.completion_tokens_details)?.reasoning_tokens);
20882
20922
  const parts = [];
20883
20923
  if (promptTokens !== void 0) parts.push(`prompt=${promptTokens}`);
20884
20924
  if (completionTokens !== void 0) parts.push(`completion=${completionTokens}`);
20925
+ if (reasoningTokens !== void 0) parts.push(`reasoning=${reasoningTokens}`);
20885
20926
  parts.push(`cached=${cachedTokens}`);
20886
20927
  getLogger().debug(`[${tag}] usage ${parts.join(" ")}`);
20887
20928
  } catch {
@@ -20889,13 +20930,23 @@ function logPortalUsage(body, tag) {
20889
20930
  }
20890
20931
  function extractCompletionContent(body) {
20891
20932
  if (typeof body !== "object" || body === null) return null;
20933
+ const responsesText = extractResponsesContent(body);
20934
+ if (responsesText !== null) return responsesText;
20892
20935
  const choices = body.choices;
20893
20936
  if (!Array.isArray(choices) || choices.length === 0) return null;
20894
20937
  const first = choices[0];
20895
20938
  const content = first?.message?.content;
20896
20939
  return typeof content === "string" ? content : null;
20897
20940
  }
20898
- var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RETRYABLE_HTTP;
20941
+ function extractResponsesContent(body) {
20942
+ const root = asRecord(body);
20943
+ if (!root) return null;
20944
+ if (typeof root.output_text === "string" && root.output_text !== "") return root.output_text;
20945
+ if (!Array.isArray(root.output)) return null;
20946
+ const text12 = root.output.filter((item) => asRecord(item)?.type === "message").flatMap((item) => Array.isArray(item.content) ? item.content : []).map((part) => asRecord(part)?.text).filter((t) => typeof t === "string").join("");
20947
+ return text12;
20948
+ }
20949
+ var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
20899
20950
  var init_portalLlm = __esm({
20900
20951
  "src/lib/memory/portalLlm.ts"() {
20901
20952
  "use strict";
@@ -20907,6 +20958,13 @@ var init_portalLlm = __esm({
20907
20958
  RESPONSE_FORMAT_OK = /* @__PURE__ */ new Set(["openai", "inclusionai", "deepseek"]);
20908
20959
  RESPONSE_SCHEMA_OK = /* @__PURE__ */ new Set(["openai"]);
20909
20960
  JSON_CONTRACT_REMINDER = "Output ONLY the strict JSON object requested. No prose, no explanation, no markdown.";
20961
+ CHAT_TO_RESPONSES_FIELDS = {
20962
+ max_completion_tokens: "max_output_tokens"
20963
+ };
20964
+ FOREIGN_ENDPOINT_SUFFIX = {
20965
+ chat: "/responses",
20966
+ responses: "/chat/completions"
20967
+ };
20910
20968
  RETRYABLE_HTTP = /* @__PURE__ */ new Set([408, 409, 425, 429]);
20911
20969
  }
20912
20970
  });
@@ -141,12 +141,12 @@ import {
141
141
  updateVaultMemoryOp,
142
142
  upsertMessageOp,
143
143
  vaultMemoryToStored
144
- } from "./chunk-O7TB36P3.mjs";
144
+ } from "./chunk-2QFK4L7Y.mjs";
145
145
  import {
146
146
  createStreamingDeAnonymizer,
147
147
  notifyConsolidationFallback,
148
148
  resolvePiiRedactor
149
- } from "./chunk-GP6YY6H5.mjs";
149
+ } from "./chunk-JPLFOSB2.mjs";
150
150
  import {
151
151
  INTERNAL_FLOW_MARKER,
152
152
  callPortalJsonCompletion,
@@ -157,7 +157,7 @@ import {
157
157
  taskTypeHeader,
158
158
  validateEndpointOverride,
159
159
  withInternalFlowMarker
160
- } from "./chunk-7D3RI25K.mjs";
160
+ } from "./chunk-H4G3DLDJ.mjs";
161
161
  import {
162
162
  BASE_URL,
163
163
  __commonJS,
@@ -5700,7 +5700,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5700
5700
  content: m.content,
5701
5701
  similarity: m.similarity
5702
5702
  }));
5703
- const { consolidateMemory: doConsolidate } = await import("./consolidate-Z2JJP7LW.mjs");
5703
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-CMMDTZ37.mjs");
5704
5704
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
5705
5705
  if (decision.action === "create") return null;
5706
5706
  if (decision.action === "supersede" && decision.content) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-O7TB36P3.mjs";
4
- import "./chunk-7D3RI25K.mjs";
3
+ } from "./chunk-2QFK4L7Y.mjs";
4
+ import "./chunk-H4G3DLDJ.mjs";
5
5
  import "./chunk-3RPGXXPZ.mjs";
6
6
  export {
7
7
  recall
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "6.14.2",
3
+ "version": "6.15.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -160,7 +160,7 @@
160
160
  "homepage": "https://github.com/anuma-ai/sdk#readme",
161
161
  "packageManager": "pnpm@10.23.0",
162
162
  "dependencies": {
163
- "@anuma/portal": "1.0.0-next.20260811055217",
163
+ "@anuma/portal": "1.0.0-next.20260815023541",
164
164
  "@babel/parser": "^7.29.2",
165
165
  "@babel/types": "^7.29.0",
166
166
  "ai": "6.0.202",