@bman654/clodex 2.18.1 → 2.18.3

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.1",
349
+ version: "2.18.3",
350
350
  publishConfig: {
351
351
  access: "public"
352
352
  },
@@ -3438,7 +3438,7 @@ function savedStopsAfter(current, assignments) {
3438
3438
  }
3439
3439
 
3440
3440
  // src/patch-transforms.ts
3441
- var PATCH_TRANSFORMS_VERSION = 13;
3441
+ var PATCH_TRANSFORMS_VERSION = 14;
3442
3442
  var NATIVE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
3443
3443
  var BASE_EFFORT_LEVELS = ["low", "medium", "high"];
3444
3444
  function projectNativeEffort(effort) {
@@ -3616,15 +3616,10 @@ function applyClodexPatches(source, config) {
3616
3616
  );
3617
3617
  }
3618
3618
  }
3619
+ const pickerRow = (a) => "{value:" + q(a) + ",label:" + q(a.charAt(0).toUpperCase() + a.slice(1)) + ",description:" + q(displayFor(a, ALIAS_TO_ID[a])) + "}";
3619
3620
  {
3620
3621
  const missing = ALIASES.filter((a) => !new RegExp("value:" + reEsc(q(a))).test(js));
3621
- const entries = missing.map(
3622
- // value = the alias (the name the user types and the binary sends);
3623
- // description = the real model label, e.g. "GPT-5.6 Sol (OpenAI (ChatGPT))".
3624
- // (tweakcc's writeContent round-trips utf8 faithfully — verified — so the
3625
- // old adhoc-patch ASCII-only constraint no longer applies.)
3626
- (a) => "{value:" + q(a) + ",label:" + q(a.charAt(0).toUpperCase() + a.slice(1)) + ",description:" + q(displayFor(a, ALIAS_TO_ID[a])) + "}"
3627
- ).join(",");
3622
+ const entries = missing.map(pickerRow).join(",");
3628
3623
  const injectInto = (options) => missing.length ? "[" + entries + "].forEach(function(_o){if(!" + options + ".some(function(_i){return _i.value===_o.value}))" + options + ".push(_o)});" : "";
3629
3624
  const pickerSite = "PATCH 5: model picker options";
3630
3625
  const modelSelections = [...js.matchAll(/\(([\w$]+)==="opus"\|\|\1==="sonnet"\)/g)];
@@ -3641,6 +3636,25 @@ function applyClodexPatches(source, config) {
3641
3636
  );
3642
3637
  }
3643
3638
  }
3639
+ {
3640
+ const catalogSite = "PATCH 11: catalog picker options";
3641
+ const catalogMarker = "/*ccpatch:picker*/";
3642
+ const catalogAnchor = /function [\w$]+\(([\w$]+),([\w$]+)\)\{let ([\w$]+)=[\w$]+\(\1,\2\),([\w$]+)=\3\?\?[\w$]+\(\1\)(?=[,;])(?=[\s\S]{0,400}ANTHROPIC_CUSTOM_MODEL_OPTION)/;
3643
+ const entryPoints = source.match(new RegExp(catalogAnchor.source, "g"))?.length ?? 0;
3644
+ const rows = ALIASES.map(pickerRow).join(",");
3645
+ if (ALIASES.length === 0) {
3646
+ log13("SKIP", catalogSite, "no aliases configured");
3647
+ } else if (entryPoints !== 1 && !js.includes(catalogMarker)) {
3648
+ log13("FAIL", catalogSite, entryPoints === 0 ? "anchor not found" : "anchor matched " + entryPoints + " times (expected 1)");
3649
+ } else {
3650
+ applyOnce(
3651
+ catalogSite,
3652
+ catalogAnchor,
3653
+ (m, _first, _second, _catalog, options) => m + ",_ccpick=" + catalogMarker + "[" + rows + "].forEach(function(_o){if(!" + options + ".some(function(_i){return _i.value===_o.value}))" + options + ".push(_o)})",
3654
+ { marker: catalogMarker, required: false }
3655
+ );
3656
+ }
3657
+ }
3644
3658
  {
3645
3659
  const safe = (s) => String(s).replace(/`/g, "'").replace(/\$\{/g, "(");
3646
3660
  const listing = IDENTITIES.map(function(i) {
@@ -4147,14 +4161,14 @@ function uniqueMatch(source, name, pattern) {
4147
4161
  }
4148
4162
  return match[0];
4149
4163
  }
4150
- function captureNeedle(source, name, needle) {
4151
- if (countExactOccurrences(source, needle) !== 1) {
4164
+ function captureNeedle(source, name, needle, expected = 1) {
4165
+ if (countExactOccurrences(source, needle) !== expected) {
4152
4166
  throw new Error(`clodex patch: could not capture built-in postcondition: ${name}`);
4153
4167
  }
4154
4168
  return {
4155
4169
  name,
4156
4170
  protectedText: needle,
4157
- occurrences: 1
4171
+ occurrences: expected
4158
4172
  };
4159
4173
  }
4160
4174
  function capturePattern(source, name, pattern) {
@@ -4214,16 +4228,25 @@ function captureBuiltInPatchProofs(source, config, results) {
4214
4228
  ));
4215
4229
  }
4216
4230
  }
4217
- if (protectsResult(results, "PATCH 5: model picker options")) {
4231
+ const pickerSites = [
4232
+ "PATCH 5: model picker options",
4233
+ "PATCH 11: catalog picker options"
4234
+ ].filter((name) => protectsResult(results, name));
4235
+ if (pickerSites.length > 0) {
4218
4236
  for (const { alias, id, display } of aliases) {
4219
4237
  const entry = "{value:" + JSON.stringify(alias) + ",label:" + JSON.stringify(alias.charAt(0).toUpperCase() + alias.slice(1)) + ",description:" + JSON.stringify(display ?? `Custom model (${id})`) + "}";
4220
4238
  proofs.push(captureNeedle(
4221
4239
  source,
4222
- `PATCH 5: model picker options (${alias})`,
4223
- entry
4240
+ `model picker options (${alias})`,
4241
+ entry,
4242
+ pickerSites.length
4224
4243
  ));
4225
4244
  }
4226
4245
  }
4246
+ addPattern(
4247
+ "PATCH 11: catalog picker options",
4248
+ /,_ccpick=\/\*ccpatch:picker\*\/\[[\s\S]*?\]\.forEach\(function\(_o\)\{if\(![\w$]+\.some\(function\(_i\)\{return _i\.value===_o\.value\}\)\)[\w$]+\.push\(_o\)\}\)/
4249
+ );
4227
4250
  addPattern(
4228
4251
  "PATCH 7: per-model context window",
4229
4252
  /\/\*ccpatch:ctx\*\/var _ccw=\(\{[^{}]*\}\)\[[^\]]*\];if\(_ccw!==void 0\)return _ccw;/
@@ -12550,6 +12573,99 @@ function restoreOpenAiThinking(text6, signature, npm) {
12550
12573
  }
12551
12574
  }
12552
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
+
12553
12669
  // src/sdk-adapter.ts
12554
12670
  function sdkTranslationErrorSignature(error) {
12555
12671
  const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
@@ -13264,8 +13380,14 @@ async function streamAnthropicResponse(model, params, modelId, write, log13, obs
13264
13380
  }
13265
13381
  }
13266
13382
  async function generateAnthropicResponse(model, params, modelId, options) {
13267
- let text6;
13268
- let toolCalls;
13383
+ const requiredProps = toolRequiredProps(params.tools);
13384
+ const content = new NonStreamContent();
13385
+ const addToolCall = (tc) => content.push({
13386
+ type: "tool_use",
13387
+ id: encodeToolUseId(tc.toolCallId ?? "", grabRoundTripSignature(tc)),
13388
+ name: tc.toolName,
13389
+ input: representableToolInput(sanitizeToolInput(tc.input ?? {}, requiredProps.get(tc.toolName ?? "")))
13390
+ });
13269
13391
  let finishReason;
13270
13392
  let usage;
13271
13393
  let warnings;
@@ -13287,8 +13409,6 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13287
13409
  )),
13288
13410
  totalTimeoutMs
13289
13411
  );
13290
- const streamedText = [];
13291
- const streamedToolCalls = [];
13292
13412
  let streamedFinishReason = "stop";
13293
13413
  let streamedUsage;
13294
13414
  try {
@@ -13311,17 +13431,11 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13311
13431
  if (part.type === "error") {
13312
13432
  throw part.error instanceof Error || part.error && typeof part.error === "object" ? part.error : new Error(typeof part.error === "string" ? part.error : "Upstream stream failed");
13313
13433
  }
13314
- if (part.type === "text-delta") streamedText.push(part.text ?? "");
13315
- else if (part.type === "tool-call") {
13316
- streamedToolCalls.push({
13317
- toolCallId: part.toolCallId ?? "",
13318
- toolName: part.toolName ?? "",
13319
- input: part.input
13320
- });
13321
- } else if (part.type === "finish") {
13434
+ if (part.type === "tool-call") addToolCall(part);
13435
+ else if (part.type === "finish") {
13322
13436
  streamedFinishReason = part.finishReason ?? streamedFinishReason;
13323
13437
  streamedUsage = part.totalUsage;
13324
- }
13438
+ } else content.add(part);
13325
13439
  }
13326
13440
  if (abortSignal.aborted) throw streamAbortError(abortSignal);
13327
13441
  } finally {
@@ -13330,8 +13444,6 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13330
13444
  clearTimeout(totalTimer);
13331
13445
  if (!forceAbort.signal.aborted) forceAbort.abort();
13332
13446
  }
13333
- text6 = streamedText.join("");
13334
- toolCalls = streamedToolCalls;
13335
13447
  finishReason = streamedFinishReason;
13336
13448
  usage = streamedUsage;
13337
13449
  } else {
@@ -13350,7 +13462,8 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13350
13462
  maxRetries,
13351
13463
  abortSignal: generateAbort.signal
13352
13464
  });
13353
- ({ text: text6, toolCalls, finishReason, usage, warnings } = r);
13465
+ ({ finishReason, usage, warnings } = r);
13466
+ addGeneratedContent(content, r.content, addToolCall);
13354
13467
  } catch (error) {
13355
13468
  if (generateAbort.signal.aborted) throw streamAbortError(generateAbort.signal);
13356
13469
  throw error;
@@ -13362,21 +13475,12 @@ async function generateAnthropicResponse(model, params, modelId, options) {
13362
13475
  }
13363
13476
  reportUnsupportedServiceTier(params, warnings);
13364
13477
  reportPromptTokens({ onPromptTokens: options?.onPromptTokens }, usage);
13365
- const requiredProps = toolRequiredProps(params.tools);
13366
13478
  return {
13367
13479
  id: translatedMessageId(),
13368
13480
  type: "message",
13369
13481
  role: "assistant",
13370
13482
  model: modelId,
13371
- content: [
13372
- ...text6 ? [{ type: "text", text: text6 }] : [],
13373
- ...toolCalls.map((tc) => ({
13374
- type: "tool_use",
13375
- id: encodeToolUseId(tc.toolCallId, grabRoundTripSignature(tc)),
13376
- name: tc.toolName,
13377
- input: representableToolInput(sanitizeToolInput(tc.input ?? {}, requiredProps.get(tc.toolName)))
13378
- }))
13379
- ],
13483
+ content: content.content(),
13380
13484
  stop_reason: finishReason === "tool-calls" ? "tool_use" : "end_turn",
13381
13485
  usage: toAnthropicUsage(usage)
13382
13486
  };