ghc-proxy 0.7.1 → 0.7.2

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/main.mjs CHANGED
@@ -7364,7 +7364,7 @@ const checkUsage = defineCommand({
7364
7364
  });
7365
7365
  //#endregion
7366
7366
  //#region src/util/version.ts
7367
- const VERSION = "0.7.1";
7367
+ const VERSION = "0.7.2";
7368
7368
  //#endregion
7369
7369
  //#region src/debug.ts
7370
7370
  function getRuntimeInfo() {
@@ -48617,10 +48617,15 @@ const anthropicMcpToolUseBlockSchema = object({
48617
48617
  input: jsonObjectSchema,
48618
48618
  server_name: string().min(1)
48619
48619
  }).loose();
48620
+ const anthropicDocumentBlockSchema = object({
48621
+ type: literal("document"),
48622
+ source: jsonObjectSchema
48623
+ }).loose();
48620
48624
  const anthropicToolResultContentBlockSchema = union([
48621
48625
  anthropicTextBlockSchema,
48622
48626
  anthropicImageBlockSchema,
48623
- anthropicSearchResultBlockSchema
48627
+ anthropicSearchResultBlockSchema,
48628
+ anthropicDocumentBlockSchema
48624
48629
  ]);
48625
48630
  const anthropicToolResultBlockSchema = object({
48626
48631
  type: literal("tool_result"),
@@ -48648,10 +48653,6 @@ const anthropicServerToolResultBlockSchema = object({
48648
48653
  content: unknown(),
48649
48654
  is_error: boolean().optional()
48650
48655
  }).loose();
48651
- const anthropicDocumentBlockSchema = object({
48652
- type: literal("document"),
48653
- source: jsonObjectSchema
48654
- }).loose();
48655
48656
  const anthropicMessageSchema = union([
48656
48657
  object({
48657
48658
  role: literal("user"),
@@ -49638,6 +49639,31 @@ function normalizeOutputConfigEffort(effort, model) {
49638
49639
  function hasOutputConfigFormat(payload) {
49639
49640
  return payload?.output_config?.format != null;
49640
49641
  }
49642
+ function budgetTokensToEffort(budget) {
49643
+ if (budget >= 24e3) return "high";
49644
+ if (budget >= 8e3) return "medium";
49645
+ return "low";
49646
+ }
49647
+ /**
49648
+ * Models whose upstream `/v1/messages` endpoint only accepts the adaptive
49649
+ * thinking API reject the classic `thinking.type: "enabled"` shape with a 400.
49650
+ * Convert `enabled` → `adaptive` (+ derive `output_config.effort` from the
49651
+ * requested `budget_tokens`) for those models before forwarding. Models that
49652
+ * do not advertise `adaptive_thinking` keep the classic `enabled` shape.
49653
+ *
49654
+ * Must run before `sanitizeOutputConfig` so the derived effort is normalized
49655
+ * against the model's advertised efforts.
49656
+ */
49657
+ function convertEnabledThinkingToAdaptive(payload, model) {
49658
+ if (payload.thinking?.type !== "enabled") return;
49659
+ if (!modelCache.supportsAdaptiveThinking(model)) return;
49660
+ const budget = payload.thinking.budget_tokens;
49661
+ payload.thinking = { type: "adaptive" };
49662
+ if (payload.output_config?.effort == null && modelCache.supportsOutputConfig(model)) payload.output_config = {
49663
+ ...payload.output_config,
49664
+ effort: budgetTokensToEffort(budget)
49665
+ };
49666
+ }
49641
49667
  function sanitizeOutputConfig(payload, model) {
49642
49668
  if (!payload.output_config) return;
49643
49669
  if (!modelCache.supportsOutputConfig(model)) {
@@ -49668,6 +49694,44 @@ const messagesModelChain = composeModelTransforms(rewriteStep, modelPolicyStep);
49668
49694
  const chatCompletionsModelChain = composeModelTransforms(rewriteStep);
49669
49695
  const responsesModelChain = composeModelTransforms(rewriteStep);
49670
49696
  //#endregion
49697
+ //#region src/translator/anthropic/document.ts
49698
+ /** Trimmed text of a `content`-source document part, or undefined when it carries none. */
49699
+ function documentPartText(part) {
49700
+ if (part && typeof part === "object" && typeof part.text === "string") return part.text.trim() || void 0;
49701
+ }
49702
+ /** A short reference identifying a non-text document source, or '' when none is available. */
49703
+ function documentSourceRef(source) {
49704
+ if (typeof source.url === "string") return `: ${source.url}`;
49705
+ if (typeof source.file_id === "string") return `: ${source.file_id}`;
49706
+ if (typeof source.media_type === "string") return `: ${source.media_type}`;
49707
+ return "";
49708
+ }
49709
+ /**
49710
+ * Flatten an Anthropic `document` content block to plain text for translation
49711
+ * paths that cannot carry an attachment (Chat Completions, and the native
49712
+ * mixed-search-result flatten path). Text and content sources inline their
49713
+ * text; file/url/base64 sources have no text to inline, so they degrade to a
49714
+ * reference-labelled placeholder (mirroring `[image omitted: <media_type>]`)
49715
+ * rather than a content-free token. Anthropic allows `document` blocks inside
49716
+ * `tool_result.content` alongside `text`, `image`, and `search_result`.
49717
+ */
49718
+ function formatDocumentBlock(block) {
49719
+ const source = block.source;
49720
+ if (source.type === "text" && typeof source.data === "string") {
49721
+ const text = source.data.trim();
49722
+ return text ? `[document]\n${text}` : "[document]";
49723
+ }
49724
+ if (source.type === "content" && Array.isArray(source.content)) {
49725
+ const parts = [];
49726
+ for (const part of source.content) {
49727
+ const text = documentPartText(part);
49728
+ if (text) parts.push(text);
49729
+ }
49730
+ return parts.length ? `[document]\n${parts.join("\n")}` : "[document]";
49731
+ }
49732
+ return `[document${documentSourceRef(source)}]`;
49733
+ }
49734
+ //#endregion
49671
49735
  //#region src/translator/anthropic/search-result.ts
49672
49736
  function formatSearchResultBlock(block) {
49673
49737
  const content = block.content.map((part) => part.text.trim()).filter(Boolean).join("\n");
@@ -49711,6 +49775,7 @@ function normalizeToolResultContentValue(content) {
49711
49775
  case "text": return textBlock(contentBlock.text);
49712
49776
  case "image": return imageBlock(contentBlock.source.media_type, contentBlock.source.data);
49713
49777
  case "search_result": return textBlock(formatSearchResultBlock(contentBlock));
49778
+ case "document": return textBlock(formatDocumentBlock(contentBlock));
49714
49779
  default: return assertNever(contentBlock);
49715
49780
  }
49716
49781
  });
@@ -51126,6 +51191,12 @@ function convertToolResultContent(content) {
51126
51191
  case "search_result":
51127
51192
  result.push(createTextContent(formatSearchResultBlock(block)));
51128
51193
  break;
51194
+ case "document": {
51195
+ const source = block.source;
51196
+ if (source.type === "file" || source.type === "url" || source.type === "base64") result.push(createDocumentContent(block));
51197
+ else result.push(createTextContent(formatDocumentBlock(block)));
51198
+ break;
51199
+ }
51129
51200
  default: break;
51130
51201
  }
51131
51202
  return result;
@@ -51450,6 +51521,7 @@ function stringifyToolResultContent(content) {
51450
51521
  case "text": return block.text;
51451
51522
  case "image": return `[image omitted: ${block.source.media_type}]`;
51452
51523
  case "search_result": return formatSearchResultBlock(block);
51524
+ case "document": return formatDocumentBlock(block);
51453
51525
  }
51454
51526
  return "";
51455
51527
  }).filter(Boolean).join("\n\n");
@@ -52073,6 +52145,7 @@ const nativeMessagesEntry = {
52073
52145
  name: "native-messages",
52074
52146
  canHandle: (model, ctx) => modelCache.supportsEndpoint(model, "/v1/messages") && !hasOutputConfigFormat(ctx?.anthropicPayload),
52075
52147
  async execute(ctx) {
52148
+ convertEnabledThinkingToAdaptive(ctx.anthropicPayload, ctx.selectedModel);
52076
52149
  filterThinkingBlocksForNativeMessages(ctx.anthropicPayload);
52077
52150
  sanitizeOutputConfig(ctx.anthropicPayload, ctx.selectedModel);
52078
52151
  sanitizeCacheControl(ctx.anthropicPayload);