@anuma/sdk 6.15.0 → 6.15.1

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.
@@ -70,6 +70,10 @@ function supportsResponseFormat(model, variant = "json_object") {
70
70
  const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
71
71
  return model.split("/").some((seg) => allow.has(seg));
72
72
  }
73
+ var RESPONSES_ONLY_MODEL_PREFIXES = ["gpt-5.6"];
74
+ function requiresResponsesTransport(model) {
75
+ return model.split("/").some((seg) => RESPONSES_ONLY_MODEL_PREFIXES.some((prefix) => seg.startsWith(prefix)));
76
+ }
73
77
  var CHAT_TO_RESPONSES_FIELDS = {
74
78
  max_completion_tokens: "max_output_tokens"
75
79
  };
@@ -424,7 +428,9 @@ export {
424
428
  withInternalFlowMarker,
425
429
  taskTypeHeader,
426
430
  supportsResponseFormat,
431
+ requiresResponsesTransport,
427
432
  resolvePortalAuthHeaders,
428
433
  callPortalJsonCompletion,
429
- extractJsonCandidate
434
+ extractJsonCandidate,
435
+ extractCompletionContent
430
436
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getLogger
3
- } from "./chunk-3V3BBJLH.mjs";
3
+ } from "./chunk-4Z2X4UYQ.mjs";
4
4
 
5
5
  // src/lib/pii/patterns.ts
6
6
  function luhnCheck(digits) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  callPortalJsonCompletion,
3
3
  getLogger
4
- } from "./chunk-3V3BBJLH.mjs";
4
+ } from "./chunk-4Z2X4UYQ.mjs";
5
5
  import {
6
6
  BASE_URL,
7
7
  createClientConfig
@@ -6885,7 +6885,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
6885
6885
  subQueries = decomp.subQueries;
6886
6886
  }
6887
6887
  }
6888
- const { recall: recall2 } = await import("./recall-GKYVPD2B.mjs");
6888
+ const { recall: recall2 } = await import("./recall-FJQTIMYT.mjs");
6889
6889
  let recallDegraded = [];
6890
6890
  const result = await recall2(
6891
6891
  query,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  notifyConsolidationFallback,
3
3
  resolvePiiRedactor
4
- } from "./chunk-2GNOTRG4.mjs";
4
+ } from "./chunk-A2G6TRUK.mjs";
5
5
  import {
6
6
  callPortalJsonCompletion
7
- } from "./chunk-3V3BBJLH.mjs";
7
+ } from "./chunk-4Z2X4UYQ.mjs";
8
8
  import "./chunk-GYKJOWEO.mjs";
9
9
 
10
10
  // src/lib/memory/consolidate.ts
@@ -6145,6 +6145,9 @@ function supportsResponseFormat(model, variant = "json_object") {
6145
6145
  const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
6146
6146
  return model.split("/").some((seg) => allow.has(seg));
6147
6147
  }
6148
+ function requiresResponsesTransport(model) {
6149
+ return model.split("/").some((seg) => RESPONSES_ONLY_MODEL_PREFIXES.some((prefix) => seg.startsWith(prefix)));
6150
+ }
6148
6151
  function responsesExtra(extra) {
6149
6152
  if (!extra) return {};
6150
6153
  const out = {};
@@ -6480,7 +6483,7 @@ function extractResponsesContent(body) {
6480
6483
  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("");
6481
6484
  return text12;
6482
6485
  }
6483
- var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
6486
+ var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RESPONSES_ONLY_MODEL_PREFIXES, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
6484
6487
  var init_portalLlm = __esm({
6485
6488
  "src/lib/memory/portalLlm.ts"() {
6486
6489
  "use strict";
@@ -6492,6 +6495,7 @@ var init_portalLlm = __esm({
6492
6495
  RESPONSE_FORMAT_OK = /* @__PURE__ */ new Set(["openai", "inclusionai", "deepseek"]);
6493
6496
  RESPONSE_SCHEMA_OK = /* @__PURE__ */ new Set(["openai"]);
6494
6497
  JSON_CONTRACT_REMINDER = "Output ONLY the strict JSON object requested. No prose, no explanation, no markdown.";
6498
+ RESPONSES_ONLY_MODEL_PREFIXES = ["gpt-5.6"];
6495
6499
  CHAT_TO_RESPONSES_FIELDS = {
6496
6500
  max_completion_tokens: "max_output_tokens"
6497
6501
  };
@@ -17817,6 +17821,9 @@ var DEFAULT_BASE_URL2 = BASE_URL;
17817
17821
  var DEFAULT_MODEL4 = "anthropic/claude-sonnet-4-6";
17818
17822
  var DEFAULT_MAX_TOKENS = 4096;
17819
17823
  var REQUEST_TIMEOUT_MS = 6e4;
17824
+ var MIN_RETRY_BUDGET_MS = 2e3;
17825
+ var MIN_RESPONSES_OUTPUT_TOKENS = 2048;
17826
+ var SCHEMA_FALLBACK_SKIP_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 408, 409, 413, 425, 429]);
17820
17827
  var DEFAULT_SYSTEM_PROMPT = `You are a personal assistant with access to the user's memory. Answer the user's question using the supplied memories as evidence.
17821
17828
 
17822
17829
  Rules:
@@ -17848,14 +17855,9 @@ ${m.content}`).join("\n\n");
17848
17855
  const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL2;
17849
17856
  const model = options.llmModel ?? DEFAULT_MODEL4;
17850
17857
  const wantsStructured = !!options.responseSchema;
17851
- const sendResponseFormat = wantsStructured && supportsResponseFormat(model, "json_schema");
17858
+ const useResponsesTransport = requiresResponsesTransport(model);
17859
+ const sendResponseFormat = wantsStructured && !useResponsesTransport && supportsResponseFormat(model, "json_schema");
17852
17860
  const basePrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
17853
- const systemPrompt = wantsStructured && !sendResponseFormat ? `${basePrompt}
17854
-
17855
- Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
17856
- ${JSON.stringify(
17857
- options.responseSchema
17858
- )}` : basePrompt;
17859
17861
  const userMessage = [
17860
17862
  `Question:
17861
17863
  ${trimmed}`,
@@ -17865,85 +17867,121 @@ ${evidence}`
17865
17867
  ].join("\n\n");
17866
17868
  const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
17867
17869
  const fetchImpl = options.fetchFn ?? fetch;
17870
+ const buildBody = (useResponseFormat) => {
17871
+ const systemPrompt = wantsStructured && !useResponseFormat ? `${basePrompt}
17872
+
17873
+ Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
17874
+ ${JSON.stringify(
17875
+ options.responseSchema
17876
+ )}` : basePrompt;
17877
+ const messages = [
17878
+ { role: "system", content: systemPrompt },
17879
+ { role: "user", content: userMessage }
17880
+ ];
17881
+ if (useResponsesTransport) {
17882
+ return JSON.stringify({
17883
+ model,
17884
+ // Same system+user pair under the Responses-API field names: `input`
17885
+ // for the turns, `max_output_tokens` for the cap. Sending the
17886
+ // chat-completions spelling here is silently ignored, which caps the
17887
+ // answer at the portal default.
17888
+ input: messages,
17889
+ max_output_tokens: Math.max(maxTokens, MIN_RESPONSES_OUTPUT_TOKENS)
17890
+ });
17891
+ }
17892
+ return JSON.stringify({
17893
+ model,
17894
+ // Modern OpenAI field; the portal reads only `max_completion_tokens`
17895
+ // (the deprecated `max_tokens` is silently ignored → falls back to the
17896
+ // portal's default output cap and truncates the answer).
17897
+ max_completion_tokens: maxTokens,
17898
+ messages,
17899
+ ...useResponseFormat && {
17900
+ response_format: {
17901
+ type: "json_schema",
17902
+ json_schema: { name: "reflect_output", schema: options.responseSchema }
17903
+ }
17904
+ }
17905
+ });
17906
+ };
17868
17907
  const log = getLogger();
17869
17908
  const authHeaders = await resolvePortalAuthHeaders(options, "memory/reflect");
17870
17909
  if (authHeaders === null) return baseResult;
17871
- const controller = new AbortController();
17872
17910
  const deadline = Date.now() + REQUEST_TIMEOUT_MS;
17873
17911
  const remaining = () => Math.max(0, deadline - Date.now());
17874
- const timer = setTimeout(() => controller.abort(), remaining());
17875
- let response;
17876
- try {
17877
- response = await fetchImpl(`${baseUrl}/api/v1/chat/completions`, {
17878
- method: "POST",
17879
- // No task type unless the caller named one — an undeclared task adds no
17880
- // header at all, which is what keeps user-facing reflect() unlabelled.
17881
- headers: {
17882
- ...authHeaders,
17883
- ...taskTypeHeader(options.taskType),
17884
- "Content-Type": "application/json"
17885
- },
17886
- body: JSON.stringify({
17887
- model,
17888
- // Modern OpenAI field; the portal reads only `max_completion_tokens`
17889
- // (the deprecated `max_tokens` is silently ignored → falls back to the
17890
- // portal's default output cap and truncates the answer).
17891
- max_completion_tokens: maxTokens,
17892
- messages: [
17893
- { role: "system", content: systemPrompt },
17894
- { role: "user", content: userMessage }
17895
- ],
17896
- ...sendResponseFormat && {
17897
- response_format: {
17898
- type: "json_schema",
17899
- json_schema: { name: "reflect_output", schema: options.responseSchema }
17900
- }
17901
- }
17902
- }),
17903
- signal: controller.signal
17904
- });
17905
- } catch (err) {
17912
+ const endpoint = useResponsesTransport ? "/api/v1/responses" : "/api/v1/chat/completions";
17913
+ const sendOnce = async (useResponseFormat) => {
17914
+ const controller = new AbortController();
17915
+ const timer = setTimeout(() => controller.abort(), remaining());
17916
+ let response;
17917
+ try {
17918
+ response = await fetchImpl(`${baseUrl}${endpoint}`, {
17919
+ method: "POST",
17920
+ // No task type unless the caller named one — an undeclared task adds no
17921
+ // header at all, which is what keeps user-facing reflect() unlabelled.
17922
+ headers: {
17923
+ ...authHeaders,
17924
+ ...taskTypeHeader(options.taskType),
17925
+ "Content-Type": "application/json"
17926
+ },
17927
+ body: buildBody(useResponseFormat),
17928
+ signal: controller.signal
17929
+ });
17930
+ } catch (err) {
17931
+ clearTimeout(timer);
17932
+ log.warn("[memory/reflect] portal request failed", {
17933
+ err: err instanceof Error ? err.message : String(err),
17934
+ baseUrl
17935
+ });
17936
+ return { kind: "error" };
17937
+ }
17906
17938
  clearTimeout(timer);
17907
- log.warn("[memory/reflect] portal request failed", {
17908
- err: err instanceof Error ? err.message : String(err),
17909
- baseUrl
17939
+ if (!response.ok) {
17940
+ return { kind: "http", status: response.status, statusText: response.statusText };
17941
+ }
17942
+ const bodyTimer = setTimeout(() => controller.abort(), remaining());
17943
+ try {
17944
+ const body = await response.json();
17945
+ clearTimeout(bodyTimer);
17946
+ return { kind: "ok", body };
17947
+ } catch (err) {
17948
+ clearTimeout(bodyTimer);
17949
+ log.warn("[memory/reflect] failed to parse portal response body", {
17950
+ err: err instanceof Error ? err.message : String(err)
17951
+ });
17952
+ return { kind: "error" };
17953
+ }
17954
+ };
17955
+ let attempt = await sendOnce(sendResponseFormat);
17956
+ let schemaFallbackUsed = false;
17957
+ const budgetLeftMs = remaining();
17958
+ if (attempt.kind === "http" && sendResponseFormat && !SCHEMA_FALLBACK_SKIP_STATUSES.has(attempt.status) && budgetLeftMs >= MIN_RETRY_BUDGET_MS) {
17959
+ log.warn("[memory/reflect] response_format json_schema rejected; retrying schema-in-prompt", {
17960
+ status: attempt.status,
17961
+ statusText: attempt.statusText,
17962
+ model,
17963
+ taskType: options.taskType,
17964
+ budgetLeftMs
17910
17965
  });
17911
- return baseResult;
17966
+ schemaFallbackUsed = true;
17967
+ attempt = await sendOnce(false);
17912
17968
  }
17913
- clearTimeout(timer);
17914
- if (!response.ok) {
17969
+ if (attempt.kind === "error") return baseResult;
17970
+ if (attempt.kind === "http") {
17915
17971
  log.warn("[memory/reflect] portal returned non-OK", {
17916
- status: response.status,
17917
- statusText: response.statusText
17918
- });
17919
- return baseResult;
17920
- }
17921
- const bodyTimer = setTimeout(() => controller.abort(), remaining());
17922
- let body;
17923
- try {
17924
- body = await response.json();
17925
- } catch (err) {
17926
- clearTimeout(bodyTimer);
17927
- log.warn("[memory/reflect] failed to parse portal response body", {
17928
- err: err instanceof Error ? err.message : String(err)
17972
+ status: attempt.status,
17973
+ statusText: attempt.statusText,
17974
+ // Distinguishes "the fallback ran and still failed" from "never tried".
17975
+ schemaFallbackUsed
17929
17976
  });
17930
17977
  return baseResult;
17931
17978
  }
17932
- clearTimeout(bodyTimer);
17933
- return parseAnswer(body, baseResult, !!options.responseSchema);
17979
+ return parseAnswer(attempt.body, baseResult, !!options.responseSchema);
17934
17980
  }
17935
17981
  function parseAnswer(body, base, parseSchema) {
17936
17982
  if (typeof body !== "object" || body === null) return base;
17937
17983
  const obj = body;
17938
- const choices = obj.choices;
17939
- let text12 = "";
17940
- if (Array.isArray(choices) && choices.length > 0) {
17941
- const message = choices[0].message;
17942
- if (typeof message === "object" && message !== null) {
17943
- const content = message.content;
17944
- if (typeof content === "string") text12 = content;
17945
- }
17946
- }
17984
+ const text12 = extractCompletionContent(obj) ?? "";
17947
17985
  const usage = obj.usage;
17948
17986
  let structuredOutput;
17949
17987
  if (parseSchema && text12) {
@@ -17955,14 +17993,19 @@ function parseAnswer(body, base, parseSchema) {
17955
17993
  });
17956
17994
  }
17957
17995
  }
17996
+ const promptTokens = usage?.prompt_tokens ?? usage?.input_tokens ?? 0;
17997
+ const completionTokens = usage?.completion_tokens ?? usage?.output_tokens ?? 0;
17958
17998
  return {
17959
17999
  text: text12,
17960
18000
  ...structuredOutput !== void 0 && { structuredOutput },
17961
18001
  basedOn: base.basedOn,
17962
18002
  usage: {
17963
- promptTokens: usage?.prompt_tokens ?? 0,
17964
- completionTokens: usage?.completion_tokens ?? 0,
17965
- totalTokens: usage?.total_tokens ?? 0
18003
+ promptTokens,
18004
+ completionTokens,
18005
+ // Derived when absent: the Responses API reports the two component counts
18006
+ // and does not always send a total, which would otherwise report zero
18007
+ // spend for a call that plainly cost something.
18008
+ totalTokens: usage?.total_tokens ?? promptTokens + completionTokens
17966
18009
  }
17967
18010
  };
17968
18011
  }
@@ -132,7 +132,7 @@ import {
132
132
  upsertMessageOp,
133
133
  useEncryption,
134
134
  vaultMemoryToStored
135
- } from "./chunk-LUSKQQDD.mjs";
135
+ } from "./chunk-TNMPAE3V.mjs";
136
136
  import {
137
137
  PII_PATTERNS,
138
138
  PiiRedactor,
@@ -140,21 +140,23 @@ import {
140
140
  isPiiRedactor,
141
141
  notifyConsolidationFallback,
142
142
  resolvePiiRedactor
143
- } from "./chunk-DIUQLXEH.mjs";
143
+ } from "./chunk-A2G6TRUK.mjs";
144
144
  import {
145
145
  INTERNAL_FLOW_MARKER,
146
146
  callPortalJsonCompletion,
147
147
  consoleLogger,
148
+ extractCompletionContent,
148
149
  extractJsonCandidate,
149
150
  getLogger,
150
151
  noopLogger,
152
+ requiresResponsesTransport,
151
153
  resolvePortalAuthHeaders,
152
154
  setLogger,
153
155
  supportsResponseFormat,
154
156
  taskTypeHeader,
155
157
  validateEndpointOverride,
156
158
  withInternalFlowMarker
157
- } from "./chunk-3V3BBJLH.mjs";
159
+ } from "./chunk-4Z2X4UYQ.mjs";
158
160
  import {
159
161
  BASE_URL,
160
162
  MCP_R2_DOMAIN,
@@ -6868,7 +6870,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6868
6870
  content: m.content,
6869
6871
  similarity: m.similarity
6870
6872
  }));
6871
- const { consolidateMemory: doConsolidate } = await import("./consolidate-GTMXZZ4C.mjs");
6873
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-ZM5JNULQ.mjs");
6872
6874
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
6873
6875
  if (decision.action === "create") return null;
6874
6876
  if (decision.action === "supersede" && decision.content) {
@@ -8092,6 +8094,9 @@ var DEFAULT_BASE_URL = BASE_URL;
8092
8094
  var DEFAULT_MODEL3 = "anthropic/claude-sonnet-4-6";
8093
8095
  var DEFAULT_MAX_TOKENS = 4096;
8094
8096
  var REQUEST_TIMEOUT_MS = 6e4;
8097
+ var MIN_RETRY_BUDGET_MS = 2e3;
8098
+ var MIN_RESPONSES_OUTPUT_TOKENS = 2048;
8099
+ var SCHEMA_FALLBACK_SKIP_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 408, 409, 413, 425, 429]);
8095
8100
  var DEFAULT_SYSTEM_PROMPT = `You are a personal assistant with access to the user's memory. Answer the user's question using the supplied memories as evidence.
8096
8101
 
8097
8102
  Rules:
@@ -8123,14 +8128,9 @@ ${m.content}`).join("\n\n");
8123
8128
  const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
8124
8129
  const model = options.llmModel ?? DEFAULT_MODEL3;
8125
8130
  const wantsStructured = !!options.responseSchema;
8126
- const sendResponseFormat = wantsStructured && supportsResponseFormat(model, "json_schema");
8131
+ const useResponsesTransport = requiresResponsesTransport(model);
8132
+ const sendResponseFormat = wantsStructured && !useResponsesTransport && supportsResponseFormat(model, "json_schema");
8127
8133
  const basePrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
8128
- const systemPrompt = wantsStructured && !sendResponseFormat ? `${basePrompt}
8129
-
8130
- Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
8131
- ${JSON.stringify(
8132
- options.responseSchema
8133
- )}` : basePrompt;
8134
8134
  const userMessage = [
8135
8135
  `Question:
8136
8136
  ${trimmed}`,
@@ -8140,85 +8140,121 @@ ${evidence}`
8140
8140
  ].join("\n\n");
8141
8141
  const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
8142
8142
  const fetchImpl = options.fetchFn ?? fetch;
8143
+ const buildBody = (useResponseFormat) => {
8144
+ const systemPrompt = wantsStructured && !useResponseFormat ? `${basePrompt}
8145
+
8146
+ Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
8147
+ ${JSON.stringify(
8148
+ options.responseSchema
8149
+ )}` : basePrompt;
8150
+ const messages = [
8151
+ { role: "system", content: systemPrompt },
8152
+ { role: "user", content: userMessage }
8153
+ ];
8154
+ if (useResponsesTransport) {
8155
+ return JSON.stringify({
8156
+ model,
8157
+ // Same system+user pair under the Responses-API field names: `input`
8158
+ // for the turns, `max_output_tokens` for the cap. Sending the
8159
+ // chat-completions spelling here is silently ignored, which caps the
8160
+ // answer at the portal default.
8161
+ input: messages,
8162
+ max_output_tokens: Math.max(maxTokens, MIN_RESPONSES_OUTPUT_TOKENS)
8163
+ });
8164
+ }
8165
+ return JSON.stringify({
8166
+ model,
8167
+ // Modern OpenAI field; the portal reads only `max_completion_tokens`
8168
+ // (the deprecated `max_tokens` is silently ignored → falls back to the
8169
+ // portal's default output cap and truncates the answer).
8170
+ max_completion_tokens: maxTokens,
8171
+ messages,
8172
+ ...useResponseFormat && {
8173
+ response_format: {
8174
+ type: "json_schema",
8175
+ json_schema: { name: "reflect_output", schema: options.responseSchema }
8176
+ }
8177
+ }
8178
+ });
8179
+ };
8143
8180
  const log = getLogger();
8144
8181
  const authHeaders = await resolvePortalAuthHeaders(options, "memory/reflect");
8145
8182
  if (authHeaders === null) return baseResult;
8146
- const controller = new AbortController();
8147
8183
  const deadline = Date.now() + REQUEST_TIMEOUT_MS;
8148
8184
  const remaining = () => Math.max(0, deadline - Date.now());
8149
- const timer = setTimeout(() => controller.abort(), remaining());
8150
- let response;
8151
- try {
8152
- response = await fetchImpl(`${baseUrl}/api/v1/chat/completions`, {
8153
- method: "POST",
8154
- // No task type unless the caller named one — an undeclared task adds no
8155
- // header at all, which is what keeps user-facing reflect() unlabelled.
8156
- headers: {
8157
- ...authHeaders,
8158
- ...taskTypeHeader(options.taskType),
8159
- "Content-Type": "application/json"
8160
- },
8161
- body: JSON.stringify({
8162
- model,
8163
- // Modern OpenAI field; the portal reads only `max_completion_tokens`
8164
- // (the deprecated `max_tokens` is silently ignored → falls back to the
8165
- // portal's default output cap and truncates the answer).
8166
- max_completion_tokens: maxTokens,
8167
- messages: [
8168
- { role: "system", content: systemPrompt },
8169
- { role: "user", content: userMessage }
8170
- ],
8171
- ...sendResponseFormat && {
8172
- response_format: {
8173
- type: "json_schema",
8174
- json_schema: { name: "reflect_output", schema: options.responseSchema }
8175
- }
8176
- }
8177
- }),
8178
- signal: controller.signal
8179
- });
8180
- } catch (err) {
8185
+ const endpoint = useResponsesTransport ? "/api/v1/responses" : "/api/v1/chat/completions";
8186
+ const sendOnce = async (useResponseFormat) => {
8187
+ const controller = new AbortController();
8188
+ const timer = setTimeout(() => controller.abort(), remaining());
8189
+ let response;
8190
+ try {
8191
+ response = await fetchImpl(`${baseUrl}${endpoint}`, {
8192
+ method: "POST",
8193
+ // No task type unless the caller named one — an undeclared task adds no
8194
+ // header at all, which is what keeps user-facing reflect() unlabelled.
8195
+ headers: {
8196
+ ...authHeaders,
8197
+ ...taskTypeHeader(options.taskType),
8198
+ "Content-Type": "application/json"
8199
+ },
8200
+ body: buildBody(useResponseFormat),
8201
+ signal: controller.signal
8202
+ });
8203
+ } catch (err) {
8204
+ clearTimeout(timer);
8205
+ log.warn("[memory/reflect] portal request failed", {
8206
+ err: err instanceof Error ? err.message : String(err),
8207
+ baseUrl
8208
+ });
8209
+ return { kind: "error" };
8210
+ }
8181
8211
  clearTimeout(timer);
8182
- log.warn("[memory/reflect] portal request failed", {
8183
- err: err instanceof Error ? err.message : String(err),
8184
- baseUrl
8212
+ if (!response.ok) {
8213
+ return { kind: "http", status: response.status, statusText: response.statusText };
8214
+ }
8215
+ const bodyTimer = setTimeout(() => controller.abort(), remaining());
8216
+ try {
8217
+ const body = await response.json();
8218
+ clearTimeout(bodyTimer);
8219
+ return { kind: "ok", body };
8220
+ } catch (err) {
8221
+ clearTimeout(bodyTimer);
8222
+ log.warn("[memory/reflect] failed to parse portal response body", {
8223
+ err: err instanceof Error ? err.message : String(err)
8224
+ });
8225
+ return { kind: "error" };
8226
+ }
8227
+ };
8228
+ let attempt = await sendOnce(sendResponseFormat);
8229
+ let schemaFallbackUsed = false;
8230
+ const budgetLeftMs = remaining();
8231
+ if (attempt.kind === "http" && sendResponseFormat && !SCHEMA_FALLBACK_SKIP_STATUSES.has(attempt.status) && budgetLeftMs >= MIN_RETRY_BUDGET_MS) {
8232
+ log.warn("[memory/reflect] response_format json_schema rejected; retrying schema-in-prompt", {
8233
+ status: attempt.status,
8234
+ statusText: attempt.statusText,
8235
+ model,
8236
+ taskType: options.taskType,
8237
+ budgetLeftMs
8185
8238
  });
8186
- return baseResult;
8239
+ schemaFallbackUsed = true;
8240
+ attempt = await sendOnce(false);
8187
8241
  }
8188
- clearTimeout(timer);
8189
- if (!response.ok) {
8242
+ if (attempt.kind === "error") return baseResult;
8243
+ if (attempt.kind === "http") {
8190
8244
  log.warn("[memory/reflect] portal returned non-OK", {
8191
- status: response.status,
8192
- statusText: response.statusText
8245
+ status: attempt.status,
8246
+ statusText: attempt.statusText,
8247
+ // Distinguishes "the fallback ran and still failed" from "never tried".
8248
+ schemaFallbackUsed
8193
8249
  });
8194
8250
  return baseResult;
8195
8251
  }
8196
- const bodyTimer = setTimeout(() => controller.abort(), remaining());
8197
- let body;
8198
- try {
8199
- body = await response.json();
8200
- } catch (err) {
8201
- clearTimeout(bodyTimer);
8202
- log.warn("[memory/reflect] failed to parse portal response body", {
8203
- err: err instanceof Error ? err.message : String(err)
8204
- });
8205
- return baseResult;
8206
- }
8207
- clearTimeout(bodyTimer);
8208
- return parseAnswer(body, baseResult, !!options.responseSchema);
8252
+ return parseAnswer(attempt.body, baseResult, !!options.responseSchema);
8209
8253
  }
8210
8254
  function parseAnswer(body, base, parseSchema) {
8211
8255
  if (typeof body !== "object" || body === null) return base;
8212
8256
  const obj = body;
8213
- const choices = obj.choices;
8214
- let text12 = "";
8215
- if (Array.isArray(choices) && choices.length > 0) {
8216
- const message = choices[0].message;
8217
- if (typeof message === "object" && message !== null) {
8218
- const content = message.content;
8219
- if (typeof content === "string") text12 = content;
8220
- }
8221
- }
8257
+ const text12 = extractCompletionContent(obj) ?? "";
8222
8258
  const usage = obj.usage;
8223
8259
  let structuredOutput;
8224
8260
  if (parseSchema && text12) {
@@ -8230,14 +8266,19 @@ function parseAnswer(body, base, parseSchema) {
8230
8266
  });
8231
8267
  }
8232
8268
  }
8269
+ const promptTokens = usage?.prompt_tokens ?? usage?.input_tokens ?? 0;
8270
+ const completionTokens = usage?.completion_tokens ?? usage?.output_tokens ?? 0;
8233
8271
  return {
8234
8272
  text: text12,
8235
8273
  ...structuredOutput !== void 0 && { structuredOutput },
8236
8274
  basedOn: base.basedOn,
8237
8275
  usage: {
8238
- promptTokens: usage?.prompt_tokens ?? 0,
8239
- completionTokens: usage?.completion_tokens ?? 0,
8240
- totalTokens: usage?.total_tokens ?? 0
8276
+ promptTokens,
8277
+ completionTokens,
8278
+ // Derived when absent: the Responses API reports the two component counts
8279
+ // and does not always send a total, which would otherwise report zero
8280
+ // spend for a call that plainly cost something.
8281
+ totalTokens: usage?.total_tokens ?? promptTokens + completionTokens
8241
8282
  }
8242
8283
  };
8243
8284
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-LUSKQQDD.mjs";
4
- import "./chunk-3V3BBJLH.mjs";
3
+ } from "./chunk-TNMPAE3V.mjs";
4
+ import "./chunk-4Z2X4UYQ.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {
7
7
  recall
@@ -70,6 +70,10 @@ function supportsResponseFormat(model, variant = "json_object") {
70
70
  const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
71
71
  return model.split("/").some((seg) => allow.has(seg));
72
72
  }
73
+ var RESPONSES_ONLY_MODEL_PREFIXES = ["gpt-5.6"];
74
+ function requiresResponsesTransport(model) {
75
+ return model.split("/").some((seg) => RESPONSES_ONLY_MODEL_PREFIXES.some((prefix) => seg.startsWith(prefix)));
76
+ }
73
77
  var CHAT_TO_RESPONSES_FIELDS = {
74
78
  max_completion_tokens: "max_output_tokens"
75
79
  };
@@ -424,7 +428,9 @@ export {
424
428
  withInternalFlowMarker,
425
429
  taskTypeHeader,
426
430
  supportsResponseFormat,
431
+ requiresResponsesTransport,
427
432
  resolvePortalAuthHeaders,
428
433
  callPortalJsonCompletion,
429
- extractJsonCandidate
434
+ extractJsonCandidate,
435
+ extractCompletionContent
430
436
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getLogger
3
- } from "./chunk-3V3BBJLH.mjs";
3
+ } from "./chunk-4Z2X4UYQ.mjs";
4
4
 
5
5
  // src/lib/pii/patterns.ts
6
6
  function luhnCheck(digits) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  callPortalJsonCompletion,
3
3
  getLogger
4
- } from "./chunk-3V3BBJLH.mjs";
4
+ } from "./chunk-4Z2X4UYQ.mjs";
5
5
  import {
6
6
  BASE_URL,
7
7
  createClientConfig
@@ -7169,7 +7169,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
7169
7169
  subQueries = decomp.subQueries;
7170
7170
  }
7171
7171
  }
7172
- const { recall: recall2 } = await import("./recall-5HNAFHLL.mjs");
7172
+ const { recall: recall2 } = await import("./recall-UVVZGRVF.mjs");
7173
7173
  let recallDegraded = [];
7174
7174
  const result = await recall2(
7175
7175
  query,