@bman654/clodex 2.18.2 → 2.18.4

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/cli.js CHANGED
@@ -346,7 +346,7 @@ import { join } from "path";
346
346
  // package.json
347
347
  var package_default = {
348
348
  name: "@bman654/clodex",
349
- version: "2.18.2",
349
+ version: "2.18.4",
350
350
  publishConfig: {
351
351
  access: "public"
352
352
  },
@@ -12573,6 +12573,99 @@ function restoreOpenAiThinking(text6, signature, npm) {
12573
12573
  }
12574
12574
  }
12575
12575
 
12576
+ // src/non-stream-content.ts
12577
+ var NonStreamContent = class {
12578
+ blocks = [];
12579
+ open;
12580
+ add(part) {
12581
+ switch (part.type) {
12582
+ case "reasoning-start":
12583
+ if (openAiReasoningItemId(part) && part.id) {
12584
+ let open2 = this.open;
12585
+ if (open2?.type !== "thinking" || !open2.openAi) {
12586
+ open2 = this.openThinking(new OpenAiThinkingBlock());
12587
+ }
12588
+ open2.openAi.start(part);
12589
+ } else {
12590
+ this.openThinking();
12591
+ }
12592
+ break;
12593
+ case "reasoning-delta": {
12594
+ const open2 = this.open?.type === "thinking" ? this.open : this.openThinking();
12595
+ open2.block.thinking += open2.openAi ? open2.openAi.append(part) : part.text ?? "";
12596
+ break;
12597
+ }
12598
+ case "reasoning-end":
12599
+ if (this.open?.type !== "thinking") break;
12600
+ if (this.open.openAi) this.open.openAi.end(part);
12601
+ else this.open.signature = grabRoundTripSignature(part) ?? this.open.signature;
12602
+ break;
12603
+ case "text-start":
12604
+ this.openText();
12605
+ break;
12606
+ case "text-delta": {
12607
+ const open2 = this.open?.type === "text" ? this.open : this.openText();
12608
+ open2.block.text += part.text ?? "";
12609
+ break;
12610
+ }
12611
+ default:
12612
+ break;
12613
+ }
12614
+ }
12615
+ /** Append a finished block, such as a tool_use, after whatever is open. */
12616
+ push(block) {
12617
+ this.close();
12618
+ this.blocks.push(block);
12619
+ }
12620
+ content() {
12621
+ this.close();
12622
+ return this.blocks;
12623
+ }
12624
+ openThinking(openAi) {
12625
+ this.close();
12626
+ const block = { type: "thinking", thinking: "", signature: "" };
12627
+ const open2 = { type: "thinking", block, openAi };
12628
+ this.open = open2;
12629
+ return open2;
12630
+ }
12631
+ openText() {
12632
+ this.close();
12633
+ const open2 = { type: "text", block: { type: "text", text: "" } };
12634
+ this.open = open2;
12635
+ return open2;
12636
+ }
12637
+ close() {
12638
+ const open2 = this.open;
12639
+ this.open = void 0;
12640
+ if (!open2) return;
12641
+ if (open2.type === "thinking") {
12642
+ open2.block.signature = open2.openAi?.signature() ?? open2.signature ?? "";
12643
+ this.blocks.push(open2.block);
12644
+ } else if (open2.block.text) {
12645
+ this.blocks.push(open2.block);
12646
+ }
12647
+ }
12648
+ };
12649
+ function addGeneratedContent(content, parts, addToolCall) {
12650
+ const firstText = parts.findIndex((part) => part.type === "text");
12651
+ const late = parts.map((part, index) => firstText >= 0 && index > firstText && part.type === "reasoning" && !openAiReasoningItemId(part));
12652
+ const ordered = [...parts.filter((_, i) => late[i]), ...parts.filter((_, i) => !late[i])];
12653
+ ordered.forEach((part, index) => {
12654
+ if (part.type === "reasoning") {
12655
+ const id = `reasoning-${index}`;
12656
+ const { text: text6, providerMetadata } = part;
12657
+ content.add({ type: "reasoning-start", id, providerMetadata });
12658
+ content.add({ type: "reasoning-delta", id, text: text6, providerMetadata });
12659
+ content.add({ type: "reasoning-end", id, providerMetadata });
12660
+ } else if (part.type === "text") {
12661
+ content.add({ type: "text-start" });
12662
+ content.add({ type: "text-delta", text: part.text });
12663
+ } else if (part.type === "tool-call") {
12664
+ addToolCall(part);
12665
+ }
12666
+ });
12667
+ }
12668
+
12576
12669
  // src/sdk-adapter.ts
12577
12670
  function sdkTranslationErrorSignature(error) {
12578
12671
  const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
@@ -12932,8 +13025,8 @@ function translateRequest(body, npm, options) {
12932
13025
  }
12933
13026
  const upstreamModelId2 = options?.reasoningMetadata?.upstreamModelId ?? body.model;
12934
13027
  const supportsExplicitOpenAiCaching = !options?.openAiOAuth && supportsOpenAiPromptCacheBreakpoints(upstreamModelId2);
13028
+ const claudeSessionId = extractClaudeSessionId(body, options?.claudeSessionId);
12935
13029
  if (npm === "@ai-sdk/openai") {
12936
- const claudeSessionId = extractClaudeSessionId(body, options?.claudeSessionId);
12937
13030
  const serviceTier = options?.openAiOAuth ? oauthServiceTier() : void 0;
12938
13031
  providerOptions = deepMergeProviderOptions(providerOptions, {
12939
13032
  openai: {
@@ -12954,7 +13047,17 @@ function translateRequest(body, npm, options) {
12954
13047
  toolChoice: compactRequest ? "none" : translateToolChoice(body.tool_choice),
12955
13048
  maxOutputTokens: options?.openAiOAuth ? void 0 : body.max_tokens,
12956
13049
  temperature: body.temperature,
12957
- providerOptions
13050
+ providerOptions,
13051
+ // OpenRouter derives its own conversation key when none is sent, and routes a
13052
+ // session's requests to one provider when one is. The value needs to be stable
13053
+ // and unique, not recognizable, so the session UUID goes over hashed through
13054
+ // the same key the OpenAI route's prompt_cache_key uses; the system/tools hash
13055
+ // stays the fallback for clients that send no session identity.
13056
+ ...isOpenRouterRoute(npm, options?.reasoningMetadata) ? {
13057
+ headers: {
13058
+ "x-session-id": claudeSessionId ? claudeSessionPromptCacheKey(claudeSessionId) : openAiPromptCacheKey(baseSystem, upstreamTools)
13059
+ }
13060
+ } : {}
12958
13061
  };
12959
13062
  }
12960
13063
  function isOpenAiOAuthRoute(route) {
@@ -13287,8 +13390,14 @@ async function streamAnthropicResponse(model, params, modelId, write, log13, obs
13287
13390
  }
13288
13391
  }
13289
13392
  async function generateAnthropicResponse(model, params, modelId, options) {
13290
- let text6;
13291
- let toolCalls;
13393
+ const requiredProps = toolRequiredProps(params.tools);
13394
+ const content = new NonStreamContent();
13395
+ const addToolCall = (tc) => content.push({
13396
+ type: "tool_use",
13397
+ id: encodeToolUseId(tc.toolCallId ?? "", grabRoundTripSignature(tc)),
13398
+ name: tc.toolName,
13399
+ input: representableToolInput(sanitizeToolInput(tc.input ?? {}, requiredProps.get(tc.toolName ?? "")))
13400
+ });
13292
13401
  let finishReason;
13293
13402
  let usage;
13294
13403
  let warnings;
@@ -13310,8 +13419,6 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13310
13419
  )),
13311
13420
  totalTimeoutMs
13312
13421
  );
13313
- const streamedText = [];
13314
- const streamedToolCalls = [];
13315
13422
  let streamedFinishReason = "stop";
13316
13423
  let streamedUsage;
13317
13424
  try {
@@ -13334,17 +13441,11 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13334
13441
  if (part.type === "error") {
13335
13442
  throw part.error instanceof Error || part.error && typeof part.error === "object" ? part.error : new Error(typeof part.error === "string" ? part.error : "Upstream stream failed");
13336
13443
  }
13337
- if (part.type === "text-delta") streamedText.push(part.text ?? "");
13338
- else if (part.type === "tool-call") {
13339
- streamedToolCalls.push({
13340
- toolCallId: part.toolCallId ?? "",
13341
- toolName: part.toolName ?? "",
13342
- input: part.input
13343
- });
13344
- } else if (part.type === "finish") {
13444
+ if (part.type === "tool-call") addToolCall(part);
13445
+ else if (part.type === "finish") {
13345
13446
  streamedFinishReason = part.finishReason ?? streamedFinishReason;
13346
13447
  streamedUsage = part.totalUsage;
13347
- }
13448
+ } else content.add(part);
13348
13449
  }
13349
13450
  if (abortSignal.aborted) throw streamAbortError(abortSignal);
13350
13451
  } finally {
@@ -13353,8 +13454,6 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13353
13454
  clearTimeout(totalTimer);
13354
13455
  if (!forceAbort.signal.aborted) forceAbort.abort();
13355
13456
  }
13356
- text6 = streamedText.join("");
13357
- toolCalls = streamedToolCalls;
13358
13457
  finishReason = streamedFinishReason;
13359
13458
  usage = streamedUsage;
13360
13459
  } else {
@@ -13373,7 +13472,8 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13373
13472
  maxRetries,
13374
13473
  abortSignal: generateAbort.signal
13375
13474
  });
13376
- ({ text: text6, toolCalls, finishReason, usage, warnings } = r);
13475
+ ({ finishReason, usage, warnings } = r);
13476
+ addGeneratedContent(content, r.content, addToolCall);
13377
13477
  } catch (error) {
13378
13478
  if (generateAbort.signal.aborted) throw streamAbortError(generateAbort.signal);
13379
13479
  throw error;
@@ -13385,21 +13485,12 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13385
13485
  }
13386
13486
  reportUnsupportedServiceTier(params, warnings);
13387
13487
  reportPromptTokens({ onPromptTokens: options?.onPromptTokens }, usage);
13388
- const requiredProps = toolRequiredProps(params.tools);
13389
13488
  return {
13390
13489
  id: translatedMessageId(),
13391
13490
  type: "message",
13392
13491
  role: "assistant",
13393
13492
  model: modelId,
13394
- content: [
13395
- ...text6 ? [{ type: "text", text: text6 }] : [],
13396
- ...toolCalls.map((tc) => ({
13397
- type: "tool_use",
13398
- id: encodeToolUseId(tc.toolCallId, grabRoundTripSignature(tc)),
13399
- name: tc.toolName,
13400
- input: representableToolInput(sanitizeToolInput(tc.input ?? {}, requiredProps.get(tc.toolName)))
13401
- }))
13402
- ],
13493
+ content: content.content(),
13403
13494
  stop_reason: finishReason === "tool-calls" ? "tool_use" : "end_turn",
13404
13495
  usage: toAnthropicUsage(usage)
13405
13496
  };