@opencode/ai 0.0.0-reserved → 2.0.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 +879 -2
- package/dist/cache-policy.d.ts +2 -0
- package/dist/cache-policy.js +129 -0
- package/dist/image-client.d.ts +19 -0
- package/dist/image-client.js +28 -0
- package/dist/image.d.ts +110 -0
- package/dist/image.js +103 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +12 -0
- package/dist/llm.d.ts +252 -0
- package/dist/llm.js +74 -0
- package/dist/protocols/alibaba-chat.d.ts +225 -0
- package/dist/protocols/alibaba-chat.js +75 -0
- package/dist/protocols/alibaba-messages.d.ts +350 -0
- package/dist/protocols/alibaba-messages.js +40 -0
- package/dist/protocols/alibaba-responses.d.ts +255 -0
- package/dist/protocols/alibaba-responses.js +80 -0
- package/dist/protocols/anthropic-messages.d.ts +980 -0
- package/dist/protocols/anthropic-messages.js +1460 -0
- package/dist/protocols/bedrock-converse.d.ts +499 -0
- package/dist/protocols/bedrock-converse.js +643 -0
- package/dist/protocols/bedrock-event-stream.d.ts +9 -0
- package/dist/protocols/bedrock-event-stream.js +97 -0
- package/dist/protocols/gemini.d.ts +285 -0
- package/dist/protocols/gemini.js +671 -0
- package/dist/protocols/google-images.d.ts +30 -0
- package/dist/protocols/google-images.js +181 -0
- package/dist/protocols/index.d.ts +12 -0
- package/dist/protocols/index.js +12 -0
- package/dist/protocols/meta-images.d.ts +26 -0
- package/dist/protocols/meta-images.js +89 -0
- package/dist/protocols/meta-messages.d.ts +356 -0
- package/dist/protocols/meta-messages.js +41 -0
- package/dist/protocols/meta-responses.d.ts +473 -0
- package/dist/protocols/meta-responses.js +173 -0
- package/dist/protocols/mistral-chat.d.ts +540 -0
- package/dist/protocols/mistral-chat.js +624 -0
- package/dist/protocols/open-responses-channel.d.ts +25 -0
- package/dist/protocols/open-responses-channel.js +141 -0
- package/dist/protocols/open-responses-continuation.d.ts +16 -0
- package/dist/protocols/open-responses-continuation.js +170 -0
- package/dist/protocols/open-responses.d.ts +1715 -0
- package/dist/protocols/open-responses.js +1228 -0
- package/dist/protocols/openai-chat.d.ts +860 -0
- package/dist/protocols/openai-chat.js +966 -0
- package/dist/protocols/openai-compatible-chat.d.ts +109 -0
- package/dist/protocols/openai-compatible-chat.js +19 -0
- package/dist/protocols/openai-compatible-responses.d.ts +172 -0
- package/dist/protocols/openai-compatible-responses.js +18 -0
- package/dist/protocols/openai-images.d.ts +32 -0
- package/dist/protocols/openai-images.js +183 -0
- package/dist/protocols/openai-responses.d.ts +1389 -0
- package/dist/protocols/openai-responses.js +260 -0
- package/dist/protocols/shared.d.ts +193 -0
- package/dist/protocols/shared.js +290 -0
- package/dist/protocols/utils/bedrock-auth.d.ts +60 -0
- package/dist/protocols/utils/bedrock-auth.js +85 -0
- package/dist/protocols/utils/bedrock-cache.d.ts +19 -0
- package/dist/protocols/utils/bedrock-cache.js +49 -0
- package/dist/protocols/utils/bedrock-media.d.ts +55 -0
- package/dist/protocols/utils/bedrock-media.js +73 -0
- package/dist/protocols/utils/cache.d.ts +6 -0
- package/dist/protocols/utils/cache.js +5 -0
- package/dist/protocols/utils/gemini-tool-schema.d.ts +2 -0
- package/dist/protocols/utils/gemini-tool-schema.js +103 -0
- package/dist/protocols/utils/image-input.d.ts +21 -0
- package/dist/protocols/utils/image-input.js +20 -0
- package/dist/protocols/utils/lifecycle.d.ts +24 -0
- package/dist/protocols/utils/lifecycle.js +72 -0
- package/dist/protocols/utils/meta-image.d.ts +2 -0
- package/dist/protocols/utils/meta-image.js +13 -0
- package/dist/protocols/utils/open-responses-options.d.ts +56 -0
- package/dist/protocols/utils/open-responses-options.js +61 -0
- package/dist/protocols/utils/openai-image.d.ts +5 -0
- package/dist/protocols/utils/openai-image.js +18 -0
- package/dist/protocols/utils/openai-options.d.ts +16 -0
- package/dist/protocols/utils/openai-options.js +14 -0
- package/dist/protocols/utils/partial-json-options.d.ts +62 -0
- package/dist/protocols/utils/partial-json-options.js +52 -0
- package/dist/protocols/utils/partial-json.d.ts +8 -0
- package/dist/protocols/utils/partial-json.js +279 -0
- package/dist/protocols/utils/responses-checkpoint.d.ts +4 -0
- package/dist/protocols/utils/responses-checkpoint.js +107 -0
- package/dist/protocols/utils/responses-compaction.d.ts +4 -0
- package/dist/protocols/utils/responses-compaction.js +129 -0
- package/dist/protocols/utils/responses-hosted-tools.d.ts +26 -0
- package/dist/protocols/utils/responses-hosted-tools.js +32 -0
- package/dist/protocols/utils/tool-schema.d.ts +8 -0
- package/dist/protocols/utils/tool-schema.js +54 -0
- package/dist/protocols/utils/tool-stream.d.ts +710 -0
- package/dist/protocols/utils/tool-stream.js +155 -0
- package/dist/protocols/xai-images.d.ts +26 -0
- package/dist/protocols/xai-images.js +106 -0
- package/dist/protocols/xai-responses.d.ts +250 -0
- package/dist/protocols/xai-responses.js +81 -0
- package/dist/protocols/zai-chat.d.ts +202 -0
- package/dist/protocols/zai-chat.js +49 -0
- package/dist/protocols/zai-images.d.ts +22 -0
- package/dist/protocols/zai-images.js +79 -0
- package/dist/protocols/zai-messages.d.ts +344 -0
- package/dist/protocols/zai-messages.js +27 -0
- package/dist/protocols.d.ts +1 -0
- package/dist/protocols.js +1 -0
- package/dist/provider-error.d.ts +15 -0
- package/dist/provider-error.js +125 -0
- package/dist/provider-package.d.ts +15 -0
- package/dist/provider-package.js +1 -0
- package/dist/provider.d.ts +23 -0
- package/dist/provider.js +2 -0
- package/dist/providers/alibaba/chat.d.ts +1 -0
- package/dist/providers/alibaba/chat.js +1 -0
- package/dist/providers/alibaba/messages.d.ts +3 -0
- package/dist/providers/alibaba/messages.js +1 -0
- package/dist/providers/alibaba/responses.d.ts +3 -0
- package/dist/providers/alibaba/responses.js +1 -0
- package/dist/providers/alibaba.d.ts +711 -0
- package/dist/providers/alibaba.js +94 -0
- package/dist/providers/amazon-bedrock/mantle/chat.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle/chat.js +1 -0
- package/dist/providers/amazon-bedrock/mantle/responses.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle/responses.js +1 -0
- package/dist/providers/amazon-bedrock/mantle.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle.js +1 -0
- package/dist/providers/amazon-bedrock-mantle.d.ts +313 -0
- package/dist/providers/amazon-bedrock-mantle.js +79 -0
- package/dist/providers/amazon-bedrock.d.ts +173 -0
- package/dist/providers/amazon-bedrock.js +41 -0
- package/dist/providers/anthropic-compatible.d.ts +309 -0
- package/dist/providers/anthropic-compatible.js +50 -0
- package/dist/providers/anthropic.d.ts +307 -0
- package/dist/providers/anthropic.js +42 -0
- package/dist/providers/azure/chat.d.ts +2 -0
- package/dist/providers/azure/chat.js +1 -0
- package/dist/providers/azure/responses.d.ts +2 -0
- package/dist/providers/azure/responses.js +1 -0
- package/dist/providers/azure.d.ts +598 -0
- package/dist/providers/azure.js +115 -0
- package/dist/providers/baseten.d.ts +228 -0
- package/dist/providers/baseten.js +38 -0
- package/dist/providers/cerebras.d.ts +227 -0
- package/dist/providers/cerebras.js +40 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +237 -0
- package/dist/providers/cloudflare-ai-gateway.js +65 -0
- package/dist/providers/cloudflare-workers-ai.d.ts +231 -0
- package/dist/providers/cloudflare-workers-ai.js +51 -0
- package/dist/providers/deepinfra.d.ts +227 -0
- package/dist/providers/deepinfra.js +43 -0
- package/dist/providers/deepseek.d.ts +228 -0
- package/dist/providers/deepseek.js +41 -0
- package/dist/providers/fireworks.d.ts +228 -0
- package/dist/providers/fireworks.js +38 -0
- package/dist/providers/google-vertex/chat.d.ts +2 -0
- package/dist/providers/google-vertex/chat.js +1 -0
- package/dist/providers/google-vertex/gemini.d.ts +2 -0
- package/dist/providers/google-vertex/gemini.js +1 -0
- package/dist/providers/google-vertex/messages.d.ts +2 -0
- package/dist/providers/google-vertex/messages.js +1 -0
- package/dist/providers/google-vertex/responses.d.ts +2 -0
- package/dist/providers/google-vertex/responses.js +1 -0
- package/dist/providers/google-vertex-chat.d.ts +132 -0
- package/dist/providers/google-vertex-chat.js +55 -0
- package/dist/providers/google-vertex-messages.d.ts +306 -0
- package/dist/providers/google-vertex-messages.js +75 -0
- package/dist/providers/google-vertex-responses.d.ts +197 -0
- package/dist/providers/google-vertex-responses.js +56 -0
- package/dist/providers/google-vertex-shared.d.ts +22 -0
- package/dist/providers/google-vertex-shared.js +72 -0
- package/dist/providers/google-vertex.d.ts +119 -0
- package/dist/providers/google-vertex.js +98 -0
- package/dist/providers/google.d.ts +114 -0
- package/dist/providers/google.js +42 -0
- package/dist/providers/groq.d.ts +314 -0
- package/dist/providers/groq.js +81 -0
- package/dist/providers/index.d.ts +31 -0
- package/dist/providers/index.js +31 -0
- package/dist/providers/meta/chat.d.ts +2 -0
- package/dist/providers/meta/chat.js +1 -0
- package/dist/providers/meta/messages.d.ts +2 -0
- package/dist/providers/meta/messages.js +1 -0
- package/dist/providers/meta/responses.d.ts +2 -0
- package/dist/providers/meta/responses.js +1 -0
- package/dist/providers/meta.d.ts +636 -0
- package/dist/providers/meta.js +113 -0
- package/dist/providers/minimax/chat.d.ts +4 -0
- package/dist/providers/minimax/chat.js +8 -0
- package/dist/providers/minimax/messages.d.ts +1 -0
- package/dist/providers/minimax/messages.js +1 -0
- package/dist/providers/minimax/responses.d.ts +4 -0
- package/dist/providers/minimax/responses.js +8 -0
- package/dist/providers/minimax.d.ts +598 -0
- package/dist/providers/minimax.js +89 -0
- package/dist/providers/mistral.d.ts +207 -0
- package/dist/providers/mistral.js +28 -0
- package/dist/providers/moonshot/chat.d.ts +1 -0
- package/dist/providers/moonshot/chat.js +1 -0
- package/dist/providers/moonshot/messages.d.ts +4 -0
- package/dist/providers/moonshot/messages.js +8 -0
- package/dist/providers/moonshot/responses.d.ts +4 -0
- package/dist/providers/moonshot/responses.js +8 -0
- package/dist/providers/moonshot.d.ts +596 -0
- package/dist/providers/moonshot.js +90 -0
- package/dist/providers/open-responses-options.d.ts +6 -0
- package/dist/providers/open-responses-options.js +1 -0
- package/dist/providers/openai/chat.d.ts +2 -0
- package/dist/providers/openai/chat.js +1 -0
- package/dist/providers/openai/responses.d.ts +2 -0
- package/dist/providers/openai/responses.js +1 -0
- package/dist/providers/openai-compatible/responses.d.ts +1 -0
- package/dist/providers/openai-compatible/responses.js +1 -0
- package/dist/providers/openai-compatible-responses.d.ts +195 -0
- package/dist/providers/openai-compatible-responses.js +32 -0
- package/dist/providers/openai-compatible.d.ts +130 -0
- package/dist/providers/openai-compatible.js +33 -0
- package/dist/providers/openai-options.d.ts +26 -0
- package/dist/providers/openai-options.js +41 -0
- package/dist/providers/openai.d.ts +404 -0
- package/dist/providers/openai.js +82 -0
- package/dist/providers/openrouter.d.ts +563 -0
- package/dist/providers/openrouter.js +114 -0
- package/dist/providers/togetherai.d.ts +227 -0
- package/dist/providers/togetherai.js +40 -0
- package/dist/providers/xai.d.ts +163 -0
- package/dist/providers/xai.js +88 -0
- package/dist/providers/zai/chat.d.ts +1 -0
- package/dist/providers/zai/chat.js +1 -0
- package/dist/providers/zai-coding-plan/chat.d.ts +1 -0
- package/dist/providers/zai-coding-plan/chat.js +1 -0
- package/dist/providers/zai-coding-plan/messages.d.ts +4 -0
- package/dist/providers/zai-coding-plan/messages.js +8 -0
- package/dist/providers/zai-coding-plan/responses.d.ts +4 -0
- package/dist/providers/zai-coding-plan/responses.js +8 -0
- package/dist/providers/zai-coding-plan.d.ts +577 -0
- package/dist/providers/zai-coding-plan.js +63 -0
- package/dist/providers/zai.d.ts +149 -0
- package/dist/providers/zai.js +53 -0
- package/dist/providers.d.ts +1 -0
- package/dist/providers.js +1 -0
- package/dist/route/auth-options.d.ts +34 -0
- package/dist/route/auth-options.js +14 -0
- package/dist/route/auth.d.ts +51 -0
- package/dist/route/auth.js +87 -0
- package/dist/route/client.d.ts +430 -0
- package/dist/route/client.js +307 -0
- package/dist/route/endpoint.d.ts +28 -0
- package/dist/route/endpoint.js +21 -0
- package/dist/route/executor.d.ts +27 -0
- package/dist/route/executor.js +183 -0
- package/dist/route/framing.d.ts +29 -0
- package/dist/route/framing.js +14 -0
- package/dist/route/index.d.ts +16 -0
- package/dist/route/index.js +9 -0
- package/dist/route/protocol.d.ts +76 -0
- package/dist/route/protocol.js +16 -0
- package/dist/route/transport/http.d.ts +34 -0
- package/dist/route/transport/http.js +68 -0
- package/dist/route/transport/index.d.ts +41 -0
- package/dist/route/transport/index.js +4 -0
- package/dist/route/transport/websocket-channel.d.ts +57 -0
- package/dist/route/transport/websocket-channel.js +1 -0
- package/dist/route/transport/websocket.d.ts +56 -0
- package/dist/route/transport/websocket.js +370 -0
- package/dist/route.d.ts +1 -0
- package/dist/route.js +1 -0
- package/dist/schema/errors.d.ts +170 -0
- package/dist/schema/errors.js +131 -0
- package/dist/schema/events.d.ts +8123 -0
- package/dist/schema/events.js +550 -0
- package/dist/schema/ids.d.ts +17 -0
- package/dist/schema/ids.js +10 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/messages.d.ts +646 -0
- package/dist/schema/messages.js +301 -0
- package/dist/schema/options.d.ts +159 -0
- package/dist/schema/options.js +189 -0
- package/dist/testing.d.ts +1693 -0
- package/dist/testing.js +129 -0
- package/dist/tool-history.d.ts +2 -0
- package/dist/tool-history.js +84 -0
- package/dist/tool-runtime.d.ts +15 -0
- package/dist/tool-runtime.js +62 -0
- package/dist/tool.d.ts +136 -0
- package/dist/tool.js +66 -0
- package/dist/utils/record.d.ts +2 -0
- package/dist/utils/record.js +2 -0
- package/dist/utils/sanitize.d.ts +1 -0
- package/dist/utils/sanitize.js +12 -0
- package/package.json +43 -10
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Adapted from partial-json by the Promplate Dev Team:
|
|
3
|
+
* https://github.com/promplate/partial-json-parser-js
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 Promplate Dev Team
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
* in the Software without restriction, including without limitation the rights
|
|
12
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
* furnished to do so, subject to the following conditions:
|
|
15
|
+
*
|
|
16
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
* copies or substantial portions of the Software.
|
|
18
|
+
*
|
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
* SOFTWARE.
|
|
26
|
+
*/
|
|
27
|
+
import { Schema } from "effect";
|
|
28
|
+
import { Allow } from "./partial-json-options.js";
|
|
29
|
+
export * from "./partial-json-options.js";
|
|
30
|
+
export class PartialJSON extends Error {
|
|
31
|
+
}
|
|
32
|
+
export class MalformedJSON extends Error {
|
|
33
|
+
}
|
|
34
|
+
const decodeJson = Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Unknown));
|
|
35
|
+
/** Parse complete or incomplete JSON, restricted by the supplied partial-value flags. */
|
|
36
|
+
export function parseJSON(jsonString, allowPartial = Allow.ALL) {
|
|
37
|
+
if (typeof jsonString !== "string")
|
|
38
|
+
throw new TypeError(`expecting str, got ${typeof jsonString}`);
|
|
39
|
+
const input = jsonString.trim();
|
|
40
|
+
if (!input)
|
|
41
|
+
throw new Error(`${jsonString} is empty`);
|
|
42
|
+
try {
|
|
43
|
+
return decodeJson(input);
|
|
44
|
+
}
|
|
45
|
+
catch { }
|
|
46
|
+
const repaired = repairJSON(input);
|
|
47
|
+
if (repaired !== input) {
|
|
48
|
+
try {
|
|
49
|
+
return decodeJson(repaired);
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return _parseJSON(input, allowPartial);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (repaired !== input)
|
|
58
|
+
return _parseJSON(repaired, allowPartial);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const repairJSON = (input) => {
|
|
63
|
+
let repaired = "";
|
|
64
|
+
let quoted = false;
|
|
65
|
+
for (let index = 0; index < input.length; index++) {
|
|
66
|
+
const character = input[index];
|
|
67
|
+
if (!quoted) {
|
|
68
|
+
repaired += character;
|
|
69
|
+
if (character === '"')
|
|
70
|
+
quoted = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (character === '"') {
|
|
74
|
+
repaired += character;
|
|
75
|
+
quoted = false;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (character === "\\") {
|
|
79
|
+
const next = input[index + 1];
|
|
80
|
+
if (next === "u" && /^[0-9a-fA-F]{4}$/.test(input.slice(index + 2, index + 6))) {
|
|
81
|
+
repaired += input.slice(index, index + 6);
|
|
82
|
+
index += 5;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (next !== undefined && '"\\/bfnrtu'.includes(next)) {
|
|
86
|
+
repaired += `\\${next}`;
|
|
87
|
+
index++;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
repaired += "\\\\";
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const code = character.charCodeAt(0);
|
|
94
|
+
repaired += code <= 0x1f ? `\\u${code.toString(16).padStart(4, "0")}` : character;
|
|
95
|
+
}
|
|
96
|
+
return repaired;
|
|
97
|
+
};
|
|
98
|
+
const _parseJSON = (jsonString, allow) => {
|
|
99
|
+
const length = jsonString.length;
|
|
100
|
+
let index = 0;
|
|
101
|
+
const markPartialJSON = (message) => {
|
|
102
|
+
throw new PartialJSON(`${message} at position ${index}`);
|
|
103
|
+
};
|
|
104
|
+
const throwMalformedError = (message) => {
|
|
105
|
+
throw new MalformedJSON(`${message} at position ${index}`);
|
|
106
|
+
};
|
|
107
|
+
const parseAny = () => {
|
|
108
|
+
skipBlank();
|
|
109
|
+
if (index >= length)
|
|
110
|
+
markPartialJSON("Unexpected end of input");
|
|
111
|
+
if (jsonString[index] === '"')
|
|
112
|
+
return parseStr();
|
|
113
|
+
if (jsonString[index] === "{")
|
|
114
|
+
return parseObj();
|
|
115
|
+
if (jsonString[index] === "[")
|
|
116
|
+
return parseArr();
|
|
117
|
+
if (jsonString.substring(index, index + 4) === "null" ||
|
|
118
|
+
(Allow.NULL & allow && length - index < 4 && "null".startsWith(jsonString.substring(index)))) {
|
|
119
|
+
index += 4;
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
if (jsonString.substring(index, index + 4) === "true" ||
|
|
123
|
+
(Allow.BOOL & allow && length - index < 4 && "true".startsWith(jsonString.substring(index)))) {
|
|
124
|
+
index += 4;
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
if (jsonString.substring(index, index + 5) === "false" ||
|
|
128
|
+
(Allow.BOOL & allow && length - index < 5 && "false".startsWith(jsonString.substring(index)))) {
|
|
129
|
+
index += 5;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (jsonString.substring(index, index + 8) === "Infinity" ||
|
|
133
|
+
(Allow.INFINITY & allow && length - index < 8 && "Infinity".startsWith(jsonString.substring(index)))) {
|
|
134
|
+
index += 8;
|
|
135
|
+
return Infinity;
|
|
136
|
+
}
|
|
137
|
+
if (jsonString.substring(index, index + 9) === "-Infinity" ||
|
|
138
|
+
(Allow._INFINITY & allow &&
|
|
139
|
+
1 < length - index &&
|
|
140
|
+
length - index < 9 &&
|
|
141
|
+
"-Infinity".startsWith(jsonString.substring(index)))) {
|
|
142
|
+
index += 9;
|
|
143
|
+
return -Infinity;
|
|
144
|
+
}
|
|
145
|
+
if (jsonString.substring(index, index + 3) === "NaN" ||
|
|
146
|
+
(Allow.NAN & allow && length - index < 3 && "NaN".startsWith(jsonString.substring(index)))) {
|
|
147
|
+
index += 3;
|
|
148
|
+
return NaN;
|
|
149
|
+
}
|
|
150
|
+
return parseNum();
|
|
151
|
+
};
|
|
152
|
+
const parseStr = () => {
|
|
153
|
+
const start = index;
|
|
154
|
+
let escape = false;
|
|
155
|
+
index++;
|
|
156
|
+
while (index < length && (jsonString[index] !== '"' || (escape && jsonString[index - 1] === "\\"))) {
|
|
157
|
+
escape = jsonString[index] === "\\" ? !escape : false;
|
|
158
|
+
index++;
|
|
159
|
+
}
|
|
160
|
+
if (jsonString.charAt(index) === '"') {
|
|
161
|
+
try {
|
|
162
|
+
return decodeJson(jsonString.substring(start, ++index - Number(escape)));
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
throwMalformedError(String(error));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (Allow.STR & allow) {
|
|
169
|
+
try {
|
|
170
|
+
return decodeJson(`${jsonString.substring(start, index - Number(escape))}"`);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return decodeJson(`${jsonString.substring(start, jsonString.lastIndexOf("\\"))}"`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return markPartialJSON("Unterminated string literal");
|
|
177
|
+
};
|
|
178
|
+
const parseObj = () => {
|
|
179
|
+
index++;
|
|
180
|
+
skipBlank();
|
|
181
|
+
const object = {};
|
|
182
|
+
try {
|
|
183
|
+
while (jsonString[index] !== "}") {
|
|
184
|
+
skipBlank();
|
|
185
|
+
if (index >= length && Allow.OBJ & allow)
|
|
186
|
+
return object;
|
|
187
|
+
const key = parseStr();
|
|
188
|
+
skipBlank();
|
|
189
|
+
index++;
|
|
190
|
+
try {
|
|
191
|
+
Object.defineProperty(object, key, {
|
|
192
|
+
value: parseAny(),
|
|
193
|
+
enumerable: true,
|
|
194
|
+
configurable: true,
|
|
195
|
+
writable: true,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
if (Allow.OBJ & allow)
|
|
200
|
+
return object;
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
skipBlank();
|
|
204
|
+
if (jsonString[index] === ",")
|
|
205
|
+
index++;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
if (Allow.OBJ & allow)
|
|
210
|
+
return object;
|
|
211
|
+
return markPartialJSON("Expected '}' at end of object");
|
|
212
|
+
}
|
|
213
|
+
index++;
|
|
214
|
+
return object;
|
|
215
|
+
};
|
|
216
|
+
const parseArr = () => {
|
|
217
|
+
index++;
|
|
218
|
+
const array = [];
|
|
219
|
+
try {
|
|
220
|
+
while (jsonString[index] !== "]") {
|
|
221
|
+
array.push(parseAny());
|
|
222
|
+
skipBlank();
|
|
223
|
+
if (jsonString[index] === ",")
|
|
224
|
+
index++;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
if (Allow.ARR & allow)
|
|
229
|
+
return array;
|
|
230
|
+
return markPartialJSON("Expected ']' at end of array");
|
|
231
|
+
}
|
|
232
|
+
index++;
|
|
233
|
+
return array;
|
|
234
|
+
};
|
|
235
|
+
const parseNum = () => {
|
|
236
|
+
if (index === 0) {
|
|
237
|
+
if (jsonString === "-")
|
|
238
|
+
throwMalformedError("Not sure what '-' is");
|
|
239
|
+
try {
|
|
240
|
+
return decodeJson(jsonString);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
if (Allow.NUM & allow) {
|
|
244
|
+
try {
|
|
245
|
+
return decodeJson(jsonString.substring(0, jsonString.lastIndexOf("e")));
|
|
246
|
+
}
|
|
247
|
+
catch { }
|
|
248
|
+
}
|
|
249
|
+
throwMalformedError(String(error));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const start = index;
|
|
253
|
+
if (jsonString[index] === "-")
|
|
254
|
+
index++;
|
|
255
|
+
while (jsonString[index] && !",]}".includes(jsonString[index]))
|
|
256
|
+
index++;
|
|
257
|
+
if (index === length && !(Allow.NUM & allow))
|
|
258
|
+
markPartialJSON("Unterminated number literal");
|
|
259
|
+
try {
|
|
260
|
+
return decodeJson(jsonString.substring(start, index));
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (jsonString.substring(start, index) === "-")
|
|
264
|
+
markPartialJSON("Not sure what '-' is");
|
|
265
|
+
try {
|
|
266
|
+
return decodeJson(jsonString.substring(start, jsonString.lastIndexOf("e")));
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
throwMalformedError(String(error));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const skipBlank = () => {
|
|
274
|
+
while (index < length && " \n\r\t".includes(jsonString[index]))
|
|
275
|
+
index++;
|
|
276
|
+
};
|
|
277
|
+
return parseAny();
|
|
278
|
+
};
|
|
279
|
+
export const parse = parseJSON;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type RouteBody, type TriggerCompactOperation } from "../../route/client.js";
|
|
2
|
+
/** Collect a trigger response before acknowledging transport completion. No generation output escapes. */
|
|
3
|
+
export declare const make: <Body>(body: RouteBody<Body>) => TriggerCompactOperation;
|
|
4
|
+
export * as ResponsesCheckpoint from "./responses-checkpoint.js";
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Effect, Schema, Stream } from "effect";
|
|
2
|
+
import { Route } from "../../route/client.js";
|
|
3
|
+
import { Protocol } from "../../route/protocol.js";
|
|
4
|
+
import { CompactionCheckpointResponse, HttpOptions, LLMEvent, LLMRequest } from "../../schema/index.js";
|
|
5
|
+
import { OpenResponses } from "../open-responses.js";
|
|
6
|
+
import { ProviderShared } from "../shared.js";
|
|
7
|
+
const onOutputItem = Effect.fn("ResponsesCheckpoint.onOutputItem")(function* (state, input) {
|
|
8
|
+
const event = OpenResponses.normalize(state.parser, input);
|
|
9
|
+
const item = event.item;
|
|
10
|
+
if (!item)
|
|
11
|
+
return state;
|
|
12
|
+
const parser = event.output_index === undefined || state.parser.outputItems[event.output_index] === item.id
|
|
13
|
+
? state.parser
|
|
14
|
+
: { ...state.parser, outputItems: { ...state.parser.outputItems, [event.output_index]: item.id } };
|
|
15
|
+
const next = parser === state.parser ? state : { ...state, parser };
|
|
16
|
+
if (event.type === "response.output_item.added" || item.type !== "compaction")
|
|
17
|
+
return next;
|
|
18
|
+
if (event.output_index !== undefined &&
|
|
19
|
+
Object.entries(state.parser.outputItems).some(([index, id]) => id === item.id && Number(index) !== event.output_index))
|
|
20
|
+
return yield* ProviderShared.eventError(parser.id, "Compaction checkpoint appeared in multiple output slots");
|
|
21
|
+
if (!item.encrypted_content)
|
|
22
|
+
return yield* ProviderShared.eventError(parser.id, "Compaction output is missing its encrypted content");
|
|
23
|
+
const previous = state.checkpoints[item.id];
|
|
24
|
+
if (previous && previous.encrypted !== item.encrypted_content)
|
|
25
|
+
return yield* ProviderShared.eventError(parser.id, "Compaction output changed after completion");
|
|
26
|
+
if (previous)
|
|
27
|
+
return next;
|
|
28
|
+
return {
|
|
29
|
+
...next,
|
|
30
|
+
checkpoints: {
|
|
31
|
+
...state.checkpoints,
|
|
32
|
+
[item.id]: { type: "compaction", provider: parser.provider, id: item.id, encrypted: item.encrypted_content },
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
/** Collect a trigger response before acknowledging transport completion. No generation output escapes. */
|
|
37
|
+
export const make = (body) => Effect.fn("ResponsesCheckpoint.execute")(function* (request, executor, options) {
|
|
38
|
+
const source = request.model.route;
|
|
39
|
+
let result;
|
|
40
|
+
// Route registries erase the frame type. The codec validates that boundary before parsing.
|
|
41
|
+
const event = OpenResponses.protocol.stream.event;
|
|
42
|
+
const protocol = Protocol.make({
|
|
43
|
+
id: source.protocol,
|
|
44
|
+
body,
|
|
45
|
+
stream: {
|
|
46
|
+
event,
|
|
47
|
+
initial: (request) => ({
|
|
48
|
+
parser: { id: source.id, provider: request.model.provider, outputItems: {} },
|
|
49
|
+
checkpoints: {},
|
|
50
|
+
}),
|
|
51
|
+
terminal: OpenResponses.terminal,
|
|
52
|
+
step: Effect.fn("ResponsesCheckpoint.step")(function* (state, event) {
|
|
53
|
+
if (event.response?.id && state.responseID && event.response.id !== state.responseID)
|
|
54
|
+
return yield* ProviderShared.eventError(source.id, "Compaction response ID changed during execution");
|
|
55
|
+
if (event.type === "response.created")
|
|
56
|
+
return [{ ...state, responseID: event.response?.id }, []];
|
|
57
|
+
if (event.type === "error" || event.type === "response.failed")
|
|
58
|
+
return yield* OpenResponses.providerFailure(event, "Compaction request failed");
|
|
59
|
+
if (event.type === "response.incomplete")
|
|
60
|
+
return yield* ProviderShared.eventError(source.id, "Compaction response was incomplete");
|
|
61
|
+
if (event.type === "response.output_item.added" || event.type === "response.output_item.done")
|
|
62
|
+
return [yield* onOutputItem(state, event), []];
|
|
63
|
+
if (event.type !== "response.completed")
|
|
64
|
+
return [state, []];
|
|
65
|
+
const responseID = event.response?.id;
|
|
66
|
+
if (!responseID?.trim())
|
|
67
|
+
return yield* ProviderShared.eventError(source.id, "Compaction response is missing its response ID");
|
|
68
|
+
if (event.response?.status !== undefined && event.response.status !== "completed")
|
|
69
|
+
return yield* ProviderShared.eventError(source.id, "Compaction response did not complete successfully");
|
|
70
|
+
let next = state;
|
|
71
|
+
for (const [index, item] of (event.response?.output ?? []).entries()) {
|
|
72
|
+
next = yield* onOutputItem(next, { type: "response.output_item.done", output_index: index, item });
|
|
73
|
+
}
|
|
74
|
+
const checkpoints = Object.values(next.checkpoints);
|
|
75
|
+
const checkpoint = checkpoints[0];
|
|
76
|
+
if (checkpoints.length !== 1 || !checkpoint)
|
|
77
|
+
return yield* ProviderShared.eventError(source.id, "Compaction response must contain exactly one checkpoint");
|
|
78
|
+
result = new CompactionCheckpointResponse({
|
|
79
|
+
checkpoint,
|
|
80
|
+
responseID,
|
|
81
|
+
usage: OpenResponses.mapUsage(event.response?.usage, OpenResponses.metadataKey(request.model)),
|
|
82
|
+
});
|
|
83
|
+
return [next, [LLMEvent.finish({ reason: { normalized: "stop" } })]];
|
|
84
|
+
}),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const route = Route.make({
|
|
88
|
+
id: source.id,
|
|
89
|
+
provider: source.provider,
|
|
90
|
+
providerMetadataKey: source.providerMetadataKey,
|
|
91
|
+
protocol,
|
|
92
|
+
endpoint: source.endpoint,
|
|
93
|
+
auth: source.auth,
|
|
94
|
+
transport: source.transport,
|
|
95
|
+
});
|
|
96
|
+
const native = yield* body.from(request);
|
|
97
|
+
// The body builder already applied and validated overlays. Do not let transport reapply them.
|
|
98
|
+
const preparedRequest = LLMRequest.update(request, {
|
|
99
|
+
http: request.http === undefined ? undefined : new HttpOptions({ ...request.http, body: undefined }),
|
|
100
|
+
});
|
|
101
|
+
const prepared = yield* route.prepareTransport(native, preparedRequest, options);
|
|
102
|
+
yield* route.streamPrepared(prepared, preparedRequest, { http: executor }, options).pipe(Stream.runDrain);
|
|
103
|
+
if (!result)
|
|
104
|
+
return yield* ProviderShared.eventError(source.id, "Compaction response ended without a checkpoint");
|
|
105
|
+
return result;
|
|
106
|
+
});
|
|
107
|
+
export * as ResponsesCheckpoint from "./responses-checkpoint.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CompactOperation } from "../../route/client.js";
|
|
2
|
+
import { OpenResponses } from "../open-responses.js";
|
|
3
|
+
export declare const make: (adapter: OpenResponses.ProviderAdapter) => CompactOperation;
|
|
4
|
+
export * as ResponsesCompaction from "./responses-compaction.js";
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Effect, Schema, Stream } from "effect";
|
|
2
|
+
import { AIError, InvalidProviderOutputError, CompactionPart, CompactionResponse, HttpOptions, LLMRequest, Message, mergeJsonRecords, } from "../../schema/index.js";
|
|
3
|
+
import { Endpoint } from "../../route/endpoint.js";
|
|
4
|
+
import { RequestExecutor } from "../../route/executor.js";
|
|
5
|
+
import { HttpTransport } from "../../route/transport/index.js";
|
|
6
|
+
import { OpenResponses } from "../open-responses.js";
|
|
7
|
+
import { JsonObject, optionalNull, ProviderShared } from "../shared.js";
|
|
8
|
+
const Body = Schema.Struct({
|
|
9
|
+
model: Schema.String,
|
|
10
|
+
input: Schema.Array(Schema.Unknown),
|
|
11
|
+
instructions: optionalNull(Schema.String),
|
|
12
|
+
previous_response_id: optionalNull(Schema.String),
|
|
13
|
+
service_tier: optionalNull(Schema.String),
|
|
14
|
+
prompt_cache_key: optionalNull(Schema.String),
|
|
15
|
+
prompt_cache_retention: optionalNull(Schema.String),
|
|
16
|
+
prompt_cache_options: optionalNull(Schema.Struct({ mode: Schema.optional(Schema.String), ttl: Schema.optional(Schema.String) })),
|
|
17
|
+
});
|
|
18
|
+
const Text = Schema.Union([OpenResponses.OpenResponsesInputText, OpenResponses.OpenResponsesOutputText]);
|
|
19
|
+
const File = Schema.Union([
|
|
20
|
+
Schema.Struct({
|
|
21
|
+
...OpenResponses.OpenResponsesInputFile.fields,
|
|
22
|
+
file_url: Schema.String,
|
|
23
|
+
file_data: Schema.optional(Schema.Never),
|
|
24
|
+
}),
|
|
25
|
+
Schema.Struct({
|
|
26
|
+
...OpenResponses.OpenResponsesInputFile.fields,
|
|
27
|
+
file_data: Schema.String,
|
|
28
|
+
file_url: Schema.optional(Schema.Never),
|
|
29
|
+
}),
|
|
30
|
+
]);
|
|
31
|
+
const MessageFields = {
|
|
32
|
+
type: Schema.Literal("message"),
|
|
33
|
+
id: Schema.optional(Schema.String),
|
|
34
|
+
status: Schema.optional(Schema.String),
|
|
35
|
+
phase: Schema.optional(OpenResponses.MessagePhase),
|
|
36
|
+
};
|
|
37
|
+
const Response = Schema.Struct({
|
|
38
|
+
object: Schema.Literal("response.compaction"),
|
|
39
|
+
output: Schema.Array(Schema.Union([
|
|
40
|
+
OpenResponses.CompactionItem,
|
|
41
|
+
OpenResponses.OpenResponsesReasoningItem,
|
|
42
|
+
Schema.Struct({
|
|
43
|
+
...MessageFields,
|
|
44
|
+
role: Schema.Literal("user"),
|
|
45
|
+
content: Schema.Array(Schema.Union([Text, OpenResponses.OpenResponsesInputImage, File])).check(Schema.isMinLength(1)),
|
|
46
|
+
}),
|
|
47
|
+
Schema.Struct({
|
|
48
|
+
...MessageFields,
|
|
49
|
+
role: Schema.Literal("assistant"),
|
|
50
|
+
content: Schema.Array(Text).check(Schema.isMinLength(1)),
|
|
51
|
+
}),
|
|
52
|
+
])),
|
|
53
|
+
usage: Schema.optional(Schema.StructWithRest(OpenResponses.OpenResponsesUsage, [JsonObject])),
|
|
54
|
+
});
|
|
55
|
+
export const make = (adapter) => Effect.fn("ResponsesCompaction.execute")(function* (request, executor, options) {
|
|
56
|
+
const route = request.model.route;
|
|
57
|
+
const native = yield* OpenResponses.lowerConversation(request, adapter);
|
|
58
|
+
const body = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Body))(mergeJsonRecords({
|
|
59
|
+
...native,
|
|
60
|
+
service_tier: request.providerOptions?.serviceTier,
|
|
61
|
+
prompt_cache_key: ProviderShared.promptCacheKey(request),
|
|
62
|
+
}, request.http?.body));
|
|
63
|
+
const url = Endpoint.render(route.endpoint, { request, body: native });
|
|
64
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}/compact`;
|
|
65
|
+
const parts = yield* HttpTransport.jsonRequestParts({
|
|
66
|
+
request: LLMRequest.update(request, {
|
|
67
|
+
http: request.http === undefined ? undefined : new HttpOptions({ ...request.http, body: undefined }),
|
|
68
|
+
}),
|
|
69
|
+
body,
|
|
70
|
+
endpoint: Endpoint.path(url.toString()),
|
|
71
|
+
auth: route.auth,
|
|
72
|
+
encodeBody: Schema.encodeSync(Schema.fromJsonString(Body)),
|
|
73
|
+
});
|
|
74
|
+
const response = yield* executor.execute(ProviderShared.jsonPost({ url: parts.url, body: parts.bodyText, headers: parts.headers }), options?.http);
|
|
75
|
+
const text = yield* RequestExecutor.responseStream(response).pipe(Stream.decodeText(), Stream.runFold(() => "", (text, chunk) => text + chunk));
|
|
76
|
+
const invalid = (message, cause) => new AIError({
|
|
77
|
+
reason: new InvalidProviderOutputError({
|
|
78
|
+
route: route.id,
|
|
79
|
+
message,
|
|
80
|
+
body: text,
|
|
81
|
+
cause,
|
|
82
|
+
http: RequestExecutor.responseHttp(response),
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
const result = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Response))(text).pipe(Effect.mapError((cause) => invalid("Invalid compaction response", cause)));
|
|
86
|
+
if (!result.output.some((item) => item.type === "compaction"))
|
|
87
|
+
return yield* invalid("Compaction response did not contain a checkpoint");
|
|
88
|
+
return new CompactionResponse({
|
|
89
|
+
replacement: result.output.map((item) => toMessage(item, request.model)),
|
|
90
|
+
usage: OpenResponses.mapUsage(result.usage, OpenResponses.metadataKey(request.model)),
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
function toMessage(item, model) {
|
|
94
|
+
if (item.type === "compaction")
|
|
95
|
+
return Message.assistant(CompactionPart.make({ provider: model.provider, id: item.id ?? undefined, encrypted: item.encrypted_content }));
|
|
96
|
+
const key = OpenResponses.metadataKey(model);
|
|
97
|
+
if (item.type === "reasoning") {
|
|
98
|
+
const summary = item.summary.length ? item.summary : [{ text: "" }];
|
|
99
|
+
return Message.assistant(summary.map((part) => ({
|
|
100
|
+
type: "reasoning",
|
|
101
|
+
text: part.text,
|
|
102
|
+
providerMetadata: { [key]: { itemId: item.id, reasoningEncryptedContent: item.encrypted_content } },
|
|
103
|
+
})));
|
|
104
|
+
}
|
|
105
|
+
return Message.make({
|
|
106
|
+
role: item.role,
|
|
107
|
+
providerMetadata: { [key]: { itemId: item.id, type: item.type, status: item.status, phase: item.phase } },
|
|
108
|
+
content: item.content.map((part) => {
|
|
109
|
+
if (part.type === "input_text" || part.type === "output_text")
|
|
110
|
+
return { type: "text", text: part.text };
|
|
111
|
+
if (part.type === "input_image")
|
|
112
|
+
return {
|
|
113
|
+
type: "media",
|
|
114
|
+
data: part.image_url,
|
|
115
|
+
mediaType: /^data:([^;,]+)/.exec(part.image_url)?.[1] ?? "image/*",
|
|
116
|
+
providerMetadata: part.detail === undefined ? undefined : { [key]: { detail: part.detail } },
|
|
117
|
+
};
|
|
118
|
+
const data = part.file_url === undefined ? part.file_data : part.file_url;
|
|
119
|
+
return {
|
|
120
|
+
type: "media",
|
|
121
|
+
data,
|
|
122
|
+
filename: part.filename,
|
|
123
|
+
mediaType: /^data:([^;,]+)/.exec(data)?.[1] ?? "application/octet-stream",
|
|
124
|
+
providerMetadata: part.detail === undefined ? undefined : { [key]: { detail: part.detail } },
|
|
125
|
+
};
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
export * as ResponsesCompaction from "./responses-compaction.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { type AIError, type ToolResultPart } from "../../schema/index.js";
|
|
3
|
+
import { OpenResponses } from "../open-responses.js";
|
|
4
|
+
export type Item = OpenResponses.OutputItem & {
|
|
5
|
+
readonly status?: string;
|
|
6
|
+
readonly action?: unknown;
|
|
7
|
+
readonly queries?: unknown;
|
|
8
|
+
readonly results?: unknown;
|
|
9
|
+
readonly code?: string;
|
|
10
|
+
readonly container_id?: string;
|
|
11
|
+
readonly outputs?: unknown;
|
|
12
|
+
readonly server_label?: string;
|
|
13
|
+
readonly output?: unknown;
|
|
14
|
+
readonly result?: string;
|
|
15
|
+
readonly output_format?: "png" | "jpeg" | "webp";
|
|
16
|
+
readonly error?: unknown;
|
|
17
|
+
};
|
|
18
|
+
export interface Definition {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly input: (item: Item) => unknown;
|
|
21
|
+
readonly result?: (item: Item) => Effect.Effect<ToolResultPart["result"], AIError>;
|
|
22
|
+
}
|
|
23
|
+
export type Definitions = Readonly<Record<string, Definition>>;
|
|
24
|
+
export declare const isItem: <Tools extends Definitions>(item: OpenResponses.OutputItem, tools: Tools) => item is Item;
|
|
25
|
+
export declare const onDone: (state: OpenResponses.ParserState, item: Item, tools: Definitions) => Effect.Effect<OpenResponses.StepResult, AIError>;
|
|
26
|
+
export * as ResponsesHostedTools from "./responses-hosted-tools.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { LLMEvent } from "../../schema/index.js";
|
|
3
|
+
import { OpenResponses } from "../open-responses.js";
|
|
4
|
+
import { Lifecycle } from "./lifecycle.js";
|
|
5
|
+
export const isItem = (item, tools) => item.type in tools;
|
|
6
|
+
export const onDone = Effect.fn("ResponsesHostedTools.onDone")(function* (state, item, tools) {
|
|
7
|
+
const tool = tools[item.type];
|
|
8
|
+
if (!tool)
|
|
9
|
+
return [state, []];
|
|
10
|
+
const providerMetadata = OpenResponses.providerMetadata(state, { itemId: item.id });
|
|
11
|
+
const events = [];
|
|
12
|
+
const lifecycle = Lifecycle.stepStart(state.lifecycle, events);
|
|
13
|
+
events.push(LLMEvent.toolCall({
|
|
14
|
+
id: item.id,
|
|
15
|
+
name: tool.name,
|
|
16
|
+
input: tool.input(item),
|
|
17
|
+
providerExecuted: true,
|
|
18
|
+
providerMetadata,
|
|
19
|
+
}), LLMEvent.toolResult({
|
|
20
|
+
id: item.id,
|
|
21
|
+
name: tool.name,
|
|
22
|
+
result: tool.result
|
|
23
|
+
? yield* tool.result(item)
|
|
24
|
+
: item.error !== undefined && item.error !== null
|
|
25
|
+
? { type: "error", value: item.error }
|
|
26
|
+
: { type: "json", value: item },
|
|
27
|
+
providerExecuted: true,
|
|
28
|
+
providerMetadata,
|
|
29
|
+
}));
|
|
30
|
+
return [{ ...state, lifecycle }, events];
|
|
31
|
+
});
|
|
32
|
+
export * as ResponsesHostedTools from "./responses-hosted-tools.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { JsonSchema, LanguageModelToolSchemaCompatibility } from "../../schema/index.js";
|
|
2
|
+
export declare const ToolSchemaProjection: {
|
|
3
|
+
readonly gemini: (schema: JsonSchema) => JsonSchema;
|
|
4
|
+
readonly modelCompatibility: (schema: JsonSchema, compatibility: LanguageModelToolSchemaCompatibility | undefined) => JsonSchema;
|
|
5
|
+
readonly moonshot: (schema: JsonSchema) => JsonSchema;
|
|
6
|
+
readonly openAI: (schema: JsonSchema) => JsonSchema;
|
|
7
|
+
readonly responses: (schema: JsonSchema) => JsonSchema;
|
|
8
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { isRecord } from "../../utils/record.js";
|
|
2
|
+
import { GeminiToolSchema } from "./gemini-tool-schema.js";
|
|
3
|
+
const tupleItemsSchema = (items) => {
|
|
4
|
+
const projected = items.map(moonshotNode);
|
|
5
|
+
if (projected.length === 0)
|
|
6
|
+
return {};
|
|
7
|
+
if (projected.length === 1)
|
|
8
|
+
return projected[0];
|
|
9
|
+
return { anyOf: projected };
|
|
10
|
+
};
|
|
11
|
+
const moonshotNode = (schema) => {
|
|
12
|
+
if (Array.isArray(schema))
|
|
13
|
+
return schema.map(moonshotNode);
|
|
14
|
+
if (!isRecord(schema))
|
|
15
|
+
return schema;
|
|
16
|
+
if (typeof schema.$ref === "string")
|
|
17
|
+
return { $ref: schema.$ref };
|
|
18
|
+
return Object.fromEntries(Object.entries(schema).flatMap(([key, value]) => {
|
|
19
|
+
if (key === "items" && Array.isArray(value))
|
|
20
|
+
return [[key, tupleItemsSchema(value)]];
|
|
21
|
+
if (key === "prefixItems") {
|
|
22
|
+
if ("items" in schema)
|
|
23
|
+
return [];
|
|
24
|
+
return [["items", tupleItemsSchema(Array.isArray(value) ? value : [])]];
|
|
25
|
+
}
|
|
26
|
+
if (key === "unevaluatedItems")
|
|
27
|
+
return [];
|
|
28
|
+
return [[key, moonshotNode(value)]];
|
|
29
|
+
}));
|
|
30
|
+
};
|
|
31
|
+
const moonshot = (schema) => {
|
|
32
|
+
const projected = moonshotNode(schema);
|
|
33
|
+
return isRecord(projected) ? projected : {};
|
|
34
|
+
};
|
|
35
|
+
const openAI = (schema) => schema;
|
|
36
|
+
const responses = openAI;
|
|
37
|
+
const gemini = (schema) => GeminiToolSchema.convert(schema) ?? {};
|
|
38
|
+
const modelCompatibility = (schema, compatibility) => {
|
|
39
|
+
if (compatibility === undefined)
|
|
40
|
+
return schema;
|
|
41
|
+
switch (compatibility) {
|
|
42
|
+
case "gemini":
|
|
43
|
+
return gemini(schema);
|
|
44
|
+
case "moonshot":
|
|
45
|
+
return moonshot(schema);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
export const ToolSchemaProjection = {
|
|
49
|
+
gemini,
|
|
50
|
+
modelCompatibility,
|
|
51
|
+
moonshot,
|
|
52
|
+
openAI,
|
|
53
|
+
responses,
|
|
54
|
+
};
|