@dbx-tools/shared-model 0.3.25 → 0.3.27
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/package.json +2 -2
- package/src/openai-responses.ts +87 -0
package/package.json
CHANGED
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"zod": "^4.3.6",
|
|
15
|
-
"@dbx-tools/shared-core": "0.3.
|
|
15
|
+
"@dbx-tools/shared-core": "0.3.27"
|
|
16
16
|
},
|
|
17
17
|
"main": "index.ts",
|
|
18
18
|
"license": "UNLICENSED",
|
|
19
19
|
"publishConfig": {
|
|
20
20
|
"access": "public"
|
|
21
21
|
},
|
|
22
|
-
"version": "0.3.
|
|
22
|
+
"version": "0.3.27",
|
|
23
23
|
"types": "index.ts",
|
|
24
24
|
"type": "module",
|
|
25
25
|
"exports": {
|
package/src/openai-responses.ts
CHANGED
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
* - {@link readResponsesOutput} reads the other direction: pull the answer
|
|
27
27
|
* text and citations out of a `response` object returned by an endpoint
|
|
28
28
|
* that speaks Responses natively (the Databricks native web-search tool).
|
|
29
|
+
* - {@link sanitizeResponsesTools} keeps only `function` tools on a Responses
|
|
30
|
+
* request body (for `/open-responses` / Anthropic, which reject Codex
|
|
31
|
+
* built-ins like `web_search`).
|
|
32
|
+
* - {@link sanitizeOpenResponsesInput} rewrites `output_*` content part types
|
|
33
|
+
* in `input` to `input_*` (Open Responses rejects `output_text` in history).
|
|
29
34
|
*
|
|
30
35
|
* Only the surface real clients exercise is translated; unknown fields are
|
|
31
36
|
* ignored rather than rejected, so a newer client degrades instead of breaking.
|
|
@@ -607,3 +612,85 @@ export function readResponsesOutput(payload: Record<string, unknown>): Responses
|
|
|
607
612
|
function str(value: unknown): string {
|
|
608
613
|
return typeof value === "string" ? value.trim() : "";
|
|
609
614
|
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Strip tool types the upstream model doesn't support from a Responses request
|
|
618
|
+
* body, returning a shallow copy safe to forward (the input is not mutated).
|
|
619
|
+
*
|
|
620
|
+
* Clients like the Codex CLI include built-in Responses tools (`web_search`,
|
|
621
|
+
* `local_shell`, `custom`, ...) alongside their `function` tools. Databricks'
|
|
622
|
+
* Open Responses surface for Anthropic/Claude (and other non-OpenAI providers)
|
|
623
|
+
* only accepts `function` tools and hard-errors otherwise:
|
|
624
|
+
* "Anthropic does not support tool type 'web_search'. Only 'function' is supported."
|
|
625
|
+
* Call this before forwarding to `/serving-endpoints/open-responses`. The OpenAI
|
|
626
|
+
* `/serving-endpoints/responses` path should keep built-ins (GPT supports them).
|
|
627
|
+
* If filtering empties the list, `tools` / `tool_choice` / `parallel_tool_calls`
|
|
628
|
+
* are dropped so we never send an empty `tools: []`.
|
|
629
|
+
*/
|
|
630
|
+
export function sanitizeResponsesTools(
|
|
631
|
+
body: Record<string, unknown>,
|
|
632
|
+
): Record<string, unknown> {
|
|
633
|
+
if (!Array.isArray(body.tools) || body.tools.length === 0) return body;
|
|
634
|
+
const fnTools = body.tools.filter(
|
|
635
|
+
(t) => t && typeof t === "object" && (t as Record<string, unknown>).type === "function",
|
|
636
|
+
);
|
|
637
|
+
if (fnTools.length === body.tools.length) return body; // nothing to strip
|
|
638
|
+
const next: Record<string, unknown> = { ...body };
|
|
639
|
+
if (fnTools.length > 0) {
|
|
640
|
+
next.tools = fnTools;
|
|
641
|
+
} else {
|
|
642
|
+
delete next.tools;
|
|
643
|
+
delete next.tool_choice;
|
|
644
|
+
delete next.parallel_tool_calls;
|
|
645
|
+
}
|
|
646
|
+
return next;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Rewrite Responses `input` content parts so Open Responses will accept them.
|
|
651
|
+
*
|
|
652
|
+
* OpenAI `/responses` (and Codex) replay prior assistant turns with
|
|
653
|
+
* `output_text` / `output_*` content part types. Databricks Open Responses
|
|
654
|
+
* (Claude, Gemini, …) only allows input-side types:
|
|
655
|
+
* "Open Responses input content part type 'output_text' is not supported.
|
|
656
|
+
* Supported: input_text, input_image, input_file, input_audio."
|
|
657
|
+
* Map every `output_<kind>` part to `input_<kind>` (shallow copy; no mutation).
|
|
658
|
+
* Call together with {@link sanitizeResponsesTools} before forwarding to
|
|
659
|
+
* `/serving-endpoints/open-responses`.
|
|
660
|
+
*/
|
|
661
|
+
export function sanitizeOpenResponsesInput(
|
|
662
|
+
body: Record<string, unknown>,
|
|
663
|
+
): Record<string, unknown> {
|
|
664
|
+
if (!Array.isArray(body.input) || body.input.length === 0) return body;
|
|
665
|
+
|
|
666
|
+
let changed = false;
|
|
667
|
+
const input = body.input.map((raw) => {
|
|
668
|
+
if (!raw || typeof raw !== "object") return raw;
|
|
669
|
+
const item = raw as Record<string, unknown>;
|
|
670
|
+
if (!Array.isArray(item.content)) return raw;
|
|
671
|
+
|
|
672
|
+
let partChanged = false;
|
|
673
|
+
const content = item.content.map((part) => {
|
|
674
|
+
if (!part || typeof part !== "object") return part;
|
|
675
|
+
const p = part as Record<string, unknown>;
|
|
676
|
+
if (typeof p.type !== "string" || !p.type.startsWith("output_")) return part;
|
|
677
|
+
partChanged = true;
|
|
678
|
+
return { ...p, type: `input_${p.type.slice("output_".length)}` };
|
|
679
|
+
});
|
|
680
|
+
if (!partChanged) return raw;
|
|
681
|
+
changed = true;
|
|
682
|
+
return { ...item, content };
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
return changed ? { ...body, input } : body;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Full Open Responses request sanitizer: strip non-`function` tools and rewrite
|
|
690
|
+
* `output_*` input content parts. Safe no-op when nothing needs changing.
|
|
691
|
+
*/
|
|
692
|
+
export function sanitizeOpenResponsesRequest(
|
|
693
|
+
body: Record<string, unknown>,
|
|
694
|
+
): Record<string, unknown> {
|
|
695
|
+
return sanitizeOpenResponsesInput(sanitizeResponsesTools(body));
|
|
696
|
+
}
|