@prestyj/ai 5.9.0 → 5.11.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
@@ -40,7 +40,7 @@ Tool parameters are Zod schemas. Converted to JSON Schema at the provider bounda
40
40
 
41
41
  | Provider | Models | Notes |
42
42
  |---|---|---|
43
- | `anthropic` | Claude Opus 4.8, Sonnet 5, Haiku 4.5 | Extended thinking, prompt caching, server-side compaction |
43
+ | `anthropic` | Claude Opus 5, Sonnet 5, Haiku 4.5 | Extended thinking, prompt caching, server-side compaction |
44
44
  | `openai` | GPT-4.1, o3, o4-mini | Supports OAuth (codex endpoint) and API keys |
45
45
  | `glm` | GLM-5.1, GLM-4.7 | Z.AI platform, OpenAI-compatible |
46
46
  | `moonshot` | Kimi K3, Kimi K2.7 Code | Moonshot platform, OpenAI-compatible |
package/dist/index.cjs CHANGED
@@ -40,8 +40,10 @@ __export(index_exports, {
40
40
  environmentSecrets: () => environmentSecrets,
41
41
  formatError: () => formatError,
42
42
  formatErrorForDisplay: () => formatErrorForDisplay,
43
+ hasLoneSurrogate: () => hasLoneSurrogate,
43
44
  isHardBillingMessage: () => isHardBillingMessage,
44
45
  isUsageLimitError: () => isUsageLimitError,
46
+ localWireModelId: () => localWireModelId,
45
47
  palsuAssistantMessage: () => palsuAssistantMessage,
46
48
  palsuText: () => palsuText,
47
49
  palsuThinking: () => palsuThinking,
@@ -51,10 +53,14 @@ __export(index_exports, {
51
53
  redactText: () => redactText,
52
54
  redactValue: () => redactValue,
53
55
  registerPalsuProvider: () => registerPalsuProvider,
56
+ sanitizeMessagesForWire: () => sanitizeMessagesForWire,
54
57
  setProviderDiagnostic: () => setProviderDiagnostic,
58
+ sliceHead: () => sliceHead,
59
+ sliceTail: () => sliceTail,
55
60
  stream: () => stream,
56
61
  toAnthropicMessages: () => toAnthropicMessages,
57
- toOpenAIMessages: () => toOpenAIMessages
62
+ toOpenAIMessages: () => toOpenAIMessages,
63
+ toWellFormedText: () => toWellFormedText
58
64
  });
59
65
  module.exports = __toCommonJS(index_exports);
60
66
 
@@ -561,6 +567,39 @@ function normalizeRootForAnthropic(schema) {
561
567
  return out;
562
568
  }
563
569
 
570
+ // src/providers/reasoning-field.ts
571
+ var REASONING_FIELD_ALIASES = [
572
+ "reasoning_content",
573
+ "reasoning",
574
+ "reasoning_text"
575
+ ];
576
+ var DEFAULT_REASONING_FIELD = REASONING_FIELD_ALIASES[0];
577
+ function readReasoning(obj) {
578
+ if (!obj) return void 0;
579
+ for (const field of REASONING_FIELD_ALIASES) {
580
+ const value = obj[field];
581
+ if (typeof value === "string" && value) return { field, text: value };
582
+ }
583
+ return void 0;
584
+ }
585
+ function reasoningFieldKey(provider, baseUrl, model) {
586
+ return `${provider}|${baseUrl ?? ""}|${model}`;
587
+ }
588
+ var MAX_REMEMBERED_ENDPOINTS = 64;
589
+ var detectedFields = /* @__PURE__ */ new Map();
590
+ function rememberReasoningField(key, field) {
591
+ if (detectedFields.get(key) === field) return;
592
+ detectedFields.set(key, field);
593
+ while (detectedFields.size > MAX_REMEMBERED_ENDPOINTS) {
594
+ const oldest = detectedFields.keys().next();
595
+ if (oldest.done) break;
596
+ detectedFields.delete(oldest.value);
597
+ }
598
+ }
599
+ function getReasoningField(key) {
600
+ return detectedFields.get(key) ?? DEFAULT_REASONING_FIELD;
601
+ }
602
+
564
603
  // src/providers/transform.ts
565
604
  function hasValidThinkingSignature(part) {
566
605
  return typeof part.signature === "string" && part.signature.trim().length > 0;
@@ -945,12 +984,12 @@ function toAnthropicToolChoice(choice) {
945
984
  return { type: "tool", name: choice.name };
946
985
  }
947
986
  function isAdaptiveThinkingModel(model) {
948
- return /opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|fable-5|mythos-5/.test(model);
987
+ return /opus-5|opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|fable-5|mythos-5/.test(model);
949
988
  }
950
989
  function toAnthropicThinking(level, maxTokens, model) {
951
990
  if (isAdaptiveThinkingModel(model)) {
952
991
  let effort = level;
953
- if (effort === "xhigh" && !/opus-4-8|opus-4-7/.test(model)) {
992
+ if (effort === "xhigh" && !/opus-5|opus-4-8|opus-4-7/.test(model)) {
954
993
  effort = "high";
955
994
  }
956
995
  return {
@@ -981,6 +1020,7 @@ function remapToolCallId(id, idMap) {
981
1020
  return mapped;
982
1021
  }
983
1022
  function toOpenAIMessages(messages, options) {
1023
+ const reasoningField = options?.reasoningField || DEFAULT_REASONING_FIELD;
984
1024
  const out = [];
985
1025
  const idMap = /* @__PURE__ */ new Map();
986
1026
  const mergeToolResultText = options?.provider === "glm";
@@ -1047,9 +1087,9 @@ function toOpenAIMessages(messages, options) {
1047
1087
  ...hasToolCalls ? { tool_calls: toolCalls } : {}
1048
1088
  };
1049
1089
  if (thinkingParts) {
1050
- assistantMsg.reasoning_content = thinkingParts;
1090
+ assistantMsg[reasoningField] = thinkingParts;
1051
1091
  } else if (options?.thinking && hasToolCalls && options.provider !== "glm") {
1052
- assistantMsg.reasoning_content = " ";
1092
+ assistantMsg[reasoningField] = " ";
1053
1093
  }
1054
1094
  out.push(assistantMsg);
1055
1095
  continue;
@@ -1127,6 +1167,10 @@ function toOpenAIToolChoice(choice) {
1127
1167
  if (choice === "required") return "required";
1128
1168
  return { type: "function", function: { name: choice.name } };
1129
1169
  }
1170
+ function toLocalReasoningEffort(level) {
1171
+ if (level === "max" || level === "ultra" || level === "xhigh") return "max";
1172
+ return level;
1173
+ }
1130
1174
  function toOpenAIReasoningEffort(level, model) {
1131
1175
  const effort = level === "max" || level === "ultra" ? "xhigh" : level;
1132
1176
  if (model.startsWith("fugu") && (effort === "low" || effort === "medium")) {
@@ -1923,7 +1967,9 @@ function streamOpenAI(options) {
1923
1967
  async function* runStream2(options) {
1924
1968
  const providerName = options.provider ?? "openai";
1925
1969
  const useStreaming = options.streaming !== false;
1970
+ const endpointKey = reasoningFieldKey(providerName, options.baseUrl, options.model);
1926
1971
  const client = createClient2(options);
1972
+ const isLocal = options.provider === "local";
1927
1973
  const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
1928
1974
  const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
1929
1975
  const k3Effort = options.thinking ? toKimiK3Effort(options.thinking) : void 0;
@@ -1946,7 +1992,8 @@ async function* runStream2(options) {
1946
1992
  // disabled K3 must NOT carry placeholder reasoning_content (mirrors the
1947
1993
  // official CLI: reasoning is preserved only while thinking is enabled).
1948
1994
  thinking: isKimiK27 || !!options.thinking,
1949
- supportsImages: options.supportsImages
1995
+ supportsImages: options.supportsImages,
1996
+ reasoningField: getReasoningField(endpointKey)
1950
1997
  });
1951
1998
  const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
1952
1999
  const effectiveTemp = options.temperature ?? defaultTemp;
@@ -1958,7 +2005,7 @@ async function* runStream2(options) {
1958
2005
  ...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
1959
2006
  ...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
1960
2007
  ...options.stop ? { stop: options.stop } : {},
1961
- ...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
2008
+ ...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 && !isLocal ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
1962
2009
  ...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
1963
2010
  ...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
1964
2011
  ...useStreaming ? { stream_options: { include_usage: true } } : {}
@@ -1972,6 +2019,11 @@ async function* runStream2(options) {
1972
2019
  paramsAny.prompt_cache_retention = "24h";
1973
2020
  }
1974
2021
  }
2022
+ if (isLocal && options.thinking) {
2023
+ params.reasoning_effort = toLocalReasoningEffort(
2024
+ options.thinking
2025
+ );
2026
+ }
1975
2027
  if (options.provider === "openai" && options.serviceTier) {
1976
2028
  params.service_tier = options.serviceTier;
1977
2029
  }
@@ -2008,8 +2060,8 @@ async function* runStream2(options) {
2008
2060
  const completion = await client.chat.completions.create(params, {
2009
2061
  signal: options.signal ?? void 0
2010
2062
  });
2011
- yield* synthesizeEventsFromCompletion(completion, !!options.thinking);
2012
- return completionToResponse(completion);
2063
+ yield* synthesizeEventsFromCompletion(completion, !!options.thinking, endpointKey);
2064
+ return completionToResponse(completion, endpointKey);
2013
2065
  } catch (err) {
2014
2066
  throw toError2(err, providerName);
2015
2067
  }
@@ -2044,11 +2096,12 @@ async function* runStream2(options) {
2044
2096
  finishReason = choice.finish_reason;
2045
2097
  }
2046
2098
  const delta = choice.delta;
2047
- const reasoningContent = delta.reasoning_content;
2048
- if (typeof reasoningContent === "string" && reasoningContent) {
2049
- thinkingAccum += reasoningContent;
2099
+ const reasoning = readReasoning(delta);
2100
+ if (reasoning) {
2101
+ rememberReasoningField(endpointKey, reasoning.field);
2102
+ thinkingAccum += reasoning.text;
2050
2103
  if (options.thinking) {
2051
- yield { type: "thinking_delta", text: reasoningContent };
2104
+ yield { type: "thinking_delta", text: reasoning.text };
2052
2105
  }
2053
2106
  }
2054
2107
  if (delta.content) {
@@ -2133,16 +2186,17 @@ async function* runStream2(options) {
2133
2186
  yield { type: "done", stopReason };
2134
2187
  return response;
2135
2188
  }
2136
- function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
2189
+ function* synthesizeEventsFromCompletion(completion, thinkingEnabled, endpointKey) {
2137
2190
  const choice = completion.choices?.[0];
2138
2191
  if (!choice) {
2139
2192
  yield { type: "done", stopReason: normalizeOpenAIStopReason(null) };
2140
2193
  return;
2141
2194
  }
2142
2195
  const msg = choice.message;
2143
- const reasoning = msg.reasoning_content;
2144
- if (typeof reasoning === "string" && reasoning && thinkingEnabled) {
2145
- yield { type: "thinking_delta", text: reasoning };
2196
+ const reasoning = readReasoning(msg);
2197
+ if (reasoning) {
2198
+ rememberReasoningField(endpointKey, reasoning.field);
2199
+ if (thinkingEnabled) yield { type: "thinking_delta", text: reasoning.text };
2146
2200
  }
2147
2201
  if (typeof msg.content === "string" && msg.content) {
2148
2202
  yield { type: "text_delta", text: msg.content };
@@ -2170,15 +2224,16 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
2170
2224
  }
2171
2225
  yield { type: "done", stopReason: normalizeOpenAIStopReason(choice.finish_reason ?? null) };
2172
2226
  }
2173
- function completionToResponse(completion) {
2227
+ function completionToResponse(completion, endpointKey) {
2174
2228
  const choice = completion.choices?.[0];
2175
2229
  const contentParts = [];
2176
2230
  let textAccum = "";
2177
2231
  if (choice) {
2178
2232
  const msg = choice.message;
2179
- const reasoning = msg.reasoning_content;
2180
- if (typeof reasoning === "string" && reasoning) {
2181
- contentParts.push({ type: "thinking", text: reasoning });
2233
+ const reasoning = readReasoning(msg);
2234
+ if (reasoning) {
2235
+ rememberReasoningField(endpointKey, reasoning.field);
2236
+ contentParts.push({ type: "thinking", text: reasoning.text });
2182
2237
  }
2183
2238
  if (typeof msg.content === "string" && msg.content) {
2184
2239
  textAccum = msg.content;
@@ -3330,14 +3385,16 @@ async function* runStream4(options) {
3330
3385
  let thinkingAccum = "";
3331
3386
  let stopReason = "end_turn";
3332
3387
  let inputTokens = 0;
3333
- let outputTokens = 0;
3388
+ let candidateTokens = 0;
3389
+ let reasoningTokens = 0;
3334
3390
  let cacheRead = 0;
3335
3391
  let toolIndex = 0;
3336
3392
  const handleResponse = function* (chunk) {
3337
3393
  const usage = usageFromResponse(chunk);
3338
3394
  if (usage) {
3339
3395
  inputTokens = usage.promptTokenCount ?? inputTokens;
3340
- outputTokens = usage.candidatesTokenCount ?? outputTokens;
3396
+ candidateTokens = usage.candidatesTokenCount ?? candidateTokens;
3397
+ reasoningTokens = usage.thoughtsTokenCount ?? reasoningTokens;
3341
3398
  cacheRead = usage.cachedContentTokenCount ?? cacheRead;
3342
3399
  }
3343
3400
  const reason = finishReasonFromResponse(chunk);
@@ -3393,6 +3450,7 @@ async function* runStream4(options) {
3393
3450
  }
3394
3451
  if (pendingToolCalls.length > 0) stopReason = "tool_use";
3395
3452
  const adjustedInputTokens = Math.max(0, inputTokens - cacheRead);
3453
+ const outputTokens = candidateTokens + reasoningTokens;
3396
3454
  const streamResponse = {
3397
3455
  message: {
3398
3456
  role: "assistant",
@@ -3402,6 +3460,7 @@ async function* runStream4(options) {
3402
3460
  usage: {
3403
3461
  inputTokens: adjustedInputTokens,
3404
3462
  outputTokens,
3463
+ ...reasoningTokens > 0 ? { reasoningTokens } : {},
3405
3464
  ...cacheRead > 0 ? { cacheRead } : {}
3406
3465
  }
3407
3466
  };
@@ -3450,6 +3509,140 @@ var ProviderRegistryImpl = class {
3450
3509
  };
3451
3510
  var providerRegistry = new ProviderRegistryImpl();
3452
3511
 
3512
+ // src/utils/well-formed.ts
3513
+ var LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
3514
+ var LONE_SURROGATE_GLOBAL = new RegExp(LONE_SURROGATE, "g");
3515
+ var REPLACEMENT = "\uFFFD";
3516
+ function hasLoneSurrogate(text) {
3517
+ const isWellFormed = text.isWellFormed;
3518
+ if (typeof isWellFormed === "function") return !isWellFormed.call(text);
3519
+ return LONE_SURROGATE.test(text);
3520
+ }
3521
+ function toWellFormedText(text) {
3522
+ if (!hasLoneSurrogate(text)) return text;
3523
+ const toWellFormed = text.toWellFormed;
3524
+ if (typeof toWellFormed === "function") return toWellFormed.call(text);
3525
+ return text.replace(LONE_SURROGATE_GLOBAL, REPLACEMENT);
3526
+ }
3527
+ function isHighSurrogate(code) {
3528
+ return code !== void 0 && code >= 55296 && code <= 56319;
3529
+ }
3530
+ function isLowSurrogate(code) {
3531
+ return code !== void 0 && code >= 56320 && code <= 57343;
3532
+ }
3533
+ function sliceHead(text, chars) {
3534
+ if (chars <= 0) return "";
3535
+ if (chars >= text.length) return text;
3536
+ const end = isHighSurrogate(text.charCodeAt(chars - 1)) ? chars - 1 : chars;
3537
+ return text.slice(0, end);
3538
+ }
3539
+ function sliceTail(text, chars) {
3540
+ if (chars <= 0) return "";
3541
+ if (chars >= text.length) return text;
3542
+ const start = text.length - chars;
3543
+ return text.slice(isLowSurrogate(text.charCodeAt(start)) ? start + 1 : start);
3544
+ }
3545
+ function sanitizeJsonValue(value) {
3546
+ if (typeof value === "string") return toWellFormedText(value);
3547
+ if (Array.isArray(value)) {
3548
+ let changed = false;
3549
+ const next = value.map((item) => {
3550
+ const sanitized = sanitizeJsonValue(item);
3551
+ if (sanitized !== item) changed = true;
3552
+ return sanitized;
3553
+ });
3554
+ return changed ? next : value;
3555
+ }
3556
+ if (value !== null && typeof value === "object") {
3557
+ let changed = false;
3558
+ const next = {};
3559
+ for (const [key, item] of Object.entries(value)) {
3560
+ const sanitizedKey = toWellFormedText(key);
3561
+ const sanitized = sanitizeJsonValue(item);
3562
+ if (sanitizedKey !== key || sanitized !== item) changed = true;
3563
+ next[sanitizedKey] = sanitized;
3564
+ }
3565
+ return changed ? next : value;
3566
+ }
3567
+ return value;
3568
+ }
3569
+ function sanitizeRecord(value) {
3570
+ return sanitizeJsonValue(value);
3571
+ }
3572
+ function sanitizePart(part) {
3573
+ switch (part.type) {
3574
+ case "text":
3575
+ case "thinking": {
3576
+ const text = toWellFormedText(part.text);
3577
+ return text === part.text ? part : { ...part, text };
3578
+ }
3579
+ case "tool_call": {
3580
+ const args = sanitizeRecord(part.args);
3581
+ return args === part.args ? part : { ...part, args };
3582
+ }
3583
+ case "server_tool_call": {
3584
+ const input = sanitizeJsonValue(part.input);
3585
+ return input === part.input ? part : { ...part, input };
3586
+ }
3587
+ case "server_tool_result": {
3588
+ const data = sanitizeJsonValue(part.data);
3589
+ return data === part.data ? part : { ...part, data };
3590
+ }
3591
+ case "raw": {
3592
+ const data = sanitizeRecord(part.data);
3593
+ return data === part.data ? part : { ...part, data };
3594
+ }
3595
+ default:
3596
+ return part;
3597
+ }
3598
+ }
3599
+ function sanitizeParts(parts) {
3600
+ let changed = false;
3601
+ const next = parts.map((part) => {
3602
+ const sanitized = sanitizePart(part);
3603
+ if (sanitized !== part) changed = true;
3604
+ return sanitized;
3605
+ });
3606
+ return changed ? next : parts;
3607
+ }
3608
+ function sanitizeToolResultContent(content) {
3609
+ if (typeof content === "string") return toWellFormedText(content);
3610
+ return sanitizeParts(content);
3611
+ }
3612
+ function sanitizeToolResults(results) {
3613
+ let changed = false;
3614
+ const next = results.map((result) => {
3615
+ const content = sanitizeToolResultContent(result.content);
3616
+ if (content === result.content) return result;
3617
+ changed = true;
3618
+ return { ...result, content };
3619
+ });
3620
+ return changed ? next : results;
3621
+ }
3622
+ function sanitizeMessage(message) {
3623
+ if (message.role === "tool") {
3624
+ const content2 = sanitizeToolResults(message.content);
3625
+ return content2 === message.content ? message : { ...message, content: content2 };
3626
+ }
3627
+ if (typeof message.content === "string") {
3628
+ const content2 = toWellFormedText(message.content);
3629
+ return content2 === message.content ? message : { ...message, content: content2 };
3630
+ }
3631
+ const content = sanitizeParts(message.content);
3632
+ return content === message.content ? message : { ...message, content };
3633
+ }
3634
+ function sanitizeMessagesForWire(messages) {
3635
+ let sanitized;
3636
+ for (let index = 0; index < messages.length; index++) {
3637
+ const message = messages[index];
3638
+ const next = sanitizeMessage(message);
3639
+ if (next === message) continue;
3640
+ sanitized ??= messages.slice();
3641
+ sanitized[index] = next;
3642
+ }
3643
+ return sanitized ?? messages;
3644
+ }
3645
+
3453
3646
  // src/stream.ts
3454
3647
  var GLM_CODING_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
3455
3648
  var KIMI_CODE_USER_AGENT = `kimi-code-cli/${process.env.KIMI_CODE_VERSION ?? "1.0.11"}`;
@@ -3539,6 +3732,28 @@ providerRegistry.register("minimax", {
3539
3732
  serverTools: void 0
3540
3733
  })
3541
3734
  });
3735
+ function localWireModelId(id) {
3736
+ const match = /^local\/[^/]+\/(.+)$/.exec(id);
3737
+ return match?.[1] ?? id;
3738
+ }
3739
+ providerRegistry.register("local", {
3740
+ // Locally hosted OpenAI-compatible servers (Ollama, LM Studio, llama.cpp,
3741
+ // vLLM). There is no default endpoint: the baseUrl comes from the endpoint
3742
+ // credential the discovery layer wrote, so a missing one is a wiring bug, not
3743
+ // something to paper over with a guess at someone else's port.
3744
+ stream: (options) => {
3745
+ if (!options.baseUrl) {
3746
+ throw new EZCoderAIError(
3747
+ "Local provider requires a baseUrl (e.g. http://127.0.0.1:11434/v1). No local endpoint was resolved for this model \u2014 re-scan for local models."
3748
+ );
3749
+ }
3750
+ return streamOpenAI({
3751
+ ...options,
3752
+ model: localWireModelId(options.model),
3753
+ webSearch: false
3754
+ });
3755
+ }
3756
+ });
3542
3757
  function stream(options) {
3543
3758
  const entry = providerRegistry.get(options.provider);
3544
3759
  if (!entry) {
@@ -3549,13 +3764,25 @@ function stream(options) {
3549
3764
  if (options.supportsVideo !== true && messagesContainVideo(options.messages)) {
3550
3765
  throw new VideoUnsupportedError();
3551
3766
  }
3767
+ const wireMessages = stripMessageProvenance(options.messages);
3552
3768
  const messages = clampProviderContextImages(
3553
- options.messages,
3769
+ sanitizeMessagesForWire(wireMessages),
3554
3770
  options.provider,
3555
3771
  options.supportsImages
3556
3772
  );
3557
3773
  return entry.stream(messages === options.messages ? options : { ...options, messages });
3558
3774
  }
3775
+ function stripMessageProvenance(messages) {
3776
+ let stripped;
3777
+ for (let index = 0; index < messages.length; index++) {
3778
+ const message = messages[index];
3779
+ if (!message.provenance) continue;
3780
+ stripped ??= messages.slice();
3781
+ const { provenance: _provenance, ...wireMessage } = message;
3782
+ stripped[index] = wireMessage;
3783
+ }
3784
+ return stripped ?? messages;
3785
+ }
3559
3786
  function messagesContainVideo(messages) {
3560
3787
  for (const msg of messages) {
3561
3788
  if (typeof msg.content === "string" || !Array.isArray(msg.content)) continue;
@@ -3941,8 +4168,10 @@ function registerPalsuProvider(config) {
3941
4168
  environmentSecrets,
3942
4169
  formatError,
3943
4170
  formatErrorForDisplay,
4171
+ hasLoneSurrogate,
3944
4172
  isHardBillingMessage,
3945
4173
  isUsageLimitError,
4174
+ localWireModelId,
3946
4175
  palsuAssistantMessage,
3947
4176
  palsuText,
3948
4177
  palsuThinking,
@@ -3952,9 +4181,13 @@ function registerPalsuProvider(config) {
3952
4181
  redactText,
3953
4182
  redactValue,
3954
4183
  registerPalsuProvider,
4184
+ sanitizeMessagesForWire,
3955
4185
  setProviderDiagnostic,
4186
+ sliceHead,
4187
+ sliceTail,
3956
4188
  stream,
3957
4189
  toAnthropicMessages,
3958
- toOpenAIMessages
4190
+ toOpenAIMessages,
4191
+ toWellFormedText
3959
4192
  });
3960
4193
  //# sourceMappingURL=index.cjs.map